From dfe72e0db1c080cef3c046d064632ac6486856ff Mon Sep 17 00:00:00 2001 From: Nathan Schulzke Date: Thu, 23 Sep 2021 21:39:47 -0600 Subject: [PATCH 001/111] Enable Mark as Watched in all the other playlist fragments. --- .../fragments/list/BaseListFragment.java | 13 +++++++++++++ .../list/playlist/PlaylistFragment.java | 13 +++++++++++++ .../local/history/HistoryRecordManager.java | 18 +++++------------- .../history/StatisticsPlaylistFragment.java | 14 ++++++++++++++ .../local/playlist/LocalPlaylistFragment.java | 14 ++++++++++++++ 5 files changed, 59 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java index c30b6fc05..6a255b914 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java @@ -378,6 +378,19 @@ public abstract class BaseListFragment extends BaseStateFragment if (KoreUtils.shouldShowPlayWithKodi(context, item.getServiceId())) { entries.add(StreamDialogEntry.play_with_kodi); } + + // show "mark as watched" only when watch history is enabled + final boolean isWatchHistoryEnabled = PreferenceManager + .getDefaultSharedPreferences(context) + .getBoolean(getString(R.string.enable_watch_history_key), false); + if (item.getStreamType() != StreamType.AUDIO_LIVE_STREAM + && item.getStreamType() != StreamType.LIVE_STREAM + && isWatchHistoryEnabled + ) { + entries.add( + StreamDialogEntry.mark_as_watched + ); + } if (!isNullOrEmpty(item.getUploaderUrl())) { entries.add(StreamDialogEntry.show_channel_details); } diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java index f3aa2e306..b03dddc20 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java @@ -15,6 +15,7 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.content.res.AppCompatResources; +import androidx.preference.PreferenceManager; import androidx.viewbinding.ViewBinding; import org.reactivestreams.Subscriber; @@ -176,6 +177,18 @@ public class PlaylistFragment extends BaseListInfoFragment { entries.add(StreamDialogEntry.play_with_kodi); } + // show "mark as watched" only when watch history is enabled + final boolean isWatchHistoryEnabled = PreferenceManager + .getDefaultSharedPreferences(context) + .getBoolean(getString(R.string.enable_watch_history_key), false); + if (item.getStreamType() != StreamType.AUDIO_LIVE_STREAM + && item.getStreamType() != StreamType.LIVE_STREAM + && isWatchHistoryEnabled + ) { + entries.add( + StreamDialogEntry.mark_as_watched + ); + } if (!isNullOrEmpty(item.getUploaderUrl())) { entries.add(StreamDialogEntry.show_channel_details); } diff --git a/app/src/main/java/org/schabi/newpipe/local/history/HistoryRecordManager.java b/app/src/main/java/org/schabi/newpipe/local/history/HistoryRecordManager.java index 823e56d9e..03f04235a 100644 --- a/app/src/main/java/org/schabi/newpipe/local/history/HistoryRecordManager.java +++ b/app/src/main/java/org/schabi/newpipe/local/history/HistoryRecordManager.java @@ -120,19 +120,11 @@ public class HistoryRecordManager { } // Update the stream progress to the full duration of the video - final List states = streamStateTable.getState(streamId) - .blockingFirst(); - if (!states.isEmpty()) { - final StreamStateEntity entity = states.get(0); - entity.setProgressMillis(duration * 1000); - streamStateTable.update(entity); - } else { - final StreamStateEntity entity = new StreamStateEntity( - streamId, - duration * 1000 - ); - streamStateTable.insert(entity); - } + final StreamStateEntity entity = new StreamStateEntity( + streamId, + duration * 1000 + ); + streamStateTable.upsert(entity); // Add a history entry final StreamHistoryEntity latestEntry = streamHistoryTable.getLatestEntry(streamId); diff --git a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java index 9632b47f7..4bb907abc 100644 --- a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java @@ -14,6 +14,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.preference.PreferenceManager; import androidx.viewbinding.ViewBinding; import com.google.android.material.snackbar.Snackbar; @@ -366,6 +367,19 @@ public class StatisticsPlaylistFragment if (KoreUtils.shouldShowPlayWithKodi(context, infoItem.getServiceId())) { entries.add(StreamDialogEntry.play_with_kodi); } + + // show "mark as watched" only when watch history is enabled + final boolean isWatchHistoryEnabled = PreferenceManager + .getDefaultSharedPreferences(context) + .getBoolean(getString(R.string.enable_watch_history_key), false); + if (item.getStreamEntity().getStreamType() != StreamType.AUDIO_LIVE_STREAM + && item.getStreamEntity().getStreamType() != StreamType.LIVE_STREAM + && isWatchHistoryEnabled + ) { + entries.add( + StreamDialogEntry.mark_as_watched + ); + } entries.add(StreamDialogEntry.show_channel_details); StreamDialogEntry.setEnabledEntries(entries); diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index 21da9e571..2e33f3db4 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -19,6 +19,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; +import androidx.preference.PreferenceManager; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; import androidx.viewbinding.ViewBinding; @@ -782,6 +783,19 @@ public class LocalPlaylistFragment extends BaseLocalListFragment Date: Thu, 30 Sep 2021 15:33:20 -0400 Subject: [PATCH 002/111] Update AndroidX Media to 1.4.x --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 1c193ff34..67354fe94 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -208,7 +208,7 @@ dependencies { implementation "androidx.lifecycle:lifecycle-livedata:${androidxLifecycleVersion}" implementation "androidx.lifecycle:lifecycle-viewmodel:${androidxLifecycleVersion}" implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0' - implementation 'androidx.media:media:1.3.1' + implementation 'androidx.media:media:1.4.2' implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.preference:preference:1.1.1' implementation 'androidx.recyclerview:recyclerview:1.1.0' From dc999b4f719f4f7940f88295a1cc3f9479c029b1 Mon Sep 17 00:00:00 2001 From: Kalle Struik Date: Sat, 2 Oct 2021 19:21:25 +0200 Subject: [PATCH 003/111] Add a add to playlist option in the share menu. --- .../org/schabi/newpipe/RouterActivity.java | 59 +++++++++++++++++-- .../local/dialog/PlaylistAppendDialog.java | 28 ++++++++- .../local/dialog/PlaylistCreationDialog.java | 18 ++++++ app/src/main/res/values/settings_keys.xml | 3 + app/src/main/res/values/strings.xml | 1 + 5 files changed, 103 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java index feb9e029d..eba080e62 100644 --- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java +++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java @@ -1,5 +1,8 @@ package org.schabi.newpipe; +import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.AUDIO; +import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.VIDEO; + import android.annotation.SuppressLint; import android.app.IntentService; import android.content.Context; @@ -56,6 +59,8 @@ import org.schabi.newpipe.extractor.playlist.PlaylistInfo; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.VideoStream; import org.schabi.newpipe.ktx.ExceptionUtils; +import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; +import org.schabi.newpipe.local.dialog.PlaylistCreationDialog; import org.schabi.newpipe.player.MainPlayer; import org.schabi.newpipe.player.helper.PlayerHelper; import org.schabi.newpipe.player.helper.PlayerHolder; @@ -69,8 +74,8 @@ import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.ListHelper; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.PermissionHelper; -import org.schabi.newpipe.util.external_communication.ShareUtils; import org.schabi.newpipe.util.ThemeHelper; +import org.schabi.newpipe.util.external_communication.ShareUtils; import org.schabi.newpipe.util.urlfinder.UrlFinder; import org.schabi.newpipe.views.FocusOverlayView; @@ -89,9 +94,6 @@ import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.functions.Consumer; import io.reactivex.rxjava3.schedulers.Schedulers; -import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.AUDIO; -import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.VIDEO; - /** * Get the url from the intent and open it in the chosen preferred player. */ @@ -107,6 +109,7 @@ public class RouterActivity extends AppCompatActivity { protected String currentUrl; private StreamingService currentService; private boolean selectionIsDownload = false; + private boolean selectionIsAddToPlaylist = false; private AlertDialog alertDialogChoice = null; @Override @@ -350,7 +353,7 @@ public class RouterActivity extends AppCompatActivity { .setNegativeButton(R.string.just_once, dialogButtonsClickListener) .setPositiveButton(R.string.always, dialogButtonsClickListener) .setOnDismissListener((dialog) -> { - if (!selectionIsDownload) { + if (!selectionIsDownload && !selectionIsAddToPlaylist) { finish(); } }) @@ -446,6 +449,10 @@ public class RouterActivity extends AppCompatActivity { final AdapterChoiceItem backgroundPlayer = new AdapterChoiceItem( getString(R.string.background_player_key), getString(R.string.background_player), R.drawable.ic_headset); + final AdapterChoiceItem addToPlaylist = new AdapterChoiceItem( + getString(R.string.add_to_playlist_key), getString(R.string.add_to_playlist), + R.drawable.ic_add); + if (linkType == LinkType.STREAM) { if (isExtVideoEnabled) { @@ -482,6 +489,10 @@ public class RouterActivity extends AppCompatActivity { getString(R.string.download), R.drawable.ic_file_download)); + // Add to playlist is not necessary for CHANNEL and PLAYLIST linkType since those can + // not be added to a playlist + returnList.add(addToPlaylist); + } else { returnList.add(showInfo); if (capabilities.contains(VIDEO) && !isExtVideoEnabled) { @@ -547,6 +558,12 @@ public class RouterActivity extends AppCompatActivity { return; } + if (selectedChoiceKey.equals(getString(R.string.add_to_playlist_key))) { + selectionIsAddToPlaylist = true; + openAddToPlaylistDialog(); + return; + } + // stop and bypass FetcherService if InfoScreen was selected since // StreamDetailFragment can fetch data itself if (selectedChoiceKey.equals(getString(R.string.show_info_key))) { @@ -572,6 +589,38 @@ public class RouterActivity extends AppCompatActivity { finish(); } + private void openAddToPlaylistDialog() { + disposables.add(ExtractorHelper.getStreamInfo(currentServiceId, currentUrl, false) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(info -> { + final FragmentManager fm = getSupportFragmentManager(); + final PlaylistAppendDialog playlistAppendDialog = PlaylistAppendDialog + .fromStreamInfo(info); + + playlistAppendDialog.setOnDismissListener(dialog -> finish()); + + PlaylistAppendDialog.onPlaylistFound(getThemeWrapperContext(), + () -> { + playlistAppendDialog.show(fm, "addToPlaylistDialog"); + fm.executePendingTransactions(); + }, + () -> { + final PlaylistCreationDialog playlistCreationDialog = + PlaylistCreationDialog.newInstance(playlistAppendDialog); + playlistCreationDialog.show(fm, "addToPlaylistDialog"); + + fm.executePendingTransactions(); + + }); + + }, throwable -> handleError(this, + new ErrorInfo(throwable, UserAction.REQUESTED_STREAM, + "Tried to add " + currentUrl + " to a playlist", + currentService.getServiceId()))) + ); + } + @SuppressLint("CheckResult") private void openDownloadDialog() { disposables.add(ExtractorHelper.getStreamInfo(currentServiceId, currentUrl, true) diff --git a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistAppendDialog.java b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistAppendDialog.java index 93e1141c7..268848818 100644 --- a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistAppendDialog.java +++ b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistAppendDialog.java @@ -1,6 +1,8 @@ package org.schabi.newpipe.local.dialog; import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnDismissListener; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -40,6 +42,9 @@ public final class PlaylistAppendDialog extends PlaylistDialog { private final CompositeDisposable playlistDisposables = new CompositeDisposable(); + @Nullable + private OnDismissListener onDismissListener = null; + public static Disposable onPlaylistFound( final Context context, final Runnable onSuccess, final Runnable onFailed ) { @@ -83,6 +88,14 @@ public final class PlaylistAppendDialog extends PlaylistDialog { return dialog; } + public void setOnDismissListener(@Nullable final OnDismissListener onDismissListener) { + this.onDismissListener = onDismissListener; + } + + public OnDismissListener getOnDismissListener() { + return onDismissListener; + } + /*////////////////////////////////////////////////////////////////////////// // LifeCycle - Creation //////////////////////////////////////////////////////////////////////////*/ @@ -141,6 +154,14 @@ public final class PlaylistAppendDialog extends PlaylistDialog { playlistAdapter = null; } + @Override + public void onDismiss(@NonNull final DialogInterface dialog) { + super.onDismiss(dialog); + if (onDismissListener != null) { + onDismissListener.onDismiss(dialog); + } + } + /*////////////////////////////////////////////////////////////////////////// // Helper //////////////////////////////////////////////////////////////////////////*/ @@ -150,7 +171,12 @@ public final class PlaylistAppendDialog extends PlaylistDialog { return; } - PlaylistCreationDialog.newInstance(getStreams()).show(getParentFragmentManager(), TAG); + final PlaylistCreationDialog dialog = PlaylistCreationDialog.newInstance(getStreams()); + // Move the dismissListener to the new dialog. + dialog.setOnDismissListener(this.onDismissListener); + this.onDismissListener = null; + + dialog.show(getParentFragmentManager(), TAG); requireDialog().dismiss(); } diff --git a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistCreationDialog.java b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistCreationDialog.java index f48c72d04..55d6cec89 100644 --- a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistCreationDialog.java +++ b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistCreationDialog.java @@ -1,6 +1,8 @@ package org.schabi.newpipe.local.dialog; import android.app.Dialog; +import android.content.DialogInterface; +import android.content.DialogInterface.OnDismissListener; import android.os.Bundle; import android.text.InputType; import android.widget.Toast; @@ -20,6 +22,9 @@ import java.util.List; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; public final class PlaylistCreationDialog extends PlaylistDialog { + @Nullable + private OnDismissListener onDismissListener = null; + public static PlaylistCreationDialog newInstance(final List streams) { final PlaylistCreationDialog dialog = new PlaylistCreationDialog(); dialog.setInfo(streams); @@ -29,9 +34,22 @@ public final class PlaylistCreationDialog extends PlaylistDialog { public static PlaylistCreationDialog newInstance(final PlaylistAppendDialog appendDialog) { final PlaylistCreationDialog dialog = new PlaylistCreationDialog(); dialog.setInfo(appendDialog.getStreams()); + dialog.setOnDismissListener(appendDialog.getOnDismissListener()); return dialog; } + public void setOnDismissListener(@Nullable final OnDismissListener onDismissListener) { + this.onDismissListener = onDismissListener; + } + + @Override + public void onDismiss(@NonNull final DialogInterface dialog) { + super.onDismiss(dialog); + if (onDismissListener != null) { + onDismissListener.onDismiss(dialog); + } + } + /*////////////////////////////////////////////////////////////////////////// // Dialog //////////////////////////////////////////////////////////////////////////*/ diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index 9261dfae1..4d9927b0d 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -360,6 +360,7 @@ popup_player download always_ask_player + add_to_playlist @string/show_info @@ -368,6 +369,7 @@ @string/popup_player @string/download @string/always_ask_open_action + @string/add_to_playlist @string/show_info_key @@ -376,6 +378,7 @@ @string/popup_player_key @string/download_key @string/always_ask_open_action_key + @string/add_to_playlist_key diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 225ccd126..0497d2660 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -433,6 +433,7 @@ Background player Popup player Always ask + Add to playlist Getting info… "Loading requested content" From 6a97942a6e5000bb3c9519985d5f7ff2aac5f199 Mon Sep 17 00:00:00 2001 From: Kalle Struik Date: Sun, 3 Oct 2021 13:27:24 +0200 Subject: [PATCH 004/111] Rename the "append_playlist" string to "add_to_playlist" --- .../main/java/org/schabi/newpipe/util/StreamDialogEntry.java | 2 +- app/src/main/res/layout-large-land/fragment_video_detail.xml | 2 +- app/src/main/res/layout/fragment_video_detail.xml | 2 +- app/src/main/res/menu/menu_play_queue.xml | 2 +- app/src/main/res/menu/menu_play_queue_item.xml | 2 +- app/src/main/res/values-ar/strings.xml | 2 +- app/src/main/res/values-b+ast/strings.xml | 2 +- app/src/main/res/values-b+uz+Latn/strings.xml | 2 +- app/src/main/res/values-b+zh+HANS+CN/strings.xml | 2 +- app/src/main/res/values-be/strings.xml | 2 +- app/src/main/res/values-bg/strings.xml | 2 +- app/src/main/res/values-bn-rBD/strings.xml | 2 +- app/src/main/res/values-bn-rIN/strings.xml | 2 +- app/src/main/res/values-bn/strings.xml | 2 +- app/src/main/res/values-ca/strings.xml | 2 +- app/src/main/res/values-ckb/strings.xml | 2 +- app/src/main/res/values-cs/strings.xml | 2 +- app/src/main/res/values-da/strings.xml | 2 +- app/src/main/res/values-de/strings.xml | 2 +- app/src/main/res/values-el/strings.xml | 2 +- app/src/main/res/values-eo/strings.xml | 2 +- app/src/main/res/values-es/strings.xml | 2 +- app/src/main/res/values-et/strings.xml | 2 +- app/src/main/res/values-eu/strings.xml | 2 +- app/src/main/res/values-fa/strings.xml | 2 +- app/src/main/res/values-fi/strings.xml | 2 +- app/src/main/res/values-fr/strings.xml | 2 +- app/src/main/res/values-gl/strings.xml | 2 +- app/src/main/res/values-he/strings.xml | 2 +- app/src/main/res/values-hi/strings.xml | 2 +- app/src/main/res/values-hr/strings.xml | 2 +- app/src/main/res/values-hu/strings.xml | 2 +- app/src/main/res/values-in/strings.xml | 2 +- app/src/main/res/values-it/strings.xml | 2 +- app/src/main/res/values-ja/strings.xml | 2 +- app/src/main/res/values-kmr/strings.xml | 2 +- app/src/main/res/values-ko/strings.xml | 2 +- app/src/main/res/values-ku/strings.xml | 2 +- app/src/main/res/values-lt/strings.xml | 2 +- app/src/main/res/values-lv/strings.xml | 2 +- app/src/main/res/values-mk/strings.xml | 2 +- app/src/main/res/values-ml/strings.xml | 2 +- app/src/main/res/values-ms/strings.xml | 2 +- app/src/main/res/values-nb-rNO/strings.xml | 2 +- app/src/main/res/values-ne/strings.xml | 2 +- app/src/main/res/values-nl-rBE/strings.xml | 2 +- app/src/main/res/values-nl/strings.xml | 2 +- app/src/main/res/values-pa/strings.xml | 2 +- app/src/main/res/values-pl/strings.xml | 2 +- app/src/main/res/values-pt-rBR/strings.xml | 2 +- app/src/main/res/values-pt-rPT/strings.xml | 2 +- app/src/main/res/values-pt/strings.xml | 2 +- app/src/main/res/values-ro/strings.xml | 2 +- app/src/main/res/values-ru/strings.xml | 2 +- app/src/main/res/values-sc/strings.xml | 2 +- app/src/main/res/values-sk/strings.xml | 2 +- app/src/main/res/values-sl/strings.xml | 2 +- app/src/main/res/values-so/strings.xml | 2 +- app/src/main/res/values-sq/strings.xml | 2 +- app/src/main/res/values-sr/strings.xml | 2 +- app/src/main/res/values-sv/strings.xml | 2 +- app/src/main/res/values-th/strings.xml | 2 +- app/src/main/res/values-tr/strings.xml | 2 +- app/src/main/res/values-uk/strings.xml | 2 +- app/src/main/res/values-ur/strings.xml | 2 +- app/src/main/res/values-vi/strings.xml | 2 +- app/src/main/res/values-zh-rCN/strings.xml | 2 +- app/src/main/res/values-zh-rTW/strings.xml | 2 +- app/src/main/res/values/settings_keys.xml | 4 ++-- app/src/main/res/values/strings.xml | 3 +-- 70 files changed, 71 insertions(+), 72 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java index ec51cc370..11cc4daba 100644 --- a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java +++ b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java @@ -81,7 +81,7 @@ public enum StreamDialogEntry { delete(R.string.delete, (fragment, item) -> { }), // has to be set manually - append_playlist(R.string.append_playlist, (fragment, item) -> { + append_playlist(R.string.add_to_playlist, (fragment, item) -> { final PlaylistAppendDialog d = PlaylistAppendDialog .fromStreamInfoItems(Collections.singletonList(item)); diff --git a/app/src/main/res/layout-large-land/fragment_video_detail.xml b/app/src/main/res/layout-large-land/fragment_video_detail.xml index 3bee4bf9a..d2637110f 100644 --- a/app/src/main/res/layout-large-land/fragment_video_detail.xml +++ b/app/src/main/res/layout-large-land/fragment_video_detail.xml @@ -444,7 +444,7 @@ android:layout_weight="1" android:background="?attr/selectableItemBackgroundBorderless" android:clickable="true" - android:contentDescription="@string/append_playlist" + android:contentDescription="@string/add_to_playlist" android:focusable="true" android:gravity="center" android:paddingVertical="@dimen/detail_control_padding" diff --git a/app/src/main/res/layout/fragment_video_detail.xml b/app/src/main/res/layout/fragment_video_detail.xml index 165c690dd..6853ca7de 100644 --- a/app/src/main/res/layout/fragment_video_detail.xml +++ b/app/src/main/res/layout/fragment_video_detail.xml @@ -430,7 +430,7 @@ android:layout_weight="1" android:background="?attr/selectableItemBackgroundBorderless" android:clickable="true" - android:contentDescription="@string/append_playlist" + android:contentDescription="@string/add_to_playlist" android:focusable="true" android:gravity="center" android:paddingVertical="@dimen/detail_control_padding" diff --git a/app/src/main/res/menu/menu_play_queue.xml b/app/src/main/res/menu/menu_play_queue.xml index 0efadcb66..e8c9ab0ec 100644 --- a/app/src/main/res/menu/menu_play_queue.xml +++ b/app/src/main/res/menu/menu_play_queue.xml @@ -6,7 +6,7 @@ diff --git a/app/src/main/res/menu/menu_play_queue_item.xml b/app/src/main/res/menu/menu_play_queue_item.xml index ebb361be9..be5513708 100644 --- a/app/src/main/res/menu/menu_play_queue_item.xml +++ b/app/src/main/res/menu/menu_play_queue_item.xml @@ -9,7 +9,7 @@ android:title="@string/play_queue_stream_detail" /> + android:title="@string/add_to_playlist" /> diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index f90a82c44..55f41563c 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -235,7 +235,7 @@ إنشاء قائمة تشغيل جديدة إعادة تسمية التسمية - إضافة إلى قائمة التشغيل + إضافة إلى قائمة التشغيل هل تريد حذف قائمة التشغيل هذه؟ تم إنشاء قائمة التشغيل تمت إضافتها إلى قائمة التشغيل diff --git a/app/src/main/res/values-b+ast/strings.xml b/app/src/main/res/values-b+ast/strings.xml index 213ef6f48..19ed896f0 100644 --- a/app/src/main/res/values-b+ast/strings.xml +++ b/app/src/main/res/values-b+ast/strings.xml @@ -132,7 +132,7 @@ Escartar Llista de reproducción nueva Nome - Amestar a una llista de reproducción + Amestar a una llista de reproducción ¿Desanicair esta llista de reproducción\? Ensin sotítulos Axustar diff --git a/app/src/main/res/values-b+uz+Latn/strings.xml b/app/src/main/res/values-b+uz+Latn/strings.xml index 16f28dc09..4d4602daa 100644 --- a/app/src/main/res/values-b+uz+Latn/strings.xml +++ b/app/src/main/res/values-b+uz+Latn/strings.xml @@ -534,7 +534,7 @@ Pleylist eskizi sifatida o\'rnating Unmute rejimi Mute rejimi - Playlist qo\'shish + Playlist qo\'shish Nomi Nomni o\'zgartirish Yangi Playlist diff --git a/app/src/main/res/values-b+zh+HANS+CN/strings.xml b/app/src/main/res/values-b+zh+HANS+CN/strings.xml index 9670c318d..20b01f605 100644 --- a/app/src/main/res/values-b+zh+HANS+CN/strings.xml +++ b/app/src/main/res/values-b+zh+HANS+CN/strings.xml @@ -259,7 +259,7 @@ 新建播放列表 重命名 名称 - 添加至播放列表 + 添加至播放列表 设为播放列表封面 收藏播放列表 删除收藏 diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 46eedac34..4b185b301 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -274,7 +274,7 @@ Стварыць плэйліст Перайменаваць Імя - Дадаць у плэйліст + Дадаць у плэйліст На мініяцюру плэйліста Дадаць плэйліст у закладкі Выдаліць закладку diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index f1edfa124..1c16e225b 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -267,7 +267,7 @@ Нов Плейлист Преименувай Име - Добави Към Плейлист + Добави Към Плейлист Задай като миниатюра на плейлиста Миниатюрата на плейлиста е сменена Премахни отметката diff --git a/app/src/main/res/values-bn-rBD/strings.xml b/app/src/main/res/values-bn-rBD/strings.xml index 6198b926e..d561d52e8 100644 --- a/app/src/main/res/values-bn-rBD/strings.xml +++ b/app/src/main/res/values-bn-rBD/strings.xml @@ -188,7 +188,7 @@ বুকমার্ক মুছুন আন মিউট মিউট - প্লে লিস্ট এ যুক্ত করুন + প্লে লিস্ট এ যুক্ত করুন নাম নতুন প্লে লিস্ট সবসময় জিজ্ঞেস করুন diff --git a/app/src/main/res/values-bn-rIN/strings.xml b/app/src/main/res/values-bn-rIN/strings.xml index 79ce1caaa..831364013 100644 --- a/app/src/main/res/values-bn-rIN/strings.xml +++ b/app/src/main/res/values-bn-rIN/strings.xml @@ -167,7 +167,7 @@ প্লে লিস্ট ডিলিট করতে চান\? আন মিউট মিউট - প্লে লিস্ট এ যুক্ত করুন + প্লে লিস্ট এ যুক্ত করুন সবসময় জিজ্ঞেস করুন ভিডিও প্লেয়ার ড্রয়ার বন্ধ করুন diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index a2f9dec31..11225e706 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -37,7 +37,7 @@ বুকমার্ক মুছুন আন মিউট মিউট - প্লে লিস্ট এ যুক্ত করুন + প্লে লিস্ট এ যুক্ত করুন নাম নাম পাল্টাও নতুন প্লে লিস্ট diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index cbd725c77..5e1d1b201 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -86,7 +86,7 @@ Crea una llista de reproducció Canvia el nom Nom - Afegeix a una llista de reproducció + Afegeix a una llista de reproducció Importa Importa des de Exporta a diff --git a/app/src/main/res/values-ckb/strings.xml b/app/src/main/res/values-ckb/strings.xml index b04048c5f..65af5ffff 100644 --- a/app/src/main/res/values-ckb/strings.xml +++ b/app/src/main/res/values-ckb/strings.xml @@ -403,7 +403,7 @@ ناوفایل دانان لەسەر وێنۆچکەی خشتەلێدان دەربارەی نیوپایپ - زیادکردن بۆ خشتەلێدان + زیادکردن بۆ خشتەلێدان (نەزانراو) زمانی به‌رنامه‌ پەڕەی کیۆسک diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 1791c1794..5a4091db5 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -234,7 +234,7 @@ Nový playlist Přejmenovat Jméno - Přidat do playlistu + Přidat do playlistu Nastavit jako miniaturu playlistu Přidat playlist do záložek Smazat záložku diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 158ec44ec..d59c35edb 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -270,7 +270,7 @@ Ny spilleliste Omdøb Navn - Føj til spilleliste + Føj til spilleliste Slet denne spilleliste\? Spilleliste oprettet Ingen undertekster diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index ca4d3e4d9..105646a16 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -228,7 +228,7 @@ Immer fragen Neue Wiedergabeliste Umbenennen - Zur Wiedergabeliste hinzufügen + Zur Wiedergabeliste hinzufügen Als Vorschaubild der Wiedergabeliste festlegen Lesezeichen entfernen Diese Wiedergabeliste löschen? diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 3d4343195..1775e1ca8 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -270,7 +270,7 @@ Νέα λίστα αναπαραγωγής Μετονομασία Όνομα - Προσθήκη σε λίστα αναπαραγωγής + Προσθήκη σε λίστα αναπαραγωγής Ορισμός ως μικρογραφία λίστας αναπαραγωγής Προσθήκη σελιδοδείκτη στη λίστα Διαγραφή σελιδοδείκτη diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index 50cdf09b3..769272345 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -153,7 +153,7 @@ Nova ludlisto Alinomi Nomo - Aldoni al la ludlisto + Aldoni al la ludlisto Meti kiel bildeto de ludlisto Legosigno Ludlisto Forviŝi Legosignon diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index bb5819ff9..1937ca144 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -231,7 +231,7 @@ Lista de reproducción nueva Cambiar nombre Nombre - Añadir a la lista de reproducción + Añadir a la lista de reproducción Definir como miniatura de lista de reproducción Marcar lista de reproducción Quitar marcador diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index 1321806f5..107c0f624 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -256,7 +256,7 @@ Uus esitusloend Nimeta ümber Nimi - Lisa esitusloendisse + Lisa esitusloendisse Määra esitusloendi pisipildiks Lisa esitusloend järjehoidjaks Eemalda järjehoidja diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 9ca4bfae6..5b8161bf2 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -259,7 +259,7 @@ Erreprodukzio-zerrenda berria Aldatu izena Izena - Gehitu erreprodukzio-zerrendara + Gehitu erreprodukzio-zerrendara Ezarri erreprodukzio-zerrendaren iruditxo gisa Gogoko erreprodukzio-zerrenda Kendu gogokoa diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index e66825b96..58f6cef81 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -217,7 +217,7 @@ فهرست پخش جدید تغییر نام نام - افزودن به سیاههٔ پخش + افزودن به سیاههٔ پخش تنظیم برای تصویر سیاههٔ پخش این فهرست پخش پاک شود؟ فهرست پخش ایجاد شد diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 25ae94dd5..cd6777b5e 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -271,7 +271,7 @@ Uusi soittolista Uudelleennimeä Nimi - Lisää soittolistaan + Lisää soittolistaan Aseta soittolistan kuvakkeeksi Tallenna soittolista kirjanmerkkeihin Poista kirjanmerkki diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index f4226497a..8d27ddff9 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -230,7 +230,7 @@ Nouvelle liste de lecture Renommer Nom - Ajouter à la liste de lecture + Ajouter à la liste de lecture Définir comme miniature de la liste de lecture Enregister la liste de lecture Supprimer le signet diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 185fdda9a..f22ecff86 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -270,7 +270,7 @@ Nova lista de reprodución Renomear Nome - Engadir á lista de reprodución + Engadir á lista de reprodución Estabelecer como miniatura da lista de reprodución Gardar a lista de reprodución nos marcadores Eliminar o marcador diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index 6bc06eb3e..1d054155a 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -240,7 +240,7 @@ רשימת נגינה חדשה שינוי שם שם - הוספה לרשימת נגינה + הוספה לרשימת נגינה הוספת רשימת נגינה לסימניות הסרת סימנייה למחוק רשימת נגינה זו\? diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 6402fc638..5f295bda8 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -230,7 +230,7 @@ नई प्लेलिस्ट नाम बदलें नाम - प्लेलिस्ट में जोड़ें + प्लेलिस्ट में जोड़ें प्लेलिस्ट थंबनेल के रूप में सेट करें प्लेलिस्ट बुकमार्क करें बुकमार्क हटायें diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 88e79451e..1f8ef42a0 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -202,7 +202,7 @@ Nova playlista Preimenuj Ime - Dodaj u playlistu + Dodaj u playlistu Postavi kao minijaturu playliste Zabilježi playlistu Ukloni zabilješku diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index ca1913403..e19fade83 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -254,7 +254,7 @@ Új lejátszási lista Átnevezés Név - Lejátszási listához adás + Lejátszási listához adás Beállítás lejátszási lista indexképeként Könyvjelző törlése Törlődjön ez a lejátszási lista\? diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index b6cd2a7e2..c9fa4cebe 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -229,7 +229,7 @@ Daftar Putar Baru Ubah Nama Nama - Tambah ke daftar putar + Tambah ke daftar putar Atur sebagai thumbnail daftar putar Markah Daftar Putar Hapus Markah diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index af9d529d3..2ee99d452 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -231,7 +231,7 @@ Nuova playlist Rinomina Nome - Aggiungi alla playlist + Aggiungi alla playlist Imposta come copertina della playlist Salva playlist Rimuovi playlist diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 769a31b52..f2540f205 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -221,7 +221,7 @@ 新規プレイリスト 変更 プレイリスト名 - プレイリストに追加 + プレイリストに追加 プレイリストのサムネイルに設定 プレイリストをブックマーク ブックマークを削除 diff --git a/app/src/main/res/values-kmr/strings.xml b/app/src/main/res/values-kmr/strings.xml index 3fa5f2f45..d7ac85dd1 100644 --- a/app/src/main/res/values-kmr/strings.xml +++ b/app/src/main/res/values-kmr/strings.xml @@ -498,7 +498,7 @@ Wekî Thumbnailê Lîsteya Lîsteyê saz bikin Bê deng kirin Bêdeng - Li lîsteyê zêde bike + Li lîsteyê zêde bike Nav Navlêkirin Lîstinê ya nû diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index aaf02a5dd..880c45aee 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -230,7 +230,7 @@ 새로운 재생목록 이름 바꾸기 이름 - 재생목록에 추가 + 재생목록에 추가 재생목록 썸네일로 설정 재생목록 북마크하기 북마크 제거하기 diff --git a/app/src/main/res/values-ku/strings.xml b/app/src/main/res/values-ku/strings.xml index 2cdd31d3b..be2a8086f 100644 --- a/app/src/main/res/values-ku/strings.xml +++ b/app/src/main/res/values-ku/strings.xml @@ -212,7 +212,7 @@ لیستەلێدانی نوێ ناولێنانەوە ناو - زیادکردن بۆ لیستەلێدان + زیادکردن بۆ لیستەلێدان دانان لەسەر وێنۆچکەی لیستەلێدان لیستەلێدانی نیشانەکراو لادانی نیشانەکراو diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index dae17e3ff..d0249568e 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -235,7 +235,7 @@ Naujas grojaraštį Pervadinti Pavadinimas - Pridėti į grojaraštį + Pridėti į grojaraštį Nustatyti kaip grojaraščio miniatiūrą Pridėti grojaraštį į žymes Pašalinti žymes diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml index 01167c426..58d40b61d 100644 --- a/app/src/main/res/values-lv/strings.xml +++ b/app/src/main/res/values-lv/strings.xml @@ -5,7 +5,7 @@ Atskaņošanas saraksts radīts Dzēst atskaņošanas sarakstu\? Iestatīt, kā atskaņošanas saraksta attēlu - Pievienot atskaņošanas sarakstam + Pievienot atskaņošanas sarakstam Vārds Pārsaukt Jauns Atskaņošanas Saraksts diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index c0e16def2..d925e2970 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -248,7 +248,7 @@ Создај нова плејлиста Прекрсти плејлиста Име - Додај во плејлиста + Додај во плејлиста Постави како икона на плејлистата Обележи ја плејлистата Избриши ја белешката diff --git a/app/src/main/res/values-ml/strings.xml b/app/src/main/res/values-ml/strings.xml index 20372cbb9..eb78ca44c 100644 --- a/app/src/main/res/values-ml/strings.xml +++ b/app/src/main/res/values-ml/strings.xml @@ -54,7 +54,7 @@ പ്ലേലിസ്റ്റ് ലഘുചിത്രമായി സജ്ജമാക്കുക അൺമ്യൂട്ട് മ്യൂട്ട് - പ്ലേലിസ്റ്റിലേക്ക് ചേർക്കുക + പ്ലേലിസ്റ്റിലേക്ക് ചേർക്കുക പേര് പേര് മാറ്റുക പുതിയ പ്ലേലിസ്റ്റ് diff --git a/app/src/main/res/values-ms/strings.xml b/app/src/main/res/values-ms/strings.xml index ddf04c1e2..76aef646f 100644 --- a/app/src/main/res/values-ms/strings.xml +++ b/app/src/main/res/values-ms/strings.xml @@ -284,7 +284,7 @@ Senarai Main Baru Namakan semula Nama - Tambah ke Senarai Main + Tambah ke Senarai Main Tetapkan sebagai Thumbnail Senarai Main Menanda senarai main Hapuskan Penanda Halaman diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index b7c370900..9cce73360 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -231,7 +231,7 @@ Ny spilleliste Gi nytt navn Navn - Legg til i spilleliste + Legg til i spilleliste Sett som miniatyrbilde for spilleliste Bokmerk spilleliste Fjern bokmerke diff --git a/app/src/main/res/values-ne/strings.xml b/app/src/main/res/values-ne/strings.xml index f26e8a051..71c9e107f 100644 --- a/app/src/main/res/values-ne/strings.xml +++ b/app/src/main/res/values-ne/strings.xml @@ -292,7 +292,7 @@ नया प्लेलिस्ट पुनः नामकरण नाम - प्लेसूचीमा थप्नुहोस + प्लेसूचीमा थप्नुहोस प्लेलिस्ट थम्बनेल रूपमा सेट बुकमार्क प्लेलिस्ट बुकमार्क हटाउ diff --git a/app/src/main/res/values-nl-rBE/strings.xml b/app/src/main/res/values-nl-rBE/strings.xml index 5190e814e..be7627079 100644 --- a/app/src/main/res/values-nl-rBE/strings.xml +++ b/app/src/main/res/values-nl-rBE/strings.xml @@ -252,7 +252,7 @@ Nieuwe afspeellijst Hernoemen Naam - Toevoegen aan afspeellijst + Toevoegen aan afspeellijst Instellen als miniatuur voor afspeellijst Afspeellijst toevoegen aan bladwijzers Bladwijzer verwijderen diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index f33e5d9cd..b835c68dc 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -231,7 +231,7 @@ Nieuwe afspeellijst Naam wijzigen Naam - Toevoegen aan afspeellijst + Toevoegen aan afspeellijst Instellen als miniatuur voor afspeellijst Afspeellijst toevoegen aan bladwijzers Bladwijzer verwijderen diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml index 75f40b725..8fad329f3 100644 --- a/app/src/main/res/values-pa/strings.xml +++ b/app/src/main/res/values-pa/strings.xml @@ -259,7 +259,7 @@ ਨਵੀਂ ਪਲੇ-ਲਿਸਟ ਨਾਮ ਬਦਲੋ ਨਾਮ - ਪਲੇ-ਸੂਚੀ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ + ਪਲੇ-ਸੂਚੀ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ ਬਤੌਰ ਪਲੇ-ਸੂਚੀ ਥਮਨੇਲ ਸੈੱਟ ਕਰੋ ਬੁੱਕਮਾਰਕ ਪਲੇ-ਲਿਸਟ ਬੁੱਕਮਾਰਕ ਹਟਾਓ diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 0de5abcf0..b4de246eb 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -238,7 +238,7 @@ Nowa playlista Zmień nazwę Nazwa - Dodaj do playlisty + Dodaj do playlisty Ustaw jako miniaturę playlisty Dodaj do ulubionych Usuń z ulubionych diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 1f53db3ce..7c85328d0 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -229,7 +229,7 @@ Nova playlist Renomear Nome - Adicionar à Playlist + Adicionar à Playlist Definir Como Capa da Playlist Favoritar playlist Desfavoritar diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index ad4bb5061..4fa8e4e18 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -504,7 +504,7 @@ Utilizar pesquisa rápida Está prestes a substituir a configuração atual. Mudar para popup - Adicionar à lista de reprodução + Adicionar à lista de reprodução Reproduzir no modo poppup Acha que a fonte demora muito tempo a carregar\? Se sim, tente ativar o carregamento rápido (pode alterar a opção nas definições ou no botão abaixo). \n diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 7b8cd4cdc..c1d95a797 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -242,7 +242,7 @@ A carregar o conteúdo solicitado Nova lista de reprodução Mudar nome - Adicionar à lista de reprodução + Adicionar à lista de reprodução Guardar lista de reprodução como favorita Remover marcador Eliminar esta lista de reprodução\? diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 81c116cc4..fb367eaf0 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -266,7 +266,7 @@ Ștergeți întregul istoric al vizionărilor\? 1 element șters. Playlist nou - Adăugați la playlist + Adăugați la playlist Importare Importați din Exportați în diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 5c019d68e..4cd08d860 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -251,7 +251,7 @@ Новый плейлист Переименовать Имя - В плейлист + В плейлист На миниатюру плейлиста Сохранить плейлист Удалить плейлист diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml index 95ba064a5..1afb7990f 100644 --- a/app/src/main/res/values-sc/strings.xml +++ b/app/src/main/res/values-sc/strings.xml @@ -39,7 +39,7 @@ Imposta che a miniadura de s\'iscalita Allughe su sonu Pone a sa muda - Annanghe a s\'iscalita + Annanghe a s\'iscalita Nùmene Càmbia de nùmene Iscalita noa diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 82655d4ad..3df4ff0af 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -234,7 +234,7 @@ Nový zoznam skladieb Premenovať Názov - Pridať do zoznamu skladieb + Pridať do zoznamu skladieb Nastaviť ako miniatúru zoznamu skladieb Záložka zoznamu skladieb Odstrániť Záložku diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index c6be5581b..dbfef543d 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -247,7 +247,7 @@ Napolni Seznam predvajanja je bil ustvarjen Izbrišem seznam predvajanja\? - Dodaj v seznam predvajanja + Dodaj v seznam predvajanja Preimenuj Nov seznam predvajanja Nalaganje zahtevano vsebino diff --git a/app/src/main/res/values-so/strings.xml b/app/src/main/res/values-so/strings.xml index 5455d728b..bf9e7a768 100644 --- a/app/src/main/res/values-so/strings.xml +++ b/app/src/main/res/values-so/strings.xml @@ -115,7 +115,7 @@ Calaamadso Xulka Ku fadhiisi galka xulka Ka hadalsii - Ku dar xul + Ku dar xul Magaca ka baddal Xul Cusub Soo kicinaya shayga la codsaday diff --git a/app/src/main/res/values-sq/strings.xml b/app/src/main/res/values-sq/strings.xml index f9d2e8cfd..10ab40e69 100644 --- a/app/src/main/res/values-sq/strings.xml +++ b/app/src/main/res/values-sq/strings.xml @@ -183,7 +183,7 @@ Vendose si pamjen statike të listës së luajtjes Me zë Pa zë - Shto në listën e luajtjes + Shto në listën e luajtjes Emri Riemërto Listë Luajtje e Re diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 628f2a100..e27d9e8a8 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -350,7 +350,7 @@ Постави као сличицу листе Упали звук Утишај - Додај на листу + Додај на листу Назив Преименуј Нова листа diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 8eb761329..4fc9778be 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -271,7 +271,7 @@ Ny spellista Byt namn Namn - Lägg till i spellista + Lägg till i spellista Använd som spellistans miniatyrbild Bokmärk spellistan Ta bort bokmärke diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index 22123e517..01946c321 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -270,7 +270,7 @@ เพลย์ลิสต์ใหม่ เปลี่ยนชื่อ ชื่อ - เพิ่มในเพลย์ลิสต์ + เพิ่มในเพลย์ลิสต์ ตั้งเป็นรูปขนาดย่อของเพลย์ลิสต์ เก็บเพลย์ลิสต์ เอาที่คั่นหน้าออก diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index f802302ab..f318de744 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -227,7 +227,7 @@ Yeni Oynatma Listesi Yeniden adlandır Ad - Oynatma listesine ekle + Oynatma listesine ekle Oynatma listesi küçük resmi olarak ayarla Oynatma listesini yer imlerine ekle Yer imini kaldır diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index eae9079c0..c6b1f5bfd 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -240,7 +240,7 @@ Нова добірка Перейменувати Назва - Додати в добірку + Додати в добірку Призначити ескізом добірки Додати добірку до закладок Видалити закладку diff --git a/app/src/main/res/values-ur/strings.xml b/app/src/main/res/values-ur/strings.xml index 0454fc293..1f427504b 100644 --- a/app/src/main/res/values-ur/strings.xml +++ b/app/src/main/res/values-ur/strings.xml @@ -248,7 +248,7 @@ نئی پلے لسٹ نام تبدیل کریں نام - پلے لسٹ میں شامل + پلے لسٹ میں شامل بطور پلے لسٹ انگشتی طے کریں پلے لسٹ کو نشان زد کریں نشان زد حدف کریں diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 83aea33c0..3635aa4b4 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -267,7 +267,7 @@ Tạo playlist mới Đổi tên playlist Tên - Thêm vào danh sách phát + Thêm vào danh sách phát Đặt làm hình thu nhỏ của danh sách phát Đánh dấu playlist này Xóa dấu trang diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index e5180c51e..f6318df0b 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -259,7 +259,7 @@ 新建播放列表 重 命名 名称 - 添加到播放列表 + 添加到播放列表 设为播放列表缩略图 收藏播放列表 删除收藏 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 576f9d480..e5c499119 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -225,7 +225,7 @@ 新的播放清單 重新命名 名稱 - 新增至播放清單 + 新增至播放清單 設為播放清單縮圖 將播放清單加入書籤 移除書籤 diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index 4d9927b0d..7518b2ce8 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -368,8 +368,8 @@ @string/background_player @string/popup_player @string/download - @string/always_ask_open_action @string/add_to_playlist + @string/always_ask_open_action @string/show_info_key @@ -377,8 +377,8 @@ @string/background_player_key @string/popup_player_key @string/download_key - @string/always_ask_open_action_key @string/add_to_playlist_key + @string/always_ask_open_action_key diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0497d2660..c1fc08bc7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -433,14 +433,13 @@ Background player Popup player Always ask - Add to playlist Getting info… "Loading requested content" New Playlist Rename Name - Add to playlist + Add to playlist Mute Unmute Set as playlist thumbnail From ff82c0e585a07c53d0f5ccead05a454e5ed3eb6b Mon Sep 17 00:00:00 2001 From: Kalle Struik Date: Sun, 3 Oct 2021 14:25:50 +0200 Subject: [PATCH 005/111] Set the theme for PlaylistCreationDialog explicitly. --- .../newpipe/local/dialog/PlaylistCreationDialog.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistCreationDialog.java b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistCreationDialog.java index 55d6cec89..b27b7c454 100644 --- a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistCreationDialog.java +++ b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistCreationDialog.java @@ -9,13 +9,14 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.app.AlertDialog.Builder; import org.schabi.newpipe.NewPipeDatabase; import org.schabi.newpipe.R; import org.schabi.newpipe.database.stream.model.StreamEntity; import org.schabi.newpipe.databinding.DialogEditTextBinding; import org.schabi.newpipe.local.playlist.LocalPlaylistManager; +import org.schabi.newpipe.util.ThemeHelper; import java.util.List; @@ -66,7 +67,8 @@ public final class PlaylistCreationDialog extends PlaylistDialog { dialogBinding.dialogEditText.setHint(R.string.name); dialogBinding.dialogEditText.setInputType(InputType.TYPE_CLASS_TEXT); - final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(requireContext()) + final Builder dialogBuilder = new Builder(requireContext(), + ThemeHelper.getDialogTheme(requireContext())) .setTitle(R.string.create_playlist) .setView(dialogBinding.getRoot()) .setCancelable(true) @@ -83,7 +85,6 @@ public final class PlaylistCreationDialog extends PlaylistDialog { .observeOn(AndroidSchedulers.mainThread()) .subscribe(longs -> successToast.show()); }); - return dialogBuilder.create(); } } From 98cc9397cdc9f3574b8db29e954e52551f7ad960 Mon Sep 17 00:00:00 2001 From: Kalle Struik Date: Mon, 4 Oct 2021 21:23:56 +0200 Subject: [PATCH 006/111] Reorder preferred open action menu --- app/src/main/res/values/settings_keys.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index 7518b2ce8..9489ef543 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -359,8 +359,8 @@ background_player popup_player download - always_ask_player add_to_playlist + always_ask_player @string/show_info From fc5e090d036899e7f9d5ab403e4eab196015af89 Mon Sep 17 00:00:00 2001 From: vhouriet Date: Tue, 5 Oct 2021 18:15:36 +0200 Subject: [PATCH 007/111] Fix clicking timestamp shows Toast "Playing in popup mode" Fixes #6662 --- .../main/java/org/schabi/newpipe/util/NavigationHelper.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java index afa826677..6939e652d 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -146,7 +146,9 @@ public final class NavigationHelper { return; } - Toast.makeText(context, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show(); + if (PlayerHolder.getInstance().getType() != PlayerType.POPUP) { + Toast.makeText(context, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show(); + } final Intent intent = getPlayerIntent(context, MainPlayer.class, queue, resumePlayback); intent.putExtra(Player.PLAYER_TYPE, MainPlayer.PlayerType.POPUP.ordinal()); ContextCompat.startForegroundService(context, intent); From f9f59642f34aa4ac34238e44cc23ccf8c4f96eb0 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sat, 9 Oct 2021 16:37:34 +0200 Subject: [PATCH 008/111] Deduplicated drawer code in MainActivity --- .../java/org/schabi/newpipe/MainActivity.java | 117 +++++++----------- 1 file changed, 43 insertions(+), 74 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 5b1cf48e5..3b6fdcc86 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -20,6 +20,8 @@ package org.schabi.newpipe; +import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; + import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -91,8 +93,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; -import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; - public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; @SuppressWarnings("ConstantConditions") @@ -165,7 +165,42 @@ public class MainActivity extends AppCompatActivity { openMiniPlayerUponPlayerStarted(); } - private void setupDrawer() throws Exception { + private void setupDrawer() throws ExtractionException { + addDrawerMenuForCurrentService(); + + toggle = new ActionBarDrawerToggle(this, mainBinding.getRoot(), + toolbarLayoutBinding.toolbar, R.string.drawer_open, R.string.drawer_close); + toggle.syncState(); + mainBinding.getRoot().addDrawerListener(toggle); + mainBinding.getRoot().addDrawerListener(new DrawerLayout.SimpleDrawerListener() { + private int lastService; + + @Override + public void onDrawerOpened(final View drawerView) { + lastService = ServiceHelper.getSelectedServiceId(MainActivity.this); + } + + @Override + public void onDrawerClosed(final View drawerView) { + if (servicesShown) { + toggleServices(); + } + if (lastService != ServiceHelper.getSelectedServiceId(MainActivity.this)) { + ActivityCompat.recreate(MainActivity.this); + } + } + }); + + drawerLayoutBinding.navigation.setNavigationItemSelectedListener(this::drawerItemSelected); + setupDrawerHeader(); + } + + /** + * Builds the drawer menu for the current service. + * + * @throws ExtractionException + */ + private void addDrawerMenuForCurrentService() throws ExtractionException { //Tabs final int currentServiceId = ServiceHelper.getSelectedServiceId(this); final StreamingService service = NewPipe.getService(currentServiceId); @@ -204,32 +239,6 @@ public class MainActivity extends AppCompatActivity { drawerLayoutBinding.navigation.getMenu() .add(R.id.menu_options_about_group, ITEM_ID_ABOUT, ORDER, R.string.tab_about) .setIcon(R.drawable.ic_info_outline); - - toggle = new ActionBarDrawerToggle(this, mainBinding.getRoot(), - toolbarLayoutBinding.toolbar, R.string.drawer_open, R.string.drawer_close); - toggle.syncState(); - mainBinding.getRoot().addDrawerListener(toggle); - mainBinding.getRoot().addDrawerListener(new DrawerLayout.SimpleDrawerListener() { - private int lastService; - - @Override - public void onDrawerOpened(final View drawerView) { - lastService = ServiceHelper.getSelectedServiceId(MainActivity.this); - } - - @Override - public void onDrawerClosed(final View drawerView) { - if (servicesShown) { - toggleServices(); - } - if (lastService != ServiceHelper.getSelectedServiceId(MainActivity.this)) { - ActivityCompat.recreate(MainActivity.this); - } - } - }); - - drawerLayoutBinding.navigation.setNavigationItemSelectedListener(this::drawerItemSelected); - setupDrawerHeader(); } private boolean drawerItemSelected(final MenuItem item) { @@ -337,11 +346,15 @@ public class MainActivity extends AppCompatActivity { drawerLayoutBinding.navigation.getMenu().removeGroup(R.id.menu_tabs_group); drawerLayoutBinding.navigation.getMenu().removeGroup(R.id.menu_options_about_group); + // Show up or down arrow + drawerHeaderBinding.drawerArrow.setImageResource( + servicesShown ? R.drawable.ic_arrow_drop_up : R.drawable.ic_arrow_drop_down); + if (servicesShown) { showServices(); } else { try { - showTabs(); + addDrawerMenuForCurrentService(); } catch (final Exception e) { ErrorActivity.reportUiErrorInSnackbar(this, "Showing main page tabs", e); } @@ -349,8 +362,6 @@ public class MainActivity extends AppCompatActivity { } private void showServices() { - drawerHeaderBinding.drawerArrow.setImageResource(R.drawable.ic_arrow_drop_up); - for (final StreamingService s : NewPipe.getServices()) { final String title = s.getServiceInfo().getName() + (ServiceHelper.isBeta(s) ? " (beta)" : ""); @@ -414,48 +425,6 @@ public class MainActivity extends AppCompatActivity { menuItem.setActionView(spinner); } - private void showTabs() throws ExtractionException { - drawerHeaderBinding.drawerArrow.setImageResource(R.drawable.ic_arrow_drop_down); - - //Tabs - final int currentServiceId = ServiceHelper.getSelectedServiceId(this); - final StreamingService service = NewPipe.getService(currentServiceId); - - int kioskId = 0; - - for (final String ks : service.getKioskList().getAvailableKiosks()) { - drawerLayoutBinding.navigation.getMenu() - .add(R.id.menu_tabs_group, kioskId, ORDER, - KioskTranslator.getTranslatedKioskName(ks, this)) - .setIcon(KioskTranslator.getKioskIcon(ks, this)); - kioskId++; - } - - drawerLayoutBinding.navigation.getMenu() - .add(R.id.menu_tabs_group, ITEM_ID_SUBSCRIPTIONS, ORDER, R.string.tab_subscriptions) - .setIcon(R.drawable.ic_tv); - drawerLayoutBinding.navigation.getMenu() - .add(R.id.menu_tabs_group, ITEM_ID_FEED, ORDER, R.string.fragment_feed_title) - .setIcon(R.drawable.ic_rss_feed); - drawerLayoutBinding.navigation.getMenu() - .add(R.id.menu_tabs_group, ITEM_ID_BOOKMARKS, ORDER, R.string.tab_bookmarks) - .setIcon(R.drawable.ic_bookmark); - drawerLayoutBinding.navigation.getMenu() - .add(R.id.menu_tabs_group, ITEM_ID_DOWNLOADS, ORDER, R.string.downloads) - .setIcon(R.drawable.ic_file_download); - drawerLayoutBinding.navigation.getMenu() - .add(R.id.menu_tabs_group, ITEM_ID_HISTORY, ORDER, R.string.action_history) - .setIcon(R.drawable.ic_history); - - //Settings and About - drawerLayoutBinding.navigation.getMenu() - .add(R.id.menu_options_about_group, ITEM_ID_SETTINGS, ORDER, R.string.settings) - .setIcon(R.drawable.ic_settings); - drawerLayoutBinding.navigation.getMenu() - .add(R.id.menu_options_about_group, ITEM_ID_ABOUT, ORDER, R.string.tab_about) - .setIcon(R.drawable.ic_info_outline); - } - @Override protected void onDestroy() { super.onDestroy(); From 2361d32f75c14cc5b5b827484857bf1d2a0d0b7d Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sat, 9 Oct 2021 18:46:20 +0200 Subject: [PATCH 009/111] Cleaned up PlaylistDialog-related code --- .../org/schabi/newpipe/QueueItemMenuUtil.java | 18 ++-- .../org/schabi/newpipe/RouterActivity.java | 46 +++++---- .../fragments/detail/VideoDetailFragment.java | 14 +-- .../local/dialog/PlaylistAppendDialog.java | 94 ++++--------------- .../local/dialog/PlaylistCreationDialog.java | 34 +------ .../newpipe/local/dialog/PlaylistDialog.java | 75 +++++++++++++-- .../newpipe/player/PlayQueueActivity.java | 17 ++-- .../newpipe/util/StreamDialogEntry.java | 19 ++-- 8 files changed, 147 insertions(+), 170 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java b/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java index 9105ff992..ef24937fe 100644 --- a/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java +++ b/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java @@ -9,8 +9,8 @@ import android.widget.PopupMenu; import androidx.fragment.app.FragmentManager; -import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; -import org.schabi.newpipe.local.dialog.PlaylistCreationDialog; +import org.schabi.newpipe.database.stream.model.StreamEntity; +import org.schabi.newpipe.local.dialog.PlaylistDialog; import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.player.playqueue.PlayQueueItem; import org.schabi.newpipe.util.NavigationHelper; @@ -47,13 +47,15 @@ public final class QueueItemMenuUtil { false); return true; case R.id.menu_item_append_playlist: - final PlaylistAppendDialog d = PlaylistAppendDialog.fromPlayQueueItems( - Collections.singletonList(item) + PlaylistDialog.createCorrespondingDialog( + context, + Collections.singletonList(new StreamEntity(item)), + dialog -> dialog.show( + fragmentManager, + "QueueItemMenuUtil@append_playlist" + ) ); - PlaylistAppendDialog.onPlaylistFound(context, - () -> d.show(fragmentManager, "QueueItemMenuUtil@append_playlist"), - () -> PlaylistCreationDialog.newInstance(d) - .show(fragmentManager, "QueueItemMenuUtil@append_playlist")); + return true; case R.id.menu_item_share: shareText(context, item.getTitle(), item.getUrl(), diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java index eba080e62..e3e97d570 100644 --- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java +++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java @@ -33,6 +33,7 @@ import androidx.core.widget.TextViewCompat; import androidx.fragment.app.FragmentManager; import androidx.preference.PreferenceManager; +import org.schabi.newpipe.database.stream.model.StreamEntity; import org.schabi.newpipe.databinding.ListRadioIconItemBinding; import org.schabi.newpipe.databinding.SingleChoiceDialogViewBinding; import org.schabi.newpipe.download.DownloadDialog; @@ -59,8 +60,7 @@ import org.schabi.newpipe.extractor.playlist.PlaylistInfo; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.VideoStream; import org.schabi.newpipe.ktx.ExceptionUtils; -import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; -import org.schabi.newpipe.local.dialog.PlaylistCreationDialog; +import org.schabi.newpipe.local.dialog.PlaylistDialog; import org.schabi.newpipe.player.MainPlayer; import org.schabi.newpipe.player.helper.PlayerHelper; import org.schabi.newpipe.player.helper.PlayerHolder; @@ -82,6 +82,7 @@ import org.schabi.newpipe.views.FocusOverlayView; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import icepick.Icepick; @@ -593,31 +594,26 @@ public class RouterActivity extends AppCompatActivity { disposables.add(ExtractorHelper.getStreamInfo(currentServiceId, currentUrl, false) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(info -> { - final FragmentManager fm = getSupportFragmentManager(); - final PlaylistAppendDialog playlistAppendDialog = PlaylistAppendDialog - .fromStreamInfo(info); + .subscribe( + info -> PlaylistDialog.createCorrespondingDialog( + getThemeWrapperContext(), + Collections.singletonList(new StreamEntity(info)), + playlistDialog -> { + playlistDialog.setOnDismissListener(dialog -> finish()); - playlistAppendDialog.setOnDismissListener(dialog -> finish()); - - PlaylistAppendDialog.onPlaylistFound(getThemeWrapperContext(), - () -> { - playlistAppendDialog.show(fm, "addToPlaylistDialog"); - fm.executePendingTransactions(); - }, - () -> { - final PlaylistCreationDialog playlistCreationDialog = - PlaylistCreationDialog.newInstance(playlistAppendDialog); - playlistCreationDialog.show(fm, "addToPlaylistDialog"); - - fm.executePendingTransactions(); - - }); - - }, throwable -> handleError(this, - new ErrorInfo(throwable, UserAction.REQUESTED_STREAM, + playlistDialog.show( + this.getSupportFragmentManager(), + "addToPlaylistDialog" + ); + } + ), + throwable -> handleError(this, new ErrorInfo( + throwable, + UserAction.REQUESTED_STREAM, "Tried to add " + currentUrl + " to a playlist", - currentService.getServiceId()))) + currentService.getServiceId()) + ) + ) ); } diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index 5a30ea0f3..bda16849a 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -52,6 +52,7 @@ import com.squareup.picasso.Callback; import org.schabi.newpipe.App; import org.schabi.newpipe.R; +import org.schabi.newpipe.database.stream.model.StreamEntity; import org.schabi.newpipe.databinding.FragmentVideoDetailBinding; import org.schabi.newpipe.download.DownloadDialog; import org.schabi.newpipe.error.ErrorActivity; @@ -73,8 +74,7 @@ import org.schabi.newpipe.fragments.EmptyFragment; import org.schabi.newpipe.fragments.list.comments.CommentsFragment; import org.schabi.newpipe.fragments.list.videos.RelatedItemsFragment; import org.schabi.newpipe.ktx.AnimationType; -import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; -import org.schabi.newpipe.local.dialog.PlaylistCreationDialog; +import org.schabi.newpipe.local.dialog.PlaylistDialog; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.player.MainPlayer; import org.schabi.newpipe.player.MainPlayer.PlayerType; @@ -99,6 +99,7 @@ import org.schabi.newpipe.util.external_communication.KoreUtils; import org.schabi.newpipe.util.external_communication.ShareUtils; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -444,12 +445,11 @@ public final class VideoDetailFragment break; case R.id.detail_controls_playlist_append: if (getFM() != null && currentInfo != null) { - - final PlaylistAppendDialog d = PlaylistAppendDialog.fromStreamInfo(currentInfo); disposables.add( - PlaylistAppendDialog.onPlaylistFound(getContext(), - () -> d.show(getFM(), TAG), - () -> PlaylistCreationDialog.newInstance(d).show(getFM(), TAG) + PlaylistDialog.createCorrespondingDialog( + getContext(), + Collections.singletonList(new StreamEntity(currentInfo)), + dialog -> dialog.show(getFM(), TAG) ) ); } diff --git a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistAppendDialog.java b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistAppendDialog.java index 268848818..2db7e0153 100644 --- a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistAppendDialog.java +++ b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistAppendDialog.java @@ -1,8 +1,5 @@ package org.schabi.newpipe.local.dialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnDismissListener; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -19,20 +16,14 @@ import org.schabi.newpipe.R; import org.schabi.newpipe.database.LocalItem; import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry; import org.schabi.newpipe.database.stream.model.StreamEntity; -import org.schabi.newpipe.extractor.stream.StreamInfo; -import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.local.LocalItemListAdapter; import org.schabi.newpipe.local.playlist.LocalPlaylistManager; -import org.schabi.newpipe.player.playqueue.PlayQueueItem; import org.schabi.newpipe.util.OnClickGesture; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.disposables.CompositeDisposable; -import io.reactivex.rxjava3.disposables.Disposable; public final class PlaylistAppendDialog extends PlaylistDialog { private static final String TAG = PlaylistAppendDialog.class.getCanonicalName(); @@ -42,58 +33,8 @@ public final class PlaylistAppendDialog extends PlaylistDialog { private final CompositeDisposable playlistDisposables = new CompositeDisposable(); - @Nullable - private OnDismissListener onDismissListener = null; - - public static Disposable onPlaylistFound( - final Context context, final Runnable onSuccess, final Runnable onFailed - ) { - final LocalPlaylistManager playlistManager = - new LocalPlaylistManager(NewPipeDatabase.getInstance(context)); - - return playlistManager.hasPlaylists() - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(hasPlaylists -> { - if (hasPlaylists) { - onSuccess.run(); - } else { - onFailed.run(); - } - }); - } - - public static PlaylistAppendDialog fromStreamInfo(final StreamInfo info) { - final PlaylistAppendDialog dialog = new PlaylistAppendDialog(); - dialog.setInfo(Collections.singletonList(new StreamEntity(info))); - return dialog; - } - - public static PlaylistAppendDialog fromStreamInfoItems(final List items) { - final PlaylistAppendDialog dialog = new PlaylistAppendDialog(); - final List entities = new ArrayList<>(items.size()); - for (final StreamInfoItem item : items) { - entities.add(new StreamEntity(item)); - } - dialog.setInfo(entities); - return dialog; - } - - public static PlaylistAppendDialog fromPlayQueueItems(final List items) { - final PlaylistAppendDialog dialog = new PlaylistAppendDialog(); - final List entities = new ArrayList<>(items.size()); - for (final PlayQueueItem item : items) { - entities.add(new StreamEntity(item)); - } - dialog.setInfo(entities); - return dialog; - } - - public void setOnDismissListener(@Nullable final OnDismissListener onDismissListener) { - this.onDismissListener = onDismissListener; - } - - public OnDismissListener getOnDismissListener() { - return onDismissListener; + public PlaylistAppendDialog(final List streamEntities) { + super(streamEntities); } /*////////////////////////////////////////////////////////////////////////// @@ -117,11 +58,15 @@ public final class PlaylistAppendDialog extends PlaylistDialog { playlistAdapter.setSelectedListener(new OnClickGesture() { @Override public void selected(final LocalItem selectedItem) { - if (!(selectedItem instanceof PlaylistMetadataEntry) || getStreams() == null) { + if (!(selectedItem instanceof PlaylistMetadataEntry) + || getStreamEntities() == null) { return; } - onPlaylistSelected(playlistManager, (PlaylistMetadataEntry) selectedItem, - getStreams()); + onPlaylistSelected( + playlistManager, + (PlaylistMetadataEntry) selectedItem, + getStreamEntities() + ); } }); @@ -154,29 +99,22 @@ public final class PlaylistAppendDialog extends PlaylistDialog { playlistAdapter = null; } - @Override - public void onDismiss(@NonNull final DialogInterface dialog) { - super.onDismiss(dialog); - if (onDismissListener != null) { - onDismissListener.onDismiss(dialog); - } - } - /*////////////////////////////////////////////////////////////////////////// // Helper //////////////////////////////////////////////////////////////////////////*/ public void openCreatePlaylistDialog() { - if (getStreams() == null || !isAdded()) { + if (getStreamEntities() == null || !isAdded()) { return; } - final PlaylistCreationDialog dialog = PlaylistCreationDialog.newInstance(getStreams()); + final PlaylistCreationDialog playlistCreationDialog = + new PlaylistCreationDialog(getStreamEntities()); // Move the dismissListener to the new dialog. - dialog.setOnDismissListener(this.onDismissListener); - this.onDismissListener = null; + playlistCreationDialog.setOnDismissListener(this.getOnDismissListener()); + this.setOnDismissListener(null); - dialog.show(getParentFragmentManager(), TAG); + playlistCreationDialog.show(getParentFragmentManager(), TAG); requireDialog().dismiss(); } @@ -191,7 +129,7 @@ public final class PlaylistAppendDialog extends PlaylistDialog { private void onPlaylistSelected(@NonNull final LocalPlaylistManager manager, @NonNull final PlaylistMetadataEntry playlist, @NonNull final List streams) { - if (getStreams() == null) { + if (getStreamEntities() == null) { return; } diff --git a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistCreationDialog.java b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistCreationDialog.java index b27b7c454..0f71e54d9 100644 --- a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistCreationDialog.java +++ b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistCreationDialog.java @@ -1,8 +1,6 @@ package org.schabi.newpipe.local.dialog; import android.app.Dialog; -import android.content.DialogInterface; -import android.content.DialogInterface.OnDismissListener; import android.os.Bundle; import android.text.InputType; import android.widget.Toast; @@ -23,32 +21,8 @@ import java.util.List; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; public final class PlaylistCreationDialog extends PlaylistDialog { - @Nullable - private OnDismissListener onDismissListener = null; - - public static PlaylistCreationDialog newInstance(final List streams) { - final PlaylistCreationDialog dialog = new PlaylistCreationDialog(); - dialog.setInfo(streams); - return dialog; - } - - public static PlaylistCreationDialog newInstance(final PlaylistAppendDialog appendDialog) { - final PlaylistCreationDialog dialog = new PlaylistCreationDialog(); - dialog.setInfo(appendDialog.getStreams()); - dialog.setOnDismissListener(appendDialog.getOnDismissListener()); - return dialog; - } - - public void setOnDismissListener(@Nullable final OnDismissListener onDismissListener) { - this.onDismissListener = onDismissListener; - } - - @Override - public void onDismiss(@NonNull final DialogInterface dialog) { - super.onDismiss(dialog); - if (onDismissListener != null) { - onDismissListener.onDismiss(dialog); - } + public PlaylistCreationDialog(final List streamEntities) { + super(streamEntities); } /*////////////////////////////////////////////////////////////////////////// @@ -58,7 +32,7 @@ public final class PlaylistCreationDialog extends PlaylistDialog { @NonNull @Override public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) { - if (getStreams() == null) { + if (getStreamEntities() == null) { return super.onCreateDialog(savedInstanceState); } @@ -81,7 +55,7 @@ public final class PlaylistCreationDialog extends PlaylistDialog { R.string.playlist_creation_success, Toast.LENGTH_SHORT); - playlistManager.createPlaylist(name, getStreams()) + playlistManager.createPlaylist(name, getStreamEntities()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(longs -> successToast.show()); }); diff --git a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistDialog.java b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistDialog.java index 2c2987e95..c2d4474f8 100644 --- a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistDialog.java +++ b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistDialog.java @@ -1,6 +1,8 @@ package org.schabi.newpipe.local.dialog; import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; import android.os.Bundle; import android.view.Window; @@ -8,23 +10,29 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.DialogFragment; +import org.schabi.newpipe.NewPipeDatabase; import org.schabi.newpipe.database.stream.model.StreamEntity; +import org.schabi.newpipe.local.playlist.LocalPlaylistManager; import org.schabi.newpipe.util.StateSaver; import java.util.List; import java.util.Queue; +import java.util.function.Consumer; + +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.disposables.Disposable; public abstract class PlaylistDialog extends DialogFragment implements StateSaver.WriteRead { + + @Nullable + private DialogInterface.OnDismissListener onDismissListener = null; + private List streamEntities; private org.schabi.newpipe.util.SavedState savedState; - protected void setInfo(final List entities) { - this.streamEntities = entities; - } - - protected List getStreams() { - return streamEntities; + public PlaylistDialog(final List streamEntities) { + this.streamEntities = streamEntities; } /*////////////////////////////////////////////////////////////////////////// @@ -43,6 +51,10 @@ public abstract class PlaylistDialog extends DialogFragment implements StateSave StateSaver.onDestroy(savedState); } + public List getStreamEntities() { + return streamEntities; + } + @NonNull @Override public Dialog onCreateDialog(final Bundle savedInstanceState) { @@ -55,6 +67,14 @@ public abstract class PlaylistDialog extends DialogFragment implements StateSave return dialog; } + @Override + public void onDismiss(@NonNull final DialogInterface dialog) { + super.onDismiss(dialog); + if (onDismissListener != null) { + onDismissListener.onDismiss(dialog); + } + } + /*////////////////////////////////////////////////////////////////////////// // State Saving //////////////////////////////////////////////////////////////////////////*/ @@ -84,4 +104,47 @@ public abstract class PlaylistDialog extends DialogFragment implements StateSave savedState, outState, this); } } + + /*////////////////////////////////////////////////////////////////////////// + // Getter + Setter + //////////////////////////////////////////////////////////////////////////*/ + + @Nullable + public DialogInterface.OnDismissListener getOnDismissListener() { + return onDismissListener; + } + + public void setOnDismissListener( + @Nullable final DialogInterface.OnDismissListener onDismissListener + ) { + this.onDismissListener = onDismissListener; + } + + /*////////////////////////////////////////////////////////////////////////// + // Dialog creation + //////////////////////////////////////////////////////////////////////////*/ + + /** + * Creates a {@link PlaylistAppendDialog} when playlists exists, + * otherwise a {@link PlaylistCreationDialog}. + * + * @param context context used for accessing the database + * @param streamEntities used for crating the dialog + * @param onExec execution that should occur after a dialog got created, e.g. showing it + * @return Disposable + */ + public static Disposable createCorrespondingDialog( + final Context context, + final List streamEntities, + final Consumer onExec + ) { + return new LocalPlaylistManager(NewPipeDatabase.getInstance(context)) + .hasPlaylists() + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(hasPlaylists -> + onExec.accept(hasPlaylists + ? new PlaylistAppendDialog(streamEntities) + : new PlaylistCreationDialog(streamEntities)) + ); + } } diff --git a/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java b/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java index 0976aa4fb..e0c5ab083 100644 --- a/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java +++ b/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java @@ -23,11 +23,11 @@ import androidx.recyclerview.widget.RecyclerView; import com.google.android.exoplayer2.PlaybackParameters; import org.schabi.newpipe.R; +import org.schabi.newpipe.database.stream.model.StreamEntity; import org.schabi.newpipe.databinding.ActivityPlayerQueueControlBinding; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.fragments.OnScrollBelowItemsListener; -import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; -import org.schabi.newpipe.local.dialog.PlaylistCreationDialog; +import org.schabi.newpipe.local.dialog.PlaylistDialog; import org.schabi.newpipe.player.event.PlayerEventListener; import org.schabi.newpipe.player.helper.PlaybackParameterDialog; import org.schabi.newpipe.player.playqueue.PlayQueue; @@ -43,6 +43,7 @@ import org.schabi.newpipe.util.ServiceHelper; import org.schabi.newpipe.util.ThemeHelper; import java.util.List; +import java.util.stream.Collectors; import static org.schabi.newpipe.QueueItemMenuUtil.openPopupMenu; import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed; @@ -452,12 +453,12 @@ public final class PlayQueueActivity extends AppCompatActivity } } - private void openPlaylistAppendDialog(final List playlist) { - final PlaylistAppendDialog d = PlaylistAppendDialog.fromPlayQueueItems(playlist); - - PlaylistAppendDialog.onPlaylistFound(getApplicationContext(), - () -> d.show(getSupportFragmentManager(), TAG), - () -> PlaylistCreationDialog.newInstance(d).show(getSupportFragmentManager(), TAG)); + private void openPlaylistAppendDialog(final List playQueueItems) { + PlaylistDialog.createCorrespondingDialog( + getApplicationContext(), + playQueueItems.stream().map(StreamEntity::new).collect(Collectors.toList()), + dialog -> dialog.show(getSupportFragmentManager(), TAG) + ); } //////////////////////////////////////////////////////////////////////////// diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java index 11cc4daba..e33c4da87 100644 --- a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java +++ b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java @@ -8,9 +8,10 @@ import androidx.fragment.app.Fragment; import org.schabi.newpipe.NewPipeDatabase; import org.schabi.newpipe.R; +import org.schabi.newpipe.database.stream.model.StreamEntity; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; -import org.schabi.newpipe.local.dialog.PlaylistCreationDialog; +import org.schabi.newpipe.local.dialog.PlaylistDialog; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.player.playqueue.SinglePlayQueue; import org.schabi.newpipe.util.external_communication.KoreUtils; @@ -82,13 +83,15 @@ public enum StreamDialogEntry { }), // has to be set manually append_playlist(R.string.add_to_playlist, (fragment, item) -> { - final PlaylistAppendDialog d = PlaylistAppendDialog - .fromStreamInfoItems(Collections.singletonList(item)); - - PlaylistAppendDialog.onPlaylistFound(fragment.getContext(), - () -> d.show(fragment.getParentFragmentManager(), "StreamDialogEntry@append_playlist"), - () -> PlaylistCreationDialog.newInstance(d) - .show(fragment.getParentFragmentManager(), "StreamDialogEntry@create_playlist") + PlaylistDialog.createCorrespondingDialog( + fragment.getContext(), + Collections.singletonList(new StreamEntity(item)), + dialog -> dialog.show( + fragment.getParentFragmentManager(), + "StreamDialogEntry@" + + (dialog instanceof PlaylistAppendDialog ? "append" : "create") + + "_playlist" + ) ); }), From 3c4e392ce17df3513305e0f3bc0067b8dcab582e Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sat, 9 Oct 2021 18:47:36 +0200 Subject: [PATCH 010/111] Add to playlist - Showing toast that this may take a moment --- app/src/main/java/org/schabi/newpipe/RouterActivity.java | 8 ++++++++ app/src/main/res/values/strings.xml | 1 + 2 files changed, 9 insertions(+) diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java index e3e97d570..4e96f3bb6 100644 --- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java +++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java @@ -591,6 +591,14 @@ public class RouterActivity extends AppCompatActivity { } private void openAddToPlaylistDialog() { + // Getting the stream info usually takes a moment + // Notifying the user here to ensure that no confusion arises + Toast.makeText( + getApplicationContext(), + getString(R.string.processing_may_take_a_moment), + Toast.LENGTH_SHORT) + .show(); + disposables.add(ExtractorHelper.getStreamInfo(currentServiceId, currentUrl, false) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c1fc08bc7..faceb5910 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -440,6 +440,7 @@ Rename Name Add to playlist + Processing... May take moment Mute Unmute Set as playlist thumbnail From 1134891eace8170be44f51e8bbc8c3fe4b3cd52d Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sat, 9 Oct 2021 18:56:10 +0200 Subject: [PATCH 011/111] Fixed typo --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index faceb5910..897ec0af8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -440,7 +440,7 @@ Rename Name Add to playlist - Processing... May take moment + Processing... May take a moment Mute Unmute Set as playlist thumbnail From 5ab0946c701c105b22c1ac83dc3f9cfe06f8b21a Mon Sep 17 00:00:00 2001 From: Kalle Struik Date: Sun, 10 Oct 2021 12:32:57 +0200 Subject: [PATCH 012/111] Fix cursor color in PlaylistCreationDialog --- .../org/schabi/newpipe/local/dialog/PlaylistCreationDialog.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistCreationDialog.java b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistCreationDialog.java index 0f71e54d9..6664144cd 100644 --- a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistCreationDialog.java +++ b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistCreationDialog.java @@ -38,6 +38,7 @@ public final class PlaylistCreationDialog extends PlaylistDialog { final DialogEditTextBinding dialogBinding = DialogEditTextBinding.inflate(getLayoutInflater()); + dialogBinding.getRoot().getContext().setTheme(ThemeHelper.getDialogTheme(requireContext())); dialogBinding.dialogEditText.setHint(R.string.name); dialogBinding.dialogEditText.setInputType(InputType.TYPE_CLASS_TEXT); From 3a7f39d684759be60755c1f7de61bbe8bc64e691 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Sun, 10 Oct 2021 20:30:56 +0200 Subject: [PATCH 013/111] Simplify code and add annotations --- .../newpipe/local/history/HistoryRecordManager.java | 8 ++++---- .../schabi/newpipe/player/helper/MediaSessionManager.java | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/history/HistoryRecordManager.java b/app/src/main/java/org/schabi/newpipe/local/history/HistoryRecordManager.java index 823e56d9e..d8c8440e2 100644 --- a/app/src/main/java/org/schabi/newpipe/local/history/HistoryRecordManager.java +++ b/app/src/main/java/org/schabi/newpipe/local/history/HistoryRecordManager.java @@ -334,9 +334,9 @@ public class HistoryRecordManager { .getState(entities.get(0).getUid()).blockingFirst(); if (states.isEmpty()) { result.add(null); - continue; + } else { + result.add(states.get(0)); } - result.add(states.get(0)); } return result; }).subscribeOn(Schedulers.io()); @@ -362,9 +362,9 @@ public class HistoryRecordManager { .blockingFirst(); if (states.isEmpty()) { result.add(null); - continue; + } else { + result.add(states.get(0)); } - result.add(states.get(0)); } return result; }).subscribeOn(Schedulers.io()); diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/MediaSessionManager.java b/app/src/main/java/org/schabi/newpipe/player/helper/MediaSessionManager.java index ef0d84029..8d344c877 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/MediaSessionManager.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/MediaSessionManager.java @@ -179,9 +179,7 @@ public class MediaSessionManager { // If we got an album art check if the current set AlbumArt is null if (optAlbumArt.isPresent() && getMetadataAlbumArt() == null) { if (DEBUG) { - if (getMetadataAlbumArt() == null) { - Log.d(TAG, "N_getMetadataAlbumArt: thumb == null"); - } + Log.d(TAG, "N_getMetadataAlbumArt: thumb == null"); } return true; } @@ -191,16 +189,19 @@ public class MediaSessionManager { } + @Nullable private Bitmap getMetadataAlbumArt() { return mediaSession.getController().getMetadata() .getBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART); } + @Nullable private String getMetadataTitle() { return mediaSession.getController().getMetadata() .getString(MediaMetadataCompat.METADATA_KEY_TITLE); } + @Nullable private String getMetadataArtist() { return mediaSession.getController().getMetadata() .getString(MediaMetadataCompat.METADATA_KEY_ARTIST); From ea6e99eff910b0ea44c5c4f3595afc0507f22f98 Mon Sep 17 00:00:00 2001 From: ktprograms Date: Mon, 11 Oct 2021 14:46:29 +0800 Subject: [PATCH 014/111] Added the 'Show Channel Details' menu item to the Queue long press menu Created a method in NavigationHelper that opens the channel fragment using an Intent to MainActivity instead of replacing fragments. --- .../java/org/schabi/newpipe/QueueItemMenuUtil.java | 8 ++++++-- .../org/schabi/newpipe/util/NavigationHelper.java | 12 ++++++++++++ app/src/main/res/menu/menu_play_queue_item.xml | 3 +++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java b/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java index 9105ff992..f2f71730d 100644 --- a/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java +++ b/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java @@ -1,7 +1,5 @@ package org.schabi.newpipe; -import static org.schabi.newpipe.util.external_communication.ShareUtils.shareText; - import android.content.Context; import android.view.ContextThemeWrapper; import android.view.View; @@ -17,6 +15,8 @@ import org.schabi.newpipe.util.NavigationHelper; import java.util.Collections; +import static org.schabi.newpipe.util.external_communication.ShareUtils.shareText; + public final class QueueItemMenuUtil { public static void openPopupMenu(final PlayQueue playQueue, final PlayQueueItem item, @@ -55,6 +55,10 @@ public final class QueueItemMenuUtil { () -> PlaylistCreationDialog.newInstance(d) .show(fragmentManager, "QueueItemMenuUtil@append_playlist")); return true; + case R.id.menu_item_channel_details: + NavigationHelper.openChannelFragmentUsingIntent(context, item.getServiceId(), + item.getUploaderUrl(), item.getUploader()); + return true; case R.id.menu_item_share: shareText(context, item.getTitle(), item.getUrl(), item.getThumbnailUrl()); diff --git a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java index afa826677..8852ef369 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -491,6 +491,18 @@ public final class NavigationHelper { context.startActivity(intent); } + public static void openChannelFragmentUsingIntent(final Context context, + final int serviceId, + final String url, + @NonNull final String title) { + final Intent intent = getOpenIntent(context, url, serviceId, + StreamingService.LinkType.CHANNEL); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(Constants.KEY_TITLE, title); + + context.startActivity(intent); + } + public static void openMainActivity(final Context context) { final Intent mIntent = new Intent(context, MainActivity.class); mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); diff --git a/app/src/main/res/menu/menu_play_queue_item.xml b/app/src/main/res/menu/menu_play_queue_item.xml index ebb361be9..40c4849b4 100644 --- a/app/src/main/res/menu/menu_play_queue_item.xml +++ b/app/src/main/res/menu/menu_play_queue_item.xml @@ -10,6 +10,9 @@ + From cbe10ab3ea6f8627466f608c9d0a98585bbb0224 Mon Sep 17 00:00:00 2001 From: vhouriet Date: Mon, 11 Oct 2021 19:41:22 +0200 Subject: [PATCH 015/111] Check player type before displaying background player toast --- .../main/java/org/schabi/newpipe/util/NavigationHelper.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java index ae1e6cede..c22af1ce0 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -149,8 +149,10 @@ public final class NavigationHelper { 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(); + if (PlayerHolder.getInstance().getType() != MainPlayer.PlayerType.AUDIO) { + Toast.makeText(context, R.string.background_player_playing_toast, Toast.LENGTH_SHORT) + .show(); + } final Intent intent = getPlayerIntent(context, MainPlayer.class, queue, resumePlayback); intent.putExtra(Player.PLAYER_TYPE, MainPlayer.PlayerType.AUDIO.ordinal()); ContextCompat.startForegroundService(context, intent); From d33d390250f126202f93dc39a6aaf699cb645e38 Mon Sep 17 00:00:00 2001 From: ktprograms Date: Thu, 14 Oct 2021 09:51:25 +0800 Subject: [PATCH 016/111] Add reasoning for separate openChannelFragmentUsingIntent method --- .../main/java/org/schabi/newpipe/util/NavigationHelper.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java index 8852ef369..9e6a3980c 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -491,6 +491,11 @@ public final class NavigationHelper { context.startActivity(intent); } + ///////////////////////////////////////////////////// + // PlayQueueActivity doesn't use fragments so the // + // openChannelFragment method can't be used // + // since that uses FragmentManager transactions. // + ///////////////////////////////////////////////////// public static void openChannelFragmentUsingIntent(final Context context, final int serviceId, final String url, From 63b6e074a75e249934c89ad3d80e463041caaf15 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 15 Oct 2021 20:16:34 +0200 Subject: [PATCH 017/111] Improved documentation --- .../java/org/schabi/newpipe/QueueItemMenuUtil.java | 3 +++ .../org/schabi/newpipe/util/NavigationHelper.java | 14 +++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java b/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java index f2f71730d..7d00d0027 100644 --- a/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java +++ b/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java @@ -56,6 +56,9 @@ public final class QueueItemMenuUtil { .show(fragmentManager, "QueueItemMenuUtil@append_playlist")); return true; case R.id.menu_item_channel_details: + // An intent must be used here. + // Opening with FragmentManager transactions is not working, + // as PlayQueueActivity doesn't use fragments. NavigationHelper.openChannelFragmentUsingIntent(context, item.getServiceId(), item.getUploaderUrl(), item.getUploader()); return true; diff --git a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java index 9e6a3980c..c70f6a9d0 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -491,11 +491,15 @@ public final class NavigationHelper { context.startActivity(intent); } - ///////////////////////////////////////////////////// - // PlayQueueActivity doesn't use fragments so the // - // openChannelFragment method can't be used // - // since that uses FragmentManager transactions. // - ///////////////////////////////////////////////////// + /** + * Opens {@link ChannelFragment}. + * Use this instead of {@link #openChannelFragment(FragmentManager, int, String, String)} + * when no fragments are used / no FragmentManager is available. + * @param context + * @param serviceId + * @param url + * @param title + */ public static void openChannelFragmentUsingIntent(final Context context, final int serviceId, final String url, From 4989c06916173c41475c5a8a21ccc4b0ba2c17a9 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 15 Oct 2021 20:18:52 +0200 Subject: [PATCH 018/111] Fixed format of code --- .../main/java/org/schabi/newpipe/QueueItemMenuUtil.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java b/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java index 7d00d0027..0201064b4 100644 --- a/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java +++ b/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java @@ -1,5 +1,7 @@ package org.schabi.newpipe; +import static org.schabi.newpipe.util.external_communication.ShareUtils.shareText; + import android.content.Context; import android.view.ContextThemeWrapper; import android.view.View; @@ -15,9 +17,10 @@ import org.schabi.newpipe.util.NavigationHelper; import java.util.Collections; -import static org.schabi.newpipe.util.external_communication.ShareUtils.shareText; - public final class QueueItemMenuUtil { + private QueueItemMenuUtil() { + } + public static void openPopupMenu(final PlayQueue playQueue, final PlayQueueItem item, final View view, @@ -72,6 +75,4 @@ public final class QueueItemMenuUtil { popupMenu.show(); } - - private QueueItemMenuUtil() { } } From 0d52d0ab23dafbd500a164d5bc8e421856ed2f2f Mon Sep 17 00:00:00 2001 From: TacoTheDank Date: Fri, 15 Oct 2021 16:48:44 -0400 Subject: [PATCH 019/111] Update plugins --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 4617611a8..1bcddd7cc 100644 --- a/build.gradle +++ b/build.gradle @@ -1,14 +1,14 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.5.30' + ext.kotlin_version = '1.5.31' repositories { google() mavenCentral() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:7.0.2' + classpath 'com.android.tools.build:gradle:7.0.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong From a6bebe7b5410ebe12db507aeb1ba6b3a78ab958e Mon Sep 17 00:00:00 2001 From: TiA4f8R <74829229+TiA4f8R@users.noreply.github.com> Date: Sat, 4 Sep 2021 19:32:38 +0200 Subject: [PATCH 020/111] Use a custom TextView everywhere to be able to share with ShareUtils the selected text This TextView class extends the AppCompatTextView class from androidx. These changes (only in XML ressources) allow us to share the selected text by using ShareUtils.shareText, which opens the Android system chooser instead of the Huawei system chooser on EMUI devices. --- .../schabi/newpipe/views/NewPipeTextView.java | 60 +++++++++ .../activity_player_queue_control.xml | 12 +- .../fragment_video_detail.xml | 40 +++--- app/src/main/res/layout-large-land/player.xml | 20 +-- app/src/main/res/layout/activity_error.xml | 20 +-- .../layout/activity_player_queue_control.xml | 122 +++++++++--------- app/src/main/res/layout/channel_header.xml | 6 +- .../res/layout/dialog_feed_group_create.xml | 8 +- .../res/layout/dialog_playback_parameter.xml | 35 ++--- app/src/main/res/layout/dialog_playlists.xml | 2 +- app/src/main/res/layout/dialog_title.xml | 4 +- app/src/main/res/layout/download_dialog.xml | 6 +- app/src/main/res/layout/drawer_header.xml | 4 +- app/src/main/res/layout/error_panel.xml | 6 +- .../res/layout/feed_group_add_new_item.xml | 2 +- .../main/res/layout/feed_group_card_item.xml | 2 +- .../res/layout/feed_group_reorder_item.xml | 2 +- .../res/layout/feed_import_export_group.xml | 6 +- app/src/main/res/layout/fragment_about.xml | 20 +-- app/src/main/res/layout/fragment_channel.xml | 6 +- .../main/res/layout/fragment_choose_tabs.xml | 2 +- app/src/main/res/layout/fragment_comments.xml | 4 +- .../main/res/layout/fragment_description.xml | 6 +- app/src/main/res/layout/fragment_feed.xml | 6 +- app/src/main/res/layout/fragment_import.xml | 2 +- .../res/layout/fragment_instance_list.xml | 2 +- app/src/main/res/layout/fragment_kiosk.xml | 4 +- app/src/main/res/layout/fragment_licenses.xml | 6 +- app/src/main/res/layout/fragment_playlist.xml | 4 +- .../res/layout/fragment_related_items.xml | 4 +- app/src/main/res/layout/fragment_search.xml | 8 +- .../main/res/layout/fragment_video_detail.xml | 40 +++--- .../main/res/layout/header_with_menu_item.xml | 2 +- .../main/res/layout/item_stream_segment.xml | 6 +- .../res/layout/list_choose_tabs_dialog.xml | 2 +- .../main/res/layout/list_comments_item.xml | 10 +- .../res/layout/list_comments_mini_item.xml | 8 +- app/src/main/res/layout/list_empty_view.xml | 4 +- .../res/layout/list_playlist_grid_item.xml | 6 +- .../main/res/layout/list_playlist_item.xml | 6 +- .../res/layout/list_playlist_mini_item.xml | 6 +- .../main/res/layout/list_stream_grid_item.xml | 8 +- app/src/main/res/layout/list_stream_item.xml | 8 +- .../main/res/layout/list_stream_mini_item.xml | 6 +- .../layout/list_stream_playlist_grid_item.xml | 6 +- .../res/layout/list_stream_playlist_item.xml | 6 +- .../main/res/layout/local_playlist_header.xml | 4 +- app/src/main/res/layout/main_bg.xml | 4 +- app/src/main/res/layout/mission_item.xml | 6 +- .../main/res/layout/mission_item_linear.xml | 6 +- app/src/main/res/layout/missions_header.xml | 2 +- .../res/layout/picker_subscription_item.xml | 2 +- app/src/main/res/layout/play_queue_item.xml | 6 +- app/src/main/res/layout/player.xml | 20 +-- app/src/main/res/layout/playlist_control.xml | 6 +- app/src/main/res/layout/playlist_header.xml | 6 +- .../main/res/layout/related_items_header.xml | 2 +- .../res/layout/select_channel_fragment.xml | 6 +- .../main/res/layout/select_channel_item.xml | 2 +- .../main/res/layout/select_kiosk_fragment.xml | 4 +- app/src/main/res/layout/select_kiosk_item.xml | 2 +- .../res/layout/select_playlist_fragment.xml | 4 +- .../settings_category_header_layout.xml | 2 +- .../layout/settings_category_header_title.xml | 2 +- .../main/res/layout/settings_notification.xml | 2 +- .../layout/settings_notification_action.xml | 4 +- .../res/layout/statistic_playlist_control.xml | 2 +- .../main/res/layout/stream_quality_item.xml | 6 +- .../subscription_import_export_item.xml | 2 +- 69 files changed, 362 insertions(+), 295 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java diff --git a/app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java b/app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java new file mode 100644 index 000000000..f69dfb33b --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java @@ -0,0 +1,60 @@ +package org.schabi.newpipe.views; + +import android.content.Context; +import android.text.Selection; +import android.text.Spannable; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatTextView; + +import org.schabi.newpipe.util.external_communication.ShareUtils; + +public class NewPipeTextView extends AppCompatTextView { + + public NewPipeTextView(@NonNull final Context context) { + super(context); + } + + public NewPipeTextView(@NonNull final Context context, @Nullable final AttributeSet attrs) { + super(context, attrs); + } + + public NewPipeTextView(@NonNull final Context context, + @Nullable final AttributeSet attrs, + final int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + public boolean onTextContextMenuItem(final int id) { + final CharSequence text = getText(); + if (id == android.R.id.shareText) { + final String selectedText = getSelectedText(text).toString(); + if (!selectedText.isEmpty()) { + ShareUtils.shareText(getContext(), "", selectedText); + } + final Spannable spannable = (text instanceof Spannable) ? (Spannable) text : null; + Selection.setSelection(spannable, getSelectionEnd()); + return true; + } else { + return super.onTextContextMenuItem(id); + } + } + + @NonNull + private CharSequence getSelectedText(@NonNull final CharSequence charSequence) { + int min = 0; + int max = charSequence.length(); + + if (isFocused()) { + final int selStart = getSelectionStart(); + final int selEnd = getSelectionEnd(); + + min = Math.max(0, Math.min(selStart, selEnd)); + max = Math.max(0, Math.max(selStart, selEnd)); + } + return charSequence.subSequence(min, max); + } +} diff --git a/app/src/main/res/layout-land/activity_player_queue_control.xml b/app/src/main/res/layout-land/activity_player_queue_control.xml index 4b79d92f6..c2359552e 100644 --- a/app/src/main/res/layout-land/activity_player_queue_control.xml +++ b/app/src/main/res/layout-land/activity_player_queue_control.xml @@ -60,7 +60,7 @@ android:padding="8dp" tools:ignore="RtlHardcoded,RtlSymmetry"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -82,7 +82,7 @@ - - - - - - - + android:layout_above="@+id/playback_controls"> - + android:background="?attr/selectableItemBackground" + android:clickable="true" + android:focusable="true" + android:orientation="vertical" + android:padding="8dp" + tools:ignore="RtlHardcoded,RtlSymmetry"> - + + + + + - + android:layout_centerInParent="true" + android:background="#c0000000" + android:paddingLeft="30dp" + android:paddingTop="5dp" + android:paddingRight="30dp" + android:paddingBottom="5dp" + android:textColor="@android:color/white" + android:textSize="22sp" + android:textStyle="bold" + android:visibility="gone" + tools:ignore="RtlHardcoded" + tools:text="1:06:29" + tools:visibility="visible" /> + + android:paddingRight="12dp"> - - - + diff --git a/app/src/main/res/layout/channel_header.xml b/app/src/main/res/layout/channel_header.xml index aebb5d613..9366faf2c 100644 --- a/app/src/main/res/layout/channel_header.xml +++ b/app/src/main/res/layout/channel_header.xml @@ -49,7 +49,7 @@ tools:visibility="visible" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -85,14 +85,14 @@ android:layout_gravity="end" android:text="@string/give_back" /> - - @@ -105,14 +105,14 @@ android:layout_gravity="end" android:text="@string/open_in_browser" /> - - diff --git a/app/src/main/res/layout/fragment_channel.xml b/app/src/main/res/layout/fragment_channel.xml index 873f3c884..9e2257539 100644 --- a/app/src/main/res/layout/fragment_channel.xml +++ b/app/src/main/res/layout/fragment_channel.xml @@ -30,7 +30,7 @@ android:visibility="gone" tools:visibility="visible"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - - - --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + tools:listitem="@layout/select_channel_item" /> - - - + tools:listitem="@layout/select_kiosk_item" /> diff --git a/app/src/main/res/layout/select_kiosk_item.xml b/app/src/main/res/layout/select_kiosk_item.xml index 6cd04ae34..680767bba 100644 --- a/app/src/main/res/layout/select_kiosk_item.xml +++ b/app/src/main/res/layout/select_kiosk_item.xml @@ -22,7 +22,7 @@ app:tint="@color/contrastColor" tools:ignore="RtlHardcoded" /> - - - - diff --git a/app/src/main/res/layout/settings_category_header_title.xml b/app/src/main/res/layout/settings_category_header_title.xml index 679b9048c..c7d6920b0 100644 --- a/app/src/main/res/layout/settings_category_header_title.xml +++ b/app/src/main/res/layout/settings_category_header_title.xml @@ -1,5 +1,5 @@ - - - - - - - - - Date: Sat, 4 Sep 2021 19:40:24 +0200 Subject: [PATCH 021/111] Use a custom EditText everywhere to be able to share with ShareUtils the selected text This EditText class extends the AppCompatEditText class from androidx. These changes (only in XML ressources) allow us to share the selected text by using ShareUtils.shareText, which opens the Android system chooser instead of the Huawei system chooser on EMUI devices. --- .../schabi/newpipe/views/NewPipeEditText.java | 60 +++++++++++++++++++ app/src/main/res/layout/activity_error.xml | 2 +- app/src/main/res/layout/dialog_edit_text.xml | 2 +- .../res/layout/dialog_feed_group_create.xml | 2 +- app/src/main/res/layout/download_dialog.xml | 2 +- app/src/main/res/layout/fragment_import.xml | 2 +- .../main/res/layout/toolbar_search_layout.xml | 2 +- 7 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java diff --git a/app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java b/app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java new file mode 100644 index 000000000..15a70f360 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java @@ -0,0 +1,60 @@ +package org.schabi.newpipe.views; + +import android.content.Context; +import android.text.Selection; +import android.text.Spannable; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatEditText; + +import org.schabi.newpipe.util.external_communication.ShareUtils; + +public class NewPipeEditText extends AppCompatEditText { + public NewPipeEditText(@NonNull final Context context) { + super(context); + } + + public NewPipeEditText(@NonNull final Context context, @Nullable final AttributeSet attrs) { + super(context, attrs); + } + + public NewPipeEditText(@NonNull final Context context, + @Nullable final AttributeSet attrs, + final int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + public boolean onTextContextMenuItem(final int id) { + final Spannable text = getText(); + if (id == android.R.id.shareText) { + if (text != null) { + final String selectedText = getSelectedText(text).toString(); + if (!selectedText.isEmpty()) { + ShareUtils.shareText(getContext(), "", selectedText); + } + Selection.setSelection(text, getSelectionEnd()); + } + return true; + } else { + return super.onTextContextMenuItem(id); + } + } + + @NonNull + private CharSequence getSelectedText(@NonNull final CharSequence charSequence) { + int min = 0; + int max = charSequence.length(); + + if (isFocused()) { + final int selStart = getSelectionStart(); + final int selEnd = getSelectionEnd(); + + min = Math.max(0, Math.min(selStart, selEnd)); + max = Math.max(0, Math.max(selStart, selEnd)); + } + return charSequence.subSequence(min, max); + } +} diff --git a/app/src/main/res/layout/activity_error.xml b/app/src/main/res/layout/activity_error.xml index a7b3c48a9..45101c1a1 100644 --- a/app/src/main/res/layout/activity_error.xml +++ b/app/src/main/res/layout/activity_error.xml @@ -109,7 +109,7 @@ android:text="@string/your_comment" android:textAppearance="?android:attr/textAppearanceMedium" /> - - - - - - Date: Tue, 14 Sep 2021 20:19:17 +0200 Subject: [PATCH 022/111] Add JavaDocs on created views --- .../java/org/schabi/newpipe/views/NewPipeEditText.java | 9 +++++++++ .../java/org/schabi/newpipe/views/NewPipeTextView.java | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java b/app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java index 15a70f360..c7a397fbe 100644 --- a/app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java +++ b/app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java @@ -11,7 +11,16 @@ import androidx.appcompat.widget.AppCompatEditText; import org.schabi.newpipe.util.external_communication.ShareUtils; +/** + * An {@link AppCompatEditText} which uses {@link ShareUtils#shareText(Context, String, String)} + * when sharing selected text by using the {@code Share} command of the floating actions. + *

+ * This allows NewPipe to show Android share sheet instead of EMUI share sheet when sharing text + * from {@link AppCompatEditText} on EMUI devices. + *

+ */ public class NewPipeEditText extends AppCompatEditText { + public NewPipeEditText(@NonNull final Context context) { super(context); } diff --git a/app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java b/app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java index f69dfb33b..321f1e34d 100644 --- a/app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java +++ b/app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java @@ -11,6 +11,14 @@ import androidx.appcompat.widget.AppCompatTextView; import org.schabi.newpipe.util.external_communication.ShareUtils; +/** + * An {@link AppCompatTextView} which uses {@link ShareUtils#shareText(Context, String, String)} + * when sharing selected text by using the {@code Share} command of the floating actions. + *

+ * This allows NewPipe to show Android share sheet instead of EMUI share sheet when sharing text + * from {@link AppCompatTextView} on EMUI devices. + *

+ */ public class NewPipeTextView extends AppCompatTextView { public NewPipeTextView(@NonNull final Context context) { From 1cfd513e2550bcb18cc646e7d062899d29f1afa6 Mon Sep 17 00:00:00 2001 From: TiA4f8R <74829229+TiA4f8R@users.noreply.github.com> Date: Sat, 18 Sep 2021 14:14:36 +0200 Subject: [PATCH 023/111] Improve code of created views Use the same logic as Android TextViews --- .../schabi/newpipe/views/NewPipeEditText.java | 33 ++++++++----------- .../schabi/newpipe/views/NewPipeTextView.java | 29 ++++++++-------- 2 files changed, 27 insertions(+), 35 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java b/app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java index c7a397fbe..41d7640b6 100644 --- a/app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java +++ b/app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java @@ -37,33 +37,28 @@ public class NewPipeEditText extends AppCompatEditText { @Override public boolean onTextContextMenuItem(final int id) { - final Spannable text = getText(); if (id == android.R.id.shareText) { - if (text != null) { - final String selectedText = getSelectedText(text).toString(); - if (!selectedText.isEmpty()) { - ShareUtils.shareText(getContext(), "", selectedText); - } - Selection.setSelection(text, getSelectionEnd()); + final Spannable text = getText(); + final CharSequence selectedText = getSelectedText(text); + if (selectedText != null && selectedText.length() != 0) { + ShareUtils.shareText(getContext(), "", selectedText.toString()); } + Selection.setSelection(text, getSelectionEnd()); return true; } else { return super.onTextContextMenuItem(id); } } - @NonNull - private CharSequence getSelectedText(@NonNull final CharSequence charSequence) { - int min = 0; - int max = charSequence.length(); - - if (isFocused()) { - final int selStart = getSelectionStart(); - final int selEnd = getSelectionEnd(); - - min = Math.max(0, Math.min(selStart, selEnd)); - max = Math.max(0, Math.max(selStart, selEnd)); + @Nullable + private CharSequence getSelectedText(@Nullable final CharSequence text) { + if (!hasSelection() || text == null) { + return null; } - return charSequence.subSequence(min, max); + + final int start = getSelectionStart(); + final int end = getSelectionEnd(); + return String.valueOf(start > end ? text.subSequence(end, start) + : text.subSequence(start, end)); } } diff --git a/app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java b/app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java index 321f1e34d..f333aae5d 100644 --- a/app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java +++ b/app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java @@ -37,11 +37,11 @@ public class NewPipeTextView extends AppCompatTextView { @Override public boolean onTextContextMenuItem(final int id) { - final CharSequence text = getText(); if (id == android.R.id.shareText) { - final String selectedText = getSelectedText(text).toString(); - if (!selectedText.isEmpty()) { - ShareUtils.shareText(getContext(), "", selectedText); + final CharSequence text = getText(); + final CharSequence selectedText = getSelectedText(text); + if (selectedText != null && selectedText.length() != 0) { + ShareUtils.shareText(getContext(), "", selectedText.toString()); } final Spannable spannable = (text instanceof Spannable) ? (Spannable) text : null; Selection.setSelection(spannable, getSelectionEnd()); @@ -51,18 +51,15 @@ public class NewPipeTextView extends AppCompatTextView { } } - @NonNull - private CharSequence getSelectedText(@NonNull final CharSequence charSequence) { - int min = 0; - int max = charSequence.length(); - - if (isFocused()) { - final int selStart = getSelectionStart(); - final int selEnd = getSelectionEnd(); - - min = Math.max(0, Math.min(selStart, selEnd)); - max = Math.max(0, Math.max(selStart, selEnd)); + @Nullable + private CharSequence getSelectedText(@Nullable final CharSequence text) { + if (!hasSelection() || text == null) { + return null; } - return charSequence.subSequence(min, max); + + final int start = getSelectionStart(); + final int end = getSelectionEnd(); + return String.valueOf(start > end ? text.subSequence(end, start) + : text.subSequence(start, end)); } } From 4cd970fc97a9e4cfb3d7d093fc1dad77679d084f Mon Sep 17 00:00:00 2001 From: TiA4f8R <74829229+TiA4f8R@users.noreply.github.com> Date: Fri, 24 Sep 2021 20:14:31 +0200 Subject: [PATCH 024/111] Merge the Share process of the two classes into one A new class has been added in the util package: NewPipeTextViewHelper. It shares the selected text of a TextView with ShareUtils#shareText (with the created shareSelectedTextWithShareUtils static method). Only this static method can be used by other classes, other methods are private. --- .../newpipe/util/NewPipeTextViewHelper.java | 86 +++++++++++++++++++ .../schabi/newpipe/views/NewPipeEditText.java | 27 +----- .../schabi/newpipe/views/NewPipeTextView.java | 28 +----- 3 files changed, 94 insertions(+), 47 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java diff --git a/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java b/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java new file mode 100644 index 000000000..31c87f7df --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java @@ -0,0 +1,86 @@ +package org.schabi.newpipe.util; + +import android.content.Context; +import android.text.Selection; +import android.text.Spannable; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import org.schabi.newpipe.util.external_communication.ShareUtils; +import org.schabi.newpipe.views.NewPipeEditText; +import org.schabi.newpipe.views.NewPipeTextView; + +public final class NewPipeTextViewHelper { + private NewPipeTextViewHelper() { + } + + /** + * Share the selected text of {@link NewPipeTextView NewPipeTextViews} and + * {@link NewPipeEditText NewPipeEditTexts} with + * {@link ShareUtils#shareText(Context, String, String)}. + * + *

+ * This allows EMUI users to get the Android share sheet instead of the EMUI share sheet when + * using the {@code Share} command of the popup menu which appears when selecting text. + *

+ * + * @param textView the {@link TextView} on which sharing the selected text. It should be a + * {@link NewPipeTextView} or a {@link NewPipeEditText} (even if + * {@link TextView standard TextViews} are supported). + * + * @return true if no exceptions occurred when getting the selected text, sharing it and + * deselecting it, otherwise an exception + */ + public static boolean shareSelectedTextWithShareUtils(@NonNull final TextView textView) { + if (textView instanceof NewPipeTextView) { + final NewPipeTextView newPipeTextView = (NewPipeTextView) textView; + final CharSequence text = newPipeTextView.getText(); + final CharSequence selectedText = getSelectedText(newPipeTextView, text); + + shareSelectedTextIfNotNullAndNotEmpty(newPipeTextView, selectedText); + + final Spannable spannable = (text instanceof Spannable) ? (Spannable) text : null; + Selection.setSelection(spannable, newPipeTextView.getSelectionEnd()); + } else if (textView instanceof NewPipeEditText) { + final NewPipeEditText editText = (NewPipeEditText) textView; + final Spannable text = editText.getText(); + + final CharSequence selectedText = getSelectedText(textView, text); + shareSelectedTextIfNotNullAndNotEmpty(textView, selectedText); + Selection.setSelection(text, editText.getSelectionEnd()); + } else { + final CharSequence text = textView.getText(); + final CharSequence selectedText = getSelectedText(textView, text); + + shareSelectedTextIfNotNullAndNotEmpty(textView, selectedText); + + final Spannable spannable = (text instanceof Spannable) ? (Spannable) text : null; + Selection.setSelection(spannable, textView.getSelectionEnd()); + } + + return true; + } + + @Nullable + private static CharSequence getSelectedText(@NonNull final TextView textView, + @Nullable final CharSequence text) { + if (!textView.hasSelection() || text == null) { + return null; + } + + final int start = textView.getSelectionStart(); + final int end = textView.getSelectionEnd(); + return String.valueOf(start > end ? text.subSequence(end, start) + : text.subSequence(start, end)); + } + + private static void shareSelectedTextIfNotNullAndNotEmpty( + @NonNull final TextView textView, + @Nullable final CharSequence selectedText) { + if (selectedText != null && selectedText.length() != 0) { + ShareUtils.shareText(textView.getContext(), "", selectedText.toString()); + } + } +} diff --git a/app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java b/app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java index 41d7640b6..cdb4f0041 100644 --- a/app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java +++ b/app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java @@ -1,8 +1,6 @@ package org.schabi.newpipe.views; import android.content.Context; -import android.text.Selection; -import android.text.Spannable; import android.util.AttributeSet; import androidx.annotation.NonNull; @@ -11,6 +9,8 @@ import androidx.appcompat.widget.AppCompatEditText; import org.schabi.newpipe.util.external_communication.ShareUtils; +import static org.schabi.newpipe.util.NewPipeTextViewHelper.shareSelectedTextWithShareUtils; + /** * An {@link AppCompatEditText} which uses {@link ShareUtils#shareText(Context, String, String)} * when sharing selected text by using the {@code Share} command of the floating actions. @@ -38,27 +38,8 @@ public class NewPipeEditText extends AppCompatEditText { @Override public boolean onTextContextMenuItem(final int id) { if (id == android.R.id.shareText) { - final Spannable text = getText(); - final CharSequence selectedText = getSelectedText(text); - if (selectedText != null && selectedText.length() != 0) { - ShareUtils.shareText(getContext(), "", selectedText.toString()); - } - Selection.setSelection(text, getSelectionEnd()); - return true; - } else { - return super.onTextContextMenuItem(id); + return shareSelectedTextWithShareUtils(this); } - } - - @Nullable - private CharSequence getSelectedText(@Nullable final CharSequence text) { - if (!hasSelection() || text == null) { - return null; - } - - final int start = getSelectionStart(); - final int end = getSelectionEnd(); - return String.valueOf(start > end ? text.subSequence(end, start) - : text.subSequence(start, end)); + return super.onTextContextMenuItem(id); } } diff --git a/app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java b/app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java index f333aae5d..75fb8f161 100644 --- a/app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java +++ b/app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java @@ -1,8 +1,6 @@ package org.schabi.newpipe.views; import android.content.Context; -import android.text.Selection; -import android.text.Spannable; import android.util.AttributeSet; import androidx.annotation.NonNull; @@ -11,6 +9,8 @@ import androidx.appcompat.widget.AppCompatTextView; import org.schabi.newpipe.util.external_communication.ShareUtils; +import static org.schabi.newpipe.util.NewPipeTextViewHelper.shareSelectedTextWithShareUtils; + /** * An {@link AppCompatTextView} which uses {@link ShareUtils#shareText(Context, String, String)} * when sharing selected text by using the {@code Share} command of the floating actions. @@ -38,28 +38,8 @@ public class NewPipeTextView extends AppCompatTextView { @Override public boolean onTextContextMenuItem(final int id) { if (id == android.R.id.shareText) { - final CharSequence text = getText(); - final CharSequence selectedText = getSelectedText(text); - if (selectedText != null && selectedText.length() != 0) { - ShareUtils.shareText(getContext(), "", selectedText.toString()); - } - final Spannable spannable = (text instanceof Spannable) ? (Spannable) text : null; - Selection.setSelection(spannable, getSelectionEnd()); - return true; - } else { - return super.onTextContextMenuItem(id); + return shareSelectedTextWithShareUtils(this); } - } - - @Nullable - private CharSequence getSelectedText(@Nullable final CharSequence text) { - if (!hasSelection() || text == null) { - return null; - } - - final int start = getSelectionStart(); - final int end = getSelectionEnd(); - return String.valueOf(start > end ? text.subSequence(end, start) - : text.subSequence(start, end)); + return super.onTextContextMenuItem(id); } } From 648641341f964609ff73ffd588428cb264aa2948 Mon Sep 17 00:00:00 2001 From: TiA4f8R <74829229+TiA4f8R@users.noreply.github.com> Date: Fri, 1 Oct 2021 23:39:14 +0200 Subject: [PATCH 025/111] Simplify code --- .../newpipe/util/NewPipeTextViewHelper.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java b/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java index 31c87f7df..5e3a790d0 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java @@ -34,30 +34,30 @@ public final class NewPipeTextViewHelper { * deselecting it, otherwise an exception */ public static boolean shareSelectedTextWithShareUtils(@NonNull final TextView textView) { - if (textView instanceof NewPipeTextView) { - final NewPipeTextView newPipeTextView = (NewPipeTextView) textView; - final CharSequence text = newPipeTextView.getText(); - final CharSequence selectedText = getSelectedText(newPipeTextView, text); + if (!(textView instanceof NewPipeEditText)) { + final CharSequence textViewText; + if (textView instanceof NewPipeTextView) { + final NewPipeTextView newPipeTextView = (NewPipeTextView) textView; + textViewText = newPipeTextView.getText(); + } else { + textViewText = textView.getText(); + } - shareSelectedTextIfNotNullAndNotEmpty(newPipeTextView, selectedText); + final CharSequence selectedText = getSelectedText(textView, textViewText); + shareSelectedTextIfNotNullAndNotEmpty(textView, selectedText); - final Spannable spannable = (text instanceof Spannable) ? (Spannable) text : null; - Selection.setSelection(spannable, newPipeTextView.getSelectionEnd()); - } else if (textView instanceof NewPipeEditText) { + final Spannable spannable = (textViewText instanceof Spannable) + ? (Spannable) textViewText : null; + if (spannable != null) { + Selection.setSelection(spannable, textView.getSelectionEnd()); + } + } else { final NewPipeEditText editText = (NewPipeEditText) textView; final Spannable text = editText.getText(); final CharSequence selectedText = getSelectedText(textView, text); shareSelectedTextIfNotNullAndNotEmpty(textView, selectedText); Selection.setSelection(text, editText.getSelectionEnd()); - } else { - final CharSequence text = textView.getText(); - final CharSequence selectedText = getSelectedText(textView, text); - - shareSelectedTextIfNotNullAndNotEmpty(textView, selectedText); - - final Spannable spannable = (text instanceof Spannable) ? (Spannable) text : null; - Selection.setSelection(spannable, textView.getSelectionEnd()); } return true; @@ -65,7 +65,7 @@ public final class NewPipeTextViewHelper { @Nullable private static CharSequence getSelectedText(@NonNull final TextView textView, - @Nullable final CharSequence text) { + @Nullable final CharSequence text) { if (!textView.hasSelection() || text == null) { return null; } From 35401c01036923bb264a8d38187e2f24bf61ae80 Mon Sep 17 00:00:00 2001 From: TiA4f8R <74829229+TiA4f8R@users.noreply.github.com> Date: Sat, 2 Oct 2021 19:53:17 +0200 Subject: [PATCH 026/111] Adress requested changes and remove an unused return value in NewPipeTextViewHelper --- .../org/schabi/newpipe/util/NewPipeTextViewHelper.java | 7 +------ .../java/org/schabi/newpipe/views/NewPipeEditText.java | 6 +++--- .../java/org/schabi/newpipe/views/NewPipeTextView.java | 6 +++--- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java b/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java index 5e3a790d0..6db016090 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java @@ -29,11 +29,8 @@ public final class NewPipeTextViewHelper { * @param textView the {@link TextView} on which sharing the selected text. It should be a * {@link NewPipeTextView} or a {@link NewPipeEditText} (even if * {@link TextView standard TextViews} are supported). - * - * @return true if no exceptions occurred when getting the selected text, sharing it and - * deselecting it, otherwise an exception */ - public static boolean shareSelectedTextWithShareUtils(@NonNull final TextView textView) { + public static void shareSelectedTextWithShareUtils(@NonNull final TextView textView) { if (!(textView instanceof NewPipeEditText)) { final CharSequence textViewText; if (textView instanceof NewPipeTextView) { @@ -59,8 +56,6 @@ public final class NewPipeTextViewHelper { shareSelectedTextIfNotNullAndNotEmpty(textView, selectedText); Selection.setSelection(text, editText.getSelectionEnd()); } - - return true; } @Nullable diff --git a/app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java b/app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java index cdb4f0041..2adc28d0e 100644 --- a/app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java +++ b/app/src/main/java/org/schabi/newpipe/views/NewPipeEditText.java @@ -7,10 +7,9 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.widget.AppCompatEditText; +import org.schabi.newpipe.util.NewPipeTextViewHelper; import org.schabi.newpipe.util.external_communication.ShareUtils; -import static org.schabi.newpipe.util.NewPipeTextViewHelper.shareSelectedTextWithShareUtils; - /** * An {@link AppCompatEditText} which uses {@link ShareUtils#shareText(Context, String, String)} * when sharing selected text by using the {@code Share} command of the floating actions. @@ -38,7 +37,8 @@ public class NewPipeEditText extends AppCompatEditText { @Override public boolean onTextContextMenuItem(final int id) { if (id == android.R.id.shareText) { - return shareSelectedTextWithShareUtils(this); + NewPipeTextViewHelper.shareSelectedTextWithShareUtils(this); + return true; } return super.onTextContextMenuItem(id); } diff --git a/app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java b/app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java index 75fb8f161..8fdac32db 100644 --- a/app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java +++ b/app/src/main/java/org/schabi/newpipe/views/NewPipeTextView.java @@ -7,10 +7,9 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.widget.AppCompatTextView; +import org.schabi.newpipe.util.NewPipeTextViewHelper; import org.schabi.newpipe.util.external_communication.ShareUtils; -import static org.schabi.newpipe.util.NewPipeTextViewHelper.shareSelectedTextWithShareUtils; - /** * An {@link AppCompatTextView} which uses {@link ShareUtils#shareText(Context, String, String)} * when sharing selected text by using the {@code Share} command of the floating actions. @@ -38,7 +37,8 @@ public class NewPipeTextView extends AppCompatTextView { @Override public boolean onTextContextMenuItem(final int id) { if (id == android.R.id.shareText) { - return shareSelectedTextWithShareUtils(this); + NewPipeTextViewHelper.shareSelectedTextWithShareUtils(this); + return true; } return super.onTextContextMenuItem(id); } From 5e25566b677910c53edbc47f6f6f35e081001daf Mon Sep 17 00:00:00 2001 From: TiA4f8R <74829229+TiA4f8R@users.noreply.github.com> Date: Sat, 16 Oct 2021 15:32:56 +0200 Subject: [PATCH 027/111] Adress new requested changes --- .../newpipe/util/NewPipeTextViewHelper.java | 28 +++---------------- 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java b/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java index 6db016090..cf1a9a03a 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java @@ -31,30 +31,10 @@ public final class NewPipeTextViewHelper { * {@link TextView standard TextViews} are supported). */ public static void shareSelectedTextWithShareUtils(@NonNull final TextView textView) { - if (!(textView instanceof NewPipeEditText)) { - final CharSequence textViewText; - if (textView instanceof NewPipeTextView) { - final NewPipeTextView newPipeTextView = (NewPipeTextView) textView; - textViewText = newPipeTextView.getText(); - } else { - textViewText = textView.getText(); - } - - final CharSequence selectedText = getSelectedText(textView, textViewText); - shareSelectedTextIfNotNullAndNotEmpty(textView, selectedText); - - final Spannable spannable = (textViewText instanceof Spannable) - ? (Spannable) textViewText : null; - if (spannable != null) { - Selection.setSelection(spannable, textView.getSelectionEnd()); - } - } else { - final NewPipeEditText editText = (NewPipeEditText) textView; - final Spannable text = editText.getText(); - - final CharSequence selectedText = getSelectedText(textView, text); - shareSelectedTextIfNotNullAndNotEmpty(textView, selectedText); - Selection.setSelection(text, editText.getSelectionEnd()); + final CharSequence textViewText = textView.getText(); + shareSelectedTextIfNotNullAndNotEmpty(textView, getSelectedText(textView, textViewText)); + if (textViewText instanceof Spannable) { + Selection.setSelection((Spannable) textViewText, textView.getSelectionEnd()); } } From 53cc6737bc22779dcd296a3a2cd41eb1182e932a Mon Sep 17 00:00:00 2001 From: TacoTheDank Date: Sat, 16 Oct 2021 15:33:45 -0400 Subject: [PATCH 028/111] Get rid of setUserVisibleHint --- .../java/org/schabi/newpipe/BaseFragment.java | 10 +--------- .../newpipe/fragments/BlankFragment.java | 4 ++-- .../list/channel/ChannelFragment.java | 8 +++----- .../fragments/list/kiosk/KioskFragment.java | 18 ++++++------------ .../local/bookmark/BookmarkFragment.java | 6 +++--- .../history/StatisticsPlaylistFragment.java | 6 +++--- .../SubscriptionsImportFragment.java | 8 +++----- 7 files changed, 21 insertions(+), 39 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/BaseFragment.java b/app/src/main/java/org/schabi/newpipe/BaseFragment.java index 0be427648..16ddb8376 100644 --- a/app/src/main/java/org/schabi/newpipe/BaseFragment.java +++ b/app/src/main/java/org/schabi/newpipe/BaseFragment.java @@ -21,7 +21,6 @@ public abstract class BaseFragment extends Fragment { //These values are used for controlling fragments when they are part of the frontpage @State protected boolean useAsFrontPage = false; - private boolean mIsVisibleToUser = false; public void useAsFrontPage(final boolean value) { useAsFrontPage = value; @@ -85,12 +84,6 @@ public abstract class BaseFragment extends Fragment { AppWatcher.INSTANCE.getObjectWatcher().watch(this); } - @Override - public void setUserVisibleHint(final boolean isVisibleToUser) { - super.setUserVisibleHint(isVisibleToUser); - mIsVisibleToUser = isVisibleToUser; - } - /*////////////////////////////////////////////////////////////////////////// // Init //////////////////////////////////////////////////////////////////////////*/ @@ -109,8 +102,7 @@ public abstract class BaseFragment extends Fragment { if (DEBUG) { Log.d(TAG, "setTitle() called with: title = [" + title + "]"); } - if ((!useAsFrontPage || mIsVisibleToUser) - && (activity != null && activity.getSupportActionBar() != null)) { + if (!useAsFrontPage && activity != null && activity.getSupportActionBar() != null) { activity.getSupportActionBar().setDisplayShowTitleEnabled(true); activity.getSupportActionBar().setTitle(title); } diff --git a/app/src/main/java/org/schabi/newpipe/fragments/BlankFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/BlankFragment.java index 0cccfa4fe..fe4eef37a 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/BlankFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/BlankFragment.java @@ -20,8 +20,8 @@ public class BlankFragment extends BaseFragment { } @Override - public void setUserVisibleHint(final boolean isVisibleToUser) { - super.setUserVisibleHint(isVisibleToUser); + public void onResume() { + super.onResume(); setTitle("NewPipe"); // leave this inline. Will make it harder for copy cats. // If you are a Copy cat FUCK YOU. diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java index 1d16559ac..30e38a966 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java @@ -98,11 +98,9 @@ public class ChannelFragment extends BaseListInfoFragment } @Override - public void setUserVisibleHint(final boolean isVisibleToUser) { - super.setUserVisibleHint(isVisibleToUser); - if (activity != null - && useAsFrontPage - && isVisibleToUser) { + public void onResume() { + super.onResume(); + if (activity != null && useAsFrontPage) { setTitle(currentInfo != null ? currentInfo.getName() : name); } } diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/kiosk/KioskFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/kiosk/KioskFragment.java index f37f487bf..c25f18e8b 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/kiosk/KioskFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/kiosk/KioskFragment.java @@ -99,9 +99,12 @@ public class KioskFragment extends BaseListInfoFragment { } @Override - public void setUserVisibleHint(final boolean isVisibleToUser) { - super.setUserVisibleHint(isVisibleToUser); - if (useAsFrontPage && isVisibleToUser && activity != null) { + public void onResume() { + super.onResume(); + if (!Localization.getPreferredContentCountry(requireContext()).equals(contentCountry)) { + reloadContent(); + } + if (useAsFrontPage && activity != null) { try { setTitle(kioskTranslatedName); } catch (final Exception e) { @@ -117,15 +120,6 @@ public class KioskFragment extends BaseListInfoFragment { return inflater.inflate(R.layout.fragment_kiosk, container, false); } - @Override - public void onResume() { - super.onResume(); - - if (!Localization.getPreferredContentCountry(requireContext()).equals(contentCountry)) { - reloadContent(); - } - } - /*////////////////////////////////////////////////////////////////////////// // Menu //////////////////////////////////////////////////////////////////////////*/ diff --git a/app/src/main/java/org/schabi/newpipe/local/bookmark/BookmarkFragment.java b/app/src/main/java/org/schabi/newpipe/local/bookmark/BookmarkFragment.java index 794e5a33a..f272a8831 100644 --- a/app/src/main/java/org/schabi/newpipe/local/bookmark/BookmarkFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/bookmark/BookmarkFragment.java @@ -78,9 +78,9 @@ public final class BookmarkFragment extends BaseLocalListFragment Date: Sat, 16 Oct 2021 16:04:51 -0400 Subject: [PATCH 029/111] Clean up .gitignore files --- .gitignore | 16 ++++++++-------- app/.gitignore | 3 --- 2 files changed, 8 insertions(+), 11 deletions(-) delete mode 100644 app/.gitignore diff --git a/.gitignore b/.gitignore index 5c6962be1..40e7d2c03 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,15 @@ -.gitignore -.gradle -/local.properties +.gradle/ +local.properties .DS_Store -/build -/captures -/app/app.iml -/.idea -/*.iml +build/ +captures/ +.idea/ +*.iml *~ .weblate *.class +**/debug/ +**/release/ # vscode / eclipse files *.classpath diff --git a/app/.gitignore b/app/.gitignore deleted file mode 100644 index 53edac5e4..000000000 --- a/app/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.gitignore -/build -*.iml From 8f7a36dc4888f78aab80f6250d32db60b3ac0576 Mon Sep 17 00:00:00 2001 From: TacoTheDank Date: Tue, 19 Oct 2021 17:31:59 -0400 Subject: [PATCH 030/111] Update RecyclerView & Groupie --- app/build.gradle | 7 +++++-- .../schabi/newpipe/fragments/list/BaseListFragment.java | 2 +- .../newpipe/fragments/list/search/SearchFragment.java | 4 ++-- .../newpipe/local/playlist/LocalPlaylistFragment.java | 4 ++-- .../local/subscription/dialog/FeedGroupReorderDialog.kt | 4 ++-- .../player/playqueue/PlayQueueItemTouchCallback.java | 2 +- .../newpipe/settings/PeertubeInstanceListFragment.java | 6 +++--- .../schabi/newpipe/settings/tabs/ChooseTabsFragment.java | 6 +++--- 8 files changed, 19 insertions(+), 16 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 970cfa89d..f13483012 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -107,7 +107,7 @@ ext { icepickVersion = '3.2.0' exoPlayerVersion = '2.12.3' googleAutoServiceVersion = '1.0' - groupieVersion = '2.9.0' + groupieVersion = '2.10.0' markwonVersion = '4.6.2' leakCanaryVersion = '2.5' @@ -211,11 +211,14 @@ dependencies { implementation 'androidx.media:media:1.4.2' implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.preference:preference:1.1.1' - implementation 'androidx.recyclerview:recyclerview:1.1.0' + implementation 'androidx.recyclerview:recyclerview:1.2.1' implementation "androidx.room:room-runtime:${androidxRoomVersion}" implementation "androidx.room:room-rxjava3:${androidxRoomVersion}" kapt "androidx.room:room-compiler:${androidxRoomVersion}" implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' + // Newer version specified to prevent accessibility regressions with RecyclerView, see: + // https://developer.android.com/jetpack/androidx/releases/viewpager2#1.1.0-alpha01 + implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01' implementation 'androidx.webkit:webkit:1.4.0' implementation 'com.google.android.material:material:1.2.1' diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java index c30b6fc05..037eb8f94 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java @@ -143,7 +143,7 @@ public abstract class BaseListFragment extends BaseStateFragment final View focusedItem = itemsList.getFocusedChild(); final RecyclerView.ViewHolder itemHolder = itemsList.findContainingViewHolder(focusedItem); - return itemHolder.getAdapterPosition(); + return itemHolder.getBindingAdapterPosition(); } catch (final NullPointerException e) { return -1; } diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java index 7de212383..d4d73f74f 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java @@ -1088,7 +1088,7 @@ public class SearchFragment extends BaseListFragment Date: Tue, 19 Oct 2021 17:36:36 -0400 Subject: [PATCH 031/111] Update AndroidX Media library --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 970cfa89d..bb269eef0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -208,7 +208,7 @@ dependencies { implementation "androidx.lifecycle:lifecycle-livedata:${androidxLifecycleVersion}" implementation "androidx.lifecycle:lifecycle-viewmodel:${androidxLifecycleVersion}" implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0' - implementation 'androidx.media:media:1.4.2' + implementation 'androidx.media:media:1.4.3' implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.preference:preference:1.1.1' implementation 'androidx.recyclerview:recyclerview:1.1.0' From 79165d349c7820745a97505b44a83b66069f9e27 Mon Sep 17 00:00:00 2001 From: TacoTheDank Date: Tue, 19 Oct 2021 17:39:38 -0400 Subject: [PATCH 032/111] Update pager workaround to Fragment 1.3.6 --- ...agmentStatePagerAdapterMenuWorkaround.java | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/androidx/fragment/app/FragmentStatePagerAdapterMenuWorkaround.java b/app/src/main/java/androidx/fragment/app/FragmentStatePagerAdapterMenuWorkaround.java index 433c155c2..639443377 100644 --- a/app/src/main/java/androidx/fragment/app/FragmentStatePagerAdapterMenuWorkaround.java +++ b/app/src/main/java/androidx/fragment/app/FragmentStatePagerAdapterMenuWorkaround.java @@ -51,8 +51,12 @@ import java.util.ArrayList; *
  • {@link #saveState()}
  • *
  • {@link #restoreState(Parcelable, ClassLoader)}
  • * + * + * @deprecated Switch to {@link androidx.viewpager2.widget.ViewPager2} and use + * {@link androidx.viewpager2.adapter.FragmentStateAdapter} instead. */ @SuppressWarnings("deprecation") +@Deprecated public abstract class FragmentStatePagerAdapterMenuWorkaround extends PagerAdapter { private static final String TAG = "FragmentStatePagerAdapt"; private static final boolean DEBUG = false; @@ -86,9 +90,10 @@ public abstract class FragmentStatePagerAdapterMenuWorkaround extends PagerAdapt private final int mBehavior; private FragmentTransaction mCurTransaction = null; - private final ArrayList mSavedState = new ArrayList(); - private final ArrayList mFragments = new ArrayList(); + private final ArrayList mSavedState = new ArrayList<>(); + private final ArrayList mFragments = new ArrayList<>(); private Fragment mCurrentPrimaryItem = null; + private boolean mExecutingFinishUpdate; /** * Constructor for {@link FragmentStatePagerAdapterMenuWorkaround} @@ -208,7 +213,7 @@ public abstract class FragmentStatePagerAdapterMenuWorkaround extends PagerAdapt mFragments.set(position, null); mCurTransaction.remove(fragment); - if (fragment == mCurrentPrimaryItem) { + if (fragment.equals(mCurrentPrimaryItem)) { mCurrentPrimaryItem = null; } } @@ -247,7 +252,19 @@ public abstract class FragmentStatePagerAdapterMenuWorkaround extends PagerAdapt @Override public void finishUpdate(@NonNull final ViewGroup container) { if (mCurTransaction != null) { - mCurTransaction.commitNowAllowingStateLoss(); + // We drop any transactions that attempt to be committed + // from a re-entrant call to finishUpdate(). We need to + // do this as a workaround for Robolectric running measure/layout + // calls inline rather than allowing them to be posted + // as they would on a real device. + if (!mExecutingFinishUpdate) { + try { + mExecutingFinishUpdate = true; + mCurTransaction.commitNowAllowingStateLoss(); + } finally { + mExecutingFinishUpdate = false; + } + } mCurTransaction = null; } } From 085df96ad8033908ebb5213876cd1cc44b6aaf9e Mon Sep 17 00:00:00 2001 From: 0x416c6578 <14030169+0x416c6578@users.noreply.github.com> Date: Wed, 4 Aug 2021 14:33:40 +0100 Subject: [PATCH 033/111] Fixed shuffle button opacity bug Parameterised shuffle state into initPlayback for potentially passing the shuffle state into the player in the future --- .../main/java/org/schabi/newpipe/player/Player.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 22e66e793..fa63b0345 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -635,6 +635,7 @@ public final class Player implements final int repeatMode = intent.getIntExtra(REPEAT_MODE, getRepeatMode()); final boolean playWhenReady = intent.getBooleanExtra(PLAY_WHEN_READY, true); final boolean isMuted = intent.getBooleanExtra(IS_MUTED, isMuted()); + final boolean shuffleMode = false; //Set the default shuffle mode to disabled /* * There are 3 situations when playback shouldn't be started from scratch (zero timestamp): @@ -691,7 +692,7 @@ public final class Player implements state.getProgressMillis()); } initPlayback(newQueue, repeatMode, playbackSpeed, playbackPitch, - playbackSkipSilence, playWhenReady, isMuted); + playbackSkipSilence, playWhenReady, isMuted, shuffleMode); }, error -> { if (DEBUG) { @@ -699,19 +700,19 @@ public final class Player implements } // In case any error we can start playback without history initPlayback(newQueue, repeatMode, playbackSpeed, playbackPitch, - playbackSkipSilence, playWhenReady, isMuted); + playbackSkipSilence, playWhenReady, isMuted, shuffleMode); }, () -> { // Completed but not found in history initPlayback(newQueue, repeatMode, playbackSpeed, playbackPitch, - playbackSkipSilence, playWhenReady, isMuted); + playbackSkipSilence, playWhenReady, isMuted, shuffleMode); } )); } else { // Good to go... // In a case of equal PlayQueues we can re-init old one but only when it is disposed initPlayback(samePlayQueue ? playQueue : newQueue, repeatMode, playbackSpeed, - playbackPitch, playbackSkipSilence, playWhenReady, isMuted); + playbackPitch, playbackSkipSilence, playWhenReady, isMuted, shuffleMode); } if (oldPlayerType != playerType && playQueue != null) { @@ -770,10 +771,12 @@ public final class Player implements final float playbackPitch, final boolean playbackSkipSilence, final boolean playOnReady, - final boolean isMuted) { + final boolean isMuted, + final boolean shuffleEnabled) { destroyPlayer(); initPlayer(playOnReady); setRepeatMode(repeatMode); + onShuffleModeEnabledChanged(shuffleEnabled); setPlaybackParameters(playbackSpeed, playbackPitch, playbackSkipSilence); playQueue = queue; From 128b079f4f809158e8d33b1ad2c33e0fe7b4530e Mon Sep 17 00:00:00 2001 From: 0x416c6578 <14030169+0x416c6578@users.noreply.github.com> Date: Wed, 4 Aug 2021 17:21:50 +0100 Subject: [PATCH 034/111] Removed changes to the intent handler --- .../java/org/schabi/newpipe/player/Player.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index fa63b0345..edfcb35e4 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -635,7 +635,6 @@ public final class Player implements final int repeatMode = intent.getIntExtra(REPEAT_MODE, getRepeatMode()); final boolean playWhenReady = intent.getBooleanExtra(PLAY_WHEN_READY, true); final boolean isMuted = intent.getBooleanExtra(IS_MUTED, isMuted()); - final boolean shuffleMode = false; //Set the default shuffle mode to disabled /* * There are 3 situations when playback shouldn't be started from scratch (zero timestamp): @@ -692,7 +691,7 @@ public final class Player implements state.getProgressMillis()); } initPlayback(newQueue, repeatMode, playbackSpeed, playbackPitch, - playbackSkipSilence, playWhenReady, isMuted, shuffleMode); + playbackSkipSilence, playWhenReady, isMuted); }, error -> { if (DEBUG) { @@ -700,19 +699,19 @@ public final class Player implements } // In case any error we can start playback without history initPlayback(newQueue, repeatMode, playbackSpeed, playbackPitch, - playbackSkipSilence, playWhenReady, isMuted, shuffleMode); + playbackSkipSilence, playWhenReady, isMuted); }, () -> { // Completed but not found in history initPlayback(newQueue, repeatMode, playbackSpeed, playbackPitch, - playbackSkipSilence, playWhenReady, isMuted, shuffleMode); + playbackSkipSilence, playWhenReady, isMuted); } )); } else { // Good to go... // In a case of equal PlayQueues we can re-init old one but only when it is disposed initPlayback(samePlayQueue ? playQueue : newQueue, repeatMode, playbackSpeed, - playbackPitch, playbackSkipSilence, playWhenReady, isMuted, shuffleMode); + playbackPitch, playbackSkipSilence, playWhenReady, isMuted); } if (oldPlayerType != playerType && playQueue != null) { @@ -771,12 +770,11 @@ public final class Player implements final float playbackPitch, final boolean playbackSkipSilence, final boolean playOnReady, - final boolean isMuted, - final boolean shuffleEnabled) { + final boolean isMuted) { destroyPlayer(); initPlayer(playOnReady); setRepeatMode(repeatMode); - onShuffleModeEnabledChanged(shuffleEnabled); + onShuffleModeEnabledChanged(false); setPlaybackParameters(playbackSpeed, playbackPitch, playbackSkipSilence); playQueue = queue; From be83a6bd0e68143abeef2ae57fa5cdded5abfd94 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sat, 23 Oct 2021 16:46:56 +0200 Subject: [PATCH 035/111] Fixing the shuffle button on the UI is enough. No need for doing the heavier method ``onShuffleModeEnabledChanged(false);`` --- app/src/main/java/org/schabi/newpipe/player/Player.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index edfcb35e4..5435b9f81 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -774,7 +774,8 @@ public final class Player implements destroyPlayer(); initPlayer(playOnReady); setRepeatMode(repeatMode); - onShuffleModeEnabledChanged(false); + // #6825 - Ensure that the shuffle-button is in the correct state on the UI + setShuffleButton(binding.shuffleButton, simpleExoPlayer.getShuffleModeEnabled()); setPlaybackParameters(playbackSpeed, playbackPitch, playbackSkipSilence); playQueue = queue; From 1625c4b2a721c2697b2cc3e7b72782e027ef6430 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sat, 23 Oct 2021 17:35:42 +0200 Subject: [PATCH 036/111] Always create a backup list when shuffling The backup-list has to be created at all cost (even when current list size <= 2). Otherwise it's not possible to enter shuffle-mode (as ``isShuffled()`` always returns false)! --- .../org/schabi/newpipe/player/playqueue/PlayQueue.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueue.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueue.java index 014c13339..76fed8e9e 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueue.java +++ b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueue.java @@ -436,14 +436,16 @@ public abstract class PlayQueue implements Serializable { * top, so shuffling a size-2 list does nothing) */ public synchronized void shuffle() { + // Create a backup if it doesn't already exist + // Note: The backup-list has to be created at all cost (even when size <= 2). + // Otherwise it's not possible to enter shuffle-mode! + if (backup == null) { + backup = new ArrayList<>(streams); + } // Can't shuffle an list that's empty or only has one element if (size() <= 2) { return; } - // Create a backup if it doesn't already exist - if (backup == null) { - backup = new ArrayList<>(streams); - } final int originalIndex = getIndex(); final PlayQueueItem currentItem = getItem(); From e84e19a27194c3f1e0eaf870cd0fd1b423a1937b Mon Sep 17 00:00:00 2001 From: mhmdanas Date: Sat, 23 Oct 2021 23:14:25 +0300 Subject: [PATCH 037/111] Add support for y2u.be links --- app/build.gradle | 2 +- app/src/main/AndroidManifest.xml | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 6510b31ab..6f2f24832 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -189,7 +189,7 @@ dependencies { // name and the commit hash with the commit hash of the (pushed) commit you want to test // This works thanks to JitPack: https://jitpack.io/ implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751' - implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.21.11' + implementation 'com.github.TeamNewPipe:mhmdanas:3e8e2a1532681321c7c349342e032414baee5051' /** Checkstyle **/ checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d92d0b5bf..6a2700596 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -256,6 +256,21 @@ + + + + + + + + + + + + + + + From b43332a80795e6b52a82dc37f9523501cca478fb Mon Sep 17 00:00:00 2001 From: Mohammed Anas Date: Sat, 23 Oct 2021 20:30:04 +0000 Subject: [PATCH 038/111] Fix extractor dependency --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 6f2f24832..8da3bc596 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -189,7 +189,7 @@ dependencies { // name and the commit hash with the commit hash of the (pushed) commit you want to test // This works thanks to JitPack: https://jitpack.io/ implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751' - implementation 'com.github.TeamNewPipe:mhmdanas:3e8e2a1532681321c7c349342e032414baee5051' + implementation 'com.github.mhmdanas:NewPipeExtractor:3e8e2a1532681321c7c349342e032414baee5051' /** Checkstyle **/ checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}" From 85b9080aa6785db6a686983d8f783797d1ab2e25 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Tue, 26 Oct 2021 18:47:48 +0200 Subject: [PATCH 039/111] Changed extractor dependency back to TeamNewPipe ...as the required PR was merged. --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 8da3bc596..880e93d26 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -189,7 +189,7 @@ dependencies { // name and the commit hash with the commit hash of the (pushed) commit you want to test // This works thanks to JitPack: https://jitpack.io/ implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751' - implementation 'com.github.mhmdanas:NewPipeExtractor:3e8e2a1532681321c7c349342e032414baee5051' + implementation 'com.github.TeamNewPipe:NewPipeExtractor:4f60225ddc8a29e7a36a4ed77d73b713ba3451d9' /** Checkstyle **/ checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}" From 108a97645b711f59e82635791bed2eecc89858f4 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Tue, 26 Oct 2021 19:07:54 +0200 Subject: [PATCH 040/111] Try to fix jitpack not resolving dependency --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 880e93d26..2cbf3d9e5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -189,7 +189,7 @@ dependencies { // name and the commit hash with the commit hash of the (pushed) commit you want to test // This works thanks to JitPack: https://jitpack.io/ implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751' - implementation 'com.github.TeamNewPipe:NewPipeExtractor:4f60225ddc8a29e7a36a4ed77d73b713ba3451d9' + implementation 'com.github.TeamNewPipe:NewPipeExtractor:4f60225ddc' /** Checkstyle **/ checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}" From 66d7c282ca7791aa96b2c36bd740915faa1de77f Mon Sep 17 00:00:00 2001 From: vhouriet Date: Fri, 22 Oct 2021 21:07:53 +0200 Subject: [PATCH 041/111] Add Check for updates button --- .../newpipe/settings/MainSettingsFragment.java | 7 +++++-- .../newpipe/settings/UpdateSettingsFragment.java | 13 +++++++++++++ app/src/main/res/values/settings_keys.xml | 1 + app/src/main/res/values/strings.xml | 2 ++ app/src/main/res/xml/update_settings.xml | 7 +++++++ 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java index 2f65af4d6..0eebfb5a2 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java @@ -17,8 +17,11 @@ public class MainSettingsFragment extends BasePreferenceFragment { addPreferencesFromResource(R.xml.main_settings); if (!CheckForNewAppVersion.isGithubApk(App.getApp())) { - final Preference update = findPreference(getString(R.string.update_pref_screen_key)); - getPreferenceScreen().removePreference(update); + if (!DEBUG) { + final Preference update + = findPreference(getString(R.string.update_pref_screen_key)); + getPreferenceScreen().removePreference(update); + } defaultPreferences.edit().putBoolean(getString(R.string.update_app_key), false).apply(); } diff --git a/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java index d2f56b487..0fdf96757 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java @@ -1,5 +1,7 @@ package org.schabi.newpipe.settings; +import android.content.Intent; +import android.net.Uri; import android.os.Bundle; import androidx.preference.Preference; @@ -9,6 +11,8 @@ import org.schabi.newpipe.R; import static org.schabi.newpipe.CheckForNewAppVersion.startNewVersionCheckService; public class UpdateSettingsFragment extends BasePreferenceFragment { + private static final String RELEASES_URL = "https://github.com/TeamNewPipe/NewPipe/releases"; + private final Preference.OnPreferenceChangeListener updatePreferenceChange = (preference, checkForUpdates) -> { defaultPreferences.edit() @@ -24,11 +28,20 @@ public class UpdateSettingsFragment extends BasePreferenceFragment { return true; }; + private final Preference.OnPreferenceClickListener manualUpdateClick + = preference -> { + final Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(RELEASES_URL)); + startActivity(browserIntent); + return true; + }; + @Override public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) { addPreferencesFromResource(R.xml.update_settings); final String updateToggleKey = getString(R.string.update_app_key); + final String manualUpdateKey = getString(R.string.manual_update_key); findPreference(updateToggleKey).setOnPreferenceChangeListener(updatePreferenceChange); + findPreference(manualUpdateKey).setOnPreferenceClickListener(manualUpdateClick); } } diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index 9489ef543..1c57178b4 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -383,6 +383,7 @@ update_app_key + manual_update_key update_pref_screen_key update_expiry_key diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 897ec0af8..9ab2d2643 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -517,6 +517,8 @@ Updates Show a notification to prompt app update when a new version is available + Check for updates + Manually check for new versions Minimize on app switch Action when switching to other app from main video player — %s diff --git a/app/src/main/res/xml/update_settings.xml b/app/src/main/res/xml/update_settings.xml index adaa47352..ef121ec4e 100644 --- a/app/src/main/res/xml/update_settings.xml +++ b/app/src/main/res/xml/update_settings.xml @@ -12,4 +12,11 @@ app:singleLineTitle="false" app:iconSpaceReserved="false" /> + + From e6db2b70f885f298721d371a8f15bb0ce01c4c70 Mon Sep 17 00:00:00 2001 From: vhouriet Date: Sat, 23 Oct 2021 21:09:53 +0200 Subject: [PATCH 042/111] Change check for updates button to trigger a version check --- .../schabi/newpipe/CheckForNewAppVersion.java | 6 ++--- .../java/org/schabi/newpipe/MainActivity.java | 14 +++++++---- .../settings/MainSettingsFragment.java | 8 +++---- .../settings/UpdateSettingsFragment.java | 23 ++++++++++--------- app/src/main/res/values/strings.xml | 1 + 5 files changed, 29 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java index 9c392be1e..7e5eb0f77 100644 --- a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java +++ b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java @@ -175,9 +175,8 @@ public final class CheckForNewAppVersion extends IntentService { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(app); final NewVersionManager manager = new NewVersionManager(); - // Check if user has enabled/disabled update checking - // and if the current apk is a github one or not. - if (!prefs.getBoolean(app.getString(R.string.update_app_key), true) || !isGithubApk(app)) { + // Check if the current apk is a github one or not. + if (!isGithubApk(app)) { return; } @@ -213,6 +212,7 @@ public final class CheckForNewAppVersion extends IntentService { // Parse the json from the response. try { + final JsonObject githubStableObject = JsonParser.object() .from(response.responseBody()).getObject("flavors") .getObject("github").getObject("stable"); diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 1855d45cd..0a49e00e4 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -169,10 +169,16 @@ public class MainActivity extends AppCompatActivity { @Override protected void onPostCreate(final Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); - // Start the service which is checking all conditions - // and eventually searching for a new version. - // The service searching for a new NewPipe version must not be started in background. - startNewVersionCheckService(); + + final App app = App.getApp(); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(app); + + if (prefs.getBoolean(app.getString(R.string.update_app_key), true)) { + // Start the service which is checking all conditions + // and eventually searching for a new version. + // The service searching for a new NewPipe version must not be started in background. + startNewVersionCheckService(); + } } private void setupDrawer() throws ExtractionException { diff --git a/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java index 0eebfb5a2..4d847056e 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java @@ -17,11 +17,9 @@ public class MainSettingsFragment extends BasePreferenceFragment { addPreferencesFromResource(R.xml.main_settings); if (!CheckForNewAppVersion.isGithubApk(App.getApp())) { - if (!DEBUG) { - final Preference update - = findPreference(getString(R.string.update_pref_screen_key)); - getPreferenceScreen().removePreference(update); - } + final Preference update + = findPreference(getString(R.string.update_pref_screen_key)); + getPreferenceScreen().removePreference(update); defaultPreferences.edit().putBoolean(getString(R.string.update_app_key), false).apply(); } diff --git a/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java index 0fdf96757..339f6571b 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java @@ -1,8 +1,7 @@ package org.schabi.newpipe.settings; -import android.content.Intent; -import android.net.Uri; import android.os.Bundle; +import android.widget.Toast; import androidx.preference.Preference; @@ -11,30 +10,32 @@ import org.schabi.newpipe.R; import static org.schabi.newpipe.CheckForNewAppVersion.startNewVersionCheckService; public class UpdateSettingsFragment extends BasePreferenceFragment { - private static final String RELEASES_URL = "https://github.com/TeamNewPipe/NewPipe/releases"; - private final Preference.OnPreferenceChangeListener updatePreferenceChange = (preference, checkForUpdates) -> { defaultPreferences.edit() .putBoolean(getString(R.string.update_app_key), (boolean) checkForUpdates).apply(); if ((boolean) checkForUpdates) { - // Search for updates immediately when update checks are enabled. - // Reset the expire time. This is necessary to check for an update immediately. - defaultPreferences.edit() - .putLong(getString(R.string.update_expiry_key), 0).apply(); - startNewVersionCheckService(); + checkNewVersionNow(); } return true; }; private final Preference.OnPreferenceClickListener manualUpdateClick = preference -> { - final Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(RELEASES_URL)); - startActivity(browserIntent); + Toast.makeText(getContext(), R.string.checking_updates_toast, Toast.LENGTH_SHORT).show(); + checkNewVersionNow(); return true; }; + private void checkNewVersionNow() { + // Search for updates immediately when update checks are enabled. + // Reset the expire time. This is necessary to check for an update immediately. + defaultPreferences.edit() + .putLong(getString(R.string.update_expiry_key), 0).apply(); + startNewVersionCheckService(); + } + @Override public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) { addPreferencesFromResource(R.xml.update_settings); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9ab2d2643..2ad07b4c5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -549,6 +549,7 @@ recovering Queue Action denied by the system + Checking for updates… Download failed From 18626566dbd38e6a42f61a1d6f2234ebed0bdf77 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Tue, 26 Oct 2021 19:23:48 +0200 Subject: [PATCH 043/111] Cleanup up some code --- .../settings/UpdateSettingsFragment.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java index 339f6571b..bc183d08a 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java @@ -1,5 +1,7 @@ package org.schabi.newpipe.settings; +import static org.schabi.newpipe.CheckForNewAppVersion.startNewVersionCheckService; + import android.os.Bundle; import android.widget.Toast; @@ -7,17 +9,15 @@ import androidx.preference.Preference; import org.schabi.newpipe.R; -import static org.schabi.newpipe.CheckForNewAppVersion.startNewVersionCheckService; - public class UpdateSettingsFragment extends BasePreferenceFragment { private final Preference.OnPreferenceChangeListener updatePreferenceChange = (preference, checkForUpdates) -> { defaultPreferences.edit() .putBoolean(getString(R.string.update_app_key), (boolean) checkForUpdates).apply(); - if ((boolean) checkForUpdates) { - checkNewVersionNow(); - } + if ((boolean) checkForUpdates) { + checkNewVersionNow(); + } return true; }; @@ -40,9 +40,9 @@ public class UpdateSettingsFragment extends BasePreferenceFragment { public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) { addPreferencesFromResource(R.xml.update_settings); - final String updateToggleKey = getString(R.string.update_app_key); - final String manualUpdateKey = getString(R.string.manual_update_key); - findPreference(updateToggleKey).setOnPreferenceChangeListener(updatePreferenceChange); - findPreference(manualUpdateKey).setOnPreferenceClickListener(manualUpdateClick); + findPreference(getString(R.string.update_app_key)) + .setOnPreferenceChangeListener(updatePreferenceChange); + findPreference(getString(R.string.manual_update_key)) + .setOnPreferenceClickListener(manualUpdateClick); } } From 0c42ec715b2eca2fe379bc09647eacf7ff21e0c7 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Tue, 26 Oct 2021 19:26:47 +0200 Subject: [PATCH 044/111] Removed dead code --- .../java/org/schabi/newpipe/CheckForNewAppVersion.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java index 7e5eb0f77..76cd2988a 100644 --- a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java +++ b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java @@ -7,7 +7,6 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.pm.Signature; -import android.net.ConnectivityManager; import android.net.Uri; import android.util.Log; @@ -15,7 +14,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; -import androidx.core.content.ContextCompat; import androidx.core.content.pm.PackageInfoCompat; import androidx.preference.PreferenceManager; @@ -158,13 +156,6 @@ public final class CheckForNewAppVersion extends IntentService { } } - private static boolean isConnected(@NonNull final App app) { - final ConnectivityManager connectivityManager = - ContextCompat.getSystemService(app, ConnectivityManager.class); - return connectivityManager != null && connectivityManager.getActiveNetworkInfo() != null - && connectivityManager.getActiveNetworkInfo().isConnected(); - } - public static boolean isGithubApk(@NonNull final App app) { return getCertificateSHA1Fingerprint(app).equals(GITHUB_APK_SHA1); } From d2422ef94d665d9cce0a118a2d45efa82391d281 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Tue, 26 Oct 2021 20:25:09 +0200 Subject: [PATCH 045/111] Make naming great again When we build APKs in PRs it's also a GITHUB_APK... --- .../java/org/schabi/newpipe/CheckForNewAppVersion.java | 9 +++++---- .../schabi/newpipe/settings/MainSettingsFragment.java | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java index 76cd2988a..173a24ab7 100644 --- a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java +++ b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java @@ -46,7 +46,8 @@ public final class CheckForNewAppVersion extends IntentService { private static final boolean DEBUG = MainActivity.DEBUG; private static final String TAG = CheckForNewAppVersion.class.getSimpleName(); - private static final String GITHUB_APK_SHA1 + // Public key of the certificate that is used in NewPipe release versions + private static final String RELEASE_CERT_PUBLIC_KEY_SHA1 = "B0:2E:90:7C:1C:D6:FC:57:C3:35:F0:88:D0:8F:50:5F:94:E4:D2:15"; private static final String NEWPIPE_API_URL = "https://newpipe.net/api/data.json"; @@ -156,8 +157,8 @@ public final class CheckForNewAppVersion extends IntentService { } } - public static boolean isGithubApk(@NonNull final App app) { - return getCertificateSHA1Fingerprint(app).equals(GITHUB_APK_SHA1); + public static boolean isReleaseApk(@NonNull final App app) { + return getCertificateSHA1Fingerprint(app).equals(RELEASE_CERT_PUBLIC_KEY_SHA1); } private void checkNewVersion() throws IOException, ReCaptchaException { @@ -167,7 +168,7 @@ public final class CheckForNewAppVersion extends IntentService { final NewVersionManager manager = new NewVersionManager(); // Check if the current apk is a github one or not. - if (!isGithubApk(app)) { + if (!isReleaseApk(app)) { return; } diff --git a/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java index 4d847056e..12599b828 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java @@ -16,7 +16,7 @@ public class MainSettingsFragment extends BasePreferenceFragment { public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) { addPreferencesFromResource(R.xml.main_settings); - if (!CheckForNewAppVersion.isGithubApk(App.getApp())) { + if (!CheckForNewAppVersion.isReleaseApk(App.getApp())) { final Preference update = findPreference(getString(R.string.update_pref_screen_key)); getPreferenceScreen().removePreference(update); From 4bf5c733bd1aa955ef535016258754a47d36ea3d Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Tue, 26 Oct 2021 20:29:03 +0200 Subject: [PATCH 046/111] Less indents and code -> better readable Also removed a useless variable --- .../schabi/newpipe/CheckForNewAppVersion.java | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java index 173a24ab7..9e43394ac 100644 --- a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java +++ b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java @@ -128,33 +128,33 @@ public final class CheckForNewAppVersion extends IntentService { final String versionName, final String apkLocationUrl, final int versionCode) { - final int notificationId = 2000; - - if (BuildConfig.VERSION_CODE < versionCode) { - // A pending intent to open the apk location url in the browser. - final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(apkLocationUrl)); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - final PendingIntent pendingIntent - = PendingIntent.getActivity(application, 0, intent, 0); - - final String channelId = application - .getString(R.string.app_update_notification_channel_id); - final NotificationCompat.Builder notificationBuilder - = new NotificationCompat.Builder(application, channelId) - .setSmallIcon(R.drawable.ic_newpipe_update) - .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) - .setContentIntent(pendingIntent) - .setAutoCancel(true) - .setContentTitle(application - .getString(R.string.app_update_notification_content_title)) - .setContentText(application - .getString(R.string.app_update_notification_content_text) - + " " + versionName); - - final NotificationManagerCompat notificationManager - = NotificationManagerCompat.from(application); - notificationManager.notify(notificationId, notificationBuilder.build()); + if (BuildConfig.VERSION_CODE >= versionCode) { + return; } + + // A pending intent to open the apk location url in the browser. + final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(apkLocationUrl)); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + final PendingIntent pendingIntent + = PendingIntent.getActivity(application, 0, intent, 0); + + final String channelId = application + .getString(R.string.app_update_notification_channel_id); + final NotificationCompat.Builder notificationBuilder + = new NotificationCompat.Builder(application, channelId) + .setSmallIcon(R.drawable.ic_newpipe_update) + .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) + .setContentIntent(pendingIntent) + .setAutoCancel(true) + .setContentTitle(application + .getString(R.string.app_update_notification_content_title)) + .setContentText(application + .getString(R.string.app_update_notification_content_text) + + " " + versionName); + + final NotificationManagerCompat notificationManager + = NotificationManagerCompat.from(application); + notificationManager.notify(2000, notificationBuilder.build()); } public static boolean isReleaseApk(@NonNull final App app) { From 4efd60e80cea5f3518a0cfcc9fcf35145939d04b Mon Sep 17 00:00:00 2001 From: TiA4f8R <74829229+TiA4f8R@users.noreply.github.com> Date: Tue, 2 Nov 2021 17:53:27 +0100 Subject: [PATCH 047/111] Unrevert PR 6824 PR 7061 reverted by mistake PR 6824 (it was a rebase issue). This commit unreverts this change and uses custom TextViews correctly in the file changed by PR 6824. --- .../layout/activity_player_queue_control.xml | 120 +++++++++--------- 1 file changed, 57 insertions(+), 63 deletions(-) diff --git a/app/src/main/res/layout/activity_player_queue_control.xml b/app/src/main/res/layout/activity_player_queue_control.xml index e4eacb0e2..24e062932 100644 --- a/app/src/main/res/layout/activity_player_queue_control.xml +++ b/app/src/main/res/layout/activity_player_queue_control.xml @@ -31,84 +31,78 @@ android:id="@+id/play_queue" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_above="@id/center" + android:layout_above="@id/metadata" android:layout_below="@id/appbar" android:scrollbars="vertical" app:layoutManager="LinearLayoutManager" tools:listitem="@layout/play_queue_item" /> - + + - - - - - - - + android:layout_above="@id/progress_bar" + android:background="?attr/selectableItemBackground" + android:clickable="true" + android:focusable="true" + android:orientation="vertical" + android:padding="8dp" + tools:ignore="RtlHardcoded,RtlSymmetry"> - + android:ellipsize="marquee" + android:fadingEdge="horizontal" + android:marqueeRepeatLimit="marquee_forever" + android:scrollHorizontally="true" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceLarge" + android:textSize="14sp" + tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis nec aliquam augue, eget cursus est. Ut id tristique enim, ut scelerisque tellus. Sed ultricies ipsum non mauris ultricies, commodo malesuada velit porta." /> + + + + android:paddingRight="12dp" + android:layout_above="@+id/playback_controls"> - From bea39a14eae58d1112c2fa8f0ca2ef2ab0e868ea Mon Sep 17 00:00:00 2001 From: bopol Date: Wed, 3 Nov 2021 14:49:17 +0100 Subject: [PATCH 048/111] Support PeerTube short links --- app/build.gradle | 2 +- app/src/main/AndroidManifest.xml | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index c95699fb9..84054265a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -189,7 +189,7 @@ dependencies { // name and the commit hash with the commit hash of the (pushed) commit you want to test // This works thanks to JitPack: https://jitpack.io/ implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751' - implementation 'com.github.TeamNewPipe:NewPipeExtractor:4f60225ddc' + implementation 'com.github.B0pol:NewPipeExtractor:396aecef19ea61de9915727abd71aa55ef75549f' /** Checkstyle **/ checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6a2700596..cc631af7a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -340,8 +340,12 @@ + + + + From 3103ebab716359485b789e3c47afb9ff3b1986e2 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Wed, 3 Nov 2021 17:30:30 +0100 Subject: [PATCH 049/111] Fixed typo --- .../java/org/schabi/newpipe/player/playqueue/PlayQueue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueue.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueue.java index 76fed8e9e..f2259b120 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueue.java +++ b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueue.java @@ -442,7 +442,7 @@ public abstract class PlayQueue implements Serializable { if (backup == null) { backup = new ArrayList<>(streams); } - // Can't shuffle an list that's empty or only has one element + // Can't shuffle a list that's empty or only has one element if (size() <= 2) { return; } From fd8ff610a1e0e8bf0bb8bbfcd4e7a54fd829a8aa Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Thu, 4 Nov 2021 16:18:12 +0100 Subject: [PATCH 050/111] Changed extractor dependency back to TeamNewPipe ...as the required PR was merged. --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 84054265a..e6a78a093 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -189,7 +189,7 @@ dependencies { // name and the commit hash with the commit hash of the (pushed) commit you want to test // This works thanks to JitPack: https://jitpack.io/ implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751' - implementation 'com.github.B0pol:NewPipeExtractor:396aecef19ea61de9915727abd71aa55ef75549f' + implementation 'com.github.TeamNewPipe:NewPipeExtractor:7e7b78f1b3' /** Checkstyle **/ checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}" From d5307f5e0be613ffaeaa376ee077731403f3ec3d Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Thu, 4 Nov 2021 19:46:22 +0100 Subject: [PATCH 051/111] Reworked ``dialog_playback_parameter`` * Removed dependency to @dimen/video_item_search_padding as it's unrelated * Made the margins/paddings a bit smaller * Put the checkboxes inside a layout * Removed some useless attributes (maxLine) --- .../res/layout/dialog_playback_parameter.xml | 69 +++++++++++-------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/app/src/main/res/layout/dialog_playback_parameter.xml b/app/src/main/res/layout/dialog_playback_parameter.xml index 546602d0c..40db90675 100644 --- a/app/src/main/res/layout/dialog_playback_parameter.xml +++ b/app/src/main/res/layout/dialog_playback_parameter.xml @@ -4,9 +4,9 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:clickable="false" - android:paddingLeft="@dimen/video_item_search_padding" - android:paddingTop="@dimen/video_item_search_padding" - android:paddingRight="@dimen/video_item_search_padding"> + android:paddingStart="6dp" + android:paddingTop="4dp" + android:paddingEnd="6dp"> @@ -344,32 +350,37 @@ android:layout_width="match_parent" android:layout_height="1dp" android:layout_below="@+id/stepSizeSelector" - android:layout_margin="@dimen/video_item_search_padding" + android:layout_marginStart="12dp" + android:layout_marginTop="6dp" + android:layout_marginEnd="12dp" + android:layout_marginBottom="6dp" android:background="?attr/separator_color" /> - + android:orientation="vertical"> - + + + + From 785897044686882d44ba89624edebde660761929 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Thu, 4 Nov 2021 19:47:08 +0100 Subject: [PATCH 052/111] Added a custom title to also save some margin/padding/etc --- .../player/helper/PlaybackParameterDialog.java | 12 ++++++++---- .../layout/dialog_playback_parameter_title.xml | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 app/src/main/res/layout/dialog_playback_parameter_title.xml diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlaybackParameterDialog.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlaybackParameterDialog.java index bbe281921..1d1e0d23a 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlaybackParameterDialog.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlaybackParameterDialog.java @@ -1,5 +1,8 @@ package org.schabi.newpipe.player.helper; +import static org.schabi.newpipe.player.Player.DEBUG; +import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; + import android.app.Dialog; import android.content.Context; import android.os.Bundle; @@ -18,9 +21,6 @@ import androidx.preference.PreferenceManager; import org.schabi.newpipe.R; import org.schabi.newpipe.util.SliderStrategy; -import static org.schabi.newpipe.player.Player.DEBUG; -import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; - public class PlaybackParameterDialog extends DialogFragment { // Minimum allowable range in ExoPlayer private static final double MINIMUM_PLAYBACK_VALUE = 0.10f; @@ -157,7 +157,11 @@ public class PlaybackParameterDialog extends DialogFragment { setupControlViews(view); final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(requireActivity()) - .setTitle(R.string.playback_speed_control) + .setCustomTitle( + View.inflate( + getContext(), + R.layout.dialog_playback_parameter_title, + null)) .setView(view) .setCancelable(true) .setNegativeButton(R.string.cancel, (dialogInterface, i) -> diff --git a/app/src/main/res/layout/dialog_playback_parameter_title.xml b/app/src/main/res/layout/dialog_playback_parameter_title.xml new file mode 100644 index 000000000..0bebf67d1 --- /dev/null +++ b/app/src/main/res/layout/dialog_playback_parameter_title.xml @@ -0,0 +1,18 @@ + + + + + + + From 9080d3d6ddce4a0cf725d9405536be438c5e934b Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 5 Nov 2021 18:04:49 +0100 Subject: [PATCH 053/111] Removed ``e.printStacktrace`` and used an proper logger --- .../java/org/schabi/newpipe/local/feed/FeedFragment.kt | 3 ++- .../main/java/org/schabi/newpipe/player/Player.java | 5 ++--- .../schabi/newpipe/settings/ContentSettingsManager.kt | 10 +++++++--- .../schabi/newpipe/util/TLSSocketFactoryCompat.java | 7 ++++--- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt index 965075bf3..48427d174 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt @@ -25,6 +25,7 @@ import android.content.Intent import android.content.SharedPreferences import android.os.Bundle import android.os.Parcelable +import android.util.Log import android.view.LayoutInflater import android.view.Menu import android.view.MenuInflater @@ -464,7 +465,7 @@ class FeedFragment : BaseStateFragment() { errors.subList(i + 1, errors.size) ) }, - { throwable -> throwable.printStackTrace() } + { throwable -> Log.e(TAG, "Unable to process", throwable) } ) return // this will be called on the remaining errors by handleFeedNotAvailable() } diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 5435b9f81..fb903813c 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -695,7 +695,7 @@ public final class Player implements }, error -> { if (DEBUG) { - error.printStackTrace(); + Log.w(TAG, "Failed to start playback", error); } // In case any error we can start playback without history initPlayback(newQueue, repeatMode, playbackSpeed, playbackPitch, @@ -4184,8 +4184,7 @@ public final class Player implements } catch (@NonNull final IndexOutOfBoundsException e) { // Why would this even happen =(... but lets log it anyway, better safe than sorry if (DEBUG) { - Log.d(TAG, "player.isCurrentWindowDynamic() failed: " + e.getMessage()); - e.printStackTrace(); + Log.d(TAG, "player.isCurrentWindowDynamic() failed: ", e); } return false; } diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt index 6bc63a56a..3ac275695 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt +++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt @@ -1,6 +1,7 @@ package org.schabi.newpipe.settings import android.content.SharedPreferences +import android.util.Log import org.schabi.newpipe.streams.io.SharpOutputStream import org.schabi.newpipe.streams.io.StoredFileHelper import org.schabi.newpipe.util.ZipHelper @@ -13,6 +14,9 @@ import java.io.ObjectOutputStream import java.util.zip.ZipOutputStream class ContentSettingsManager(private val fileLocator: NewPipeFileLocator) { + companion object { + const val TAG = "ContentSetManager" + } /** * Exports given [SharedPreferences] to the file in given outputPath. @@ -31,7 +35,7 @@ class ContentSettingsManager(private val fileLocator: NewPipeFileLocator) { output.flush() } } catch (e: IOException) { - e.printStackTrace() + Log.e(TAG, "Unable to exportDatabase", e) } ZipHelper.addFileToZip(outZip, fileLocator.settings.path, "newpipe.settings") @@ -101,9 +105,9 @@ class ContentSettingsManager(private val fileLocator: NewPipeFileLocator) { preferenceEditor.commit() } } catch (e: IOException) { - e.printStackTrace() + Log.e(TAG, "Unable to loadSharedPreferences", e) } catch (e: ClassNotFoundException) { - e.printStackTrace() + Log.e(TAG, "Unable to loadSharedPreferences", e) } } } diff --git a/app/src/main/java/org/schabi/newpipe/util/TLSSocketFactoryCompat.java b/app/src/main/java/org/schabi/newpipe/util/TLSSocketFactoryCompat.java index 8cf5a4cdf..bc4383758 100644 --- a/app/src/main/java/org/schabi/newpipe/util/TLSSocketFactoryCompat.java +++ b/app/src/main/java/org/schabi/newpipe/util/TLSSocketFactoryCompat.java @@ -14,6 +14,8 @@ import javax.net.ssl.TrustManager; import static org.schabi.newpipe.MainActivity.DEBUG; +import android.util.Log; + /** * This is an extension of the SSLSocketFactory which enables TLS 1.2 and 1.1. @@ -21,6 +23,7 @@ import static org.schabi.newpipe.MainActivity.DEBUG; */ public class TLSSocketFactoryCompat extends SSLSocketFactory { + private static final String TAG = "TLSSocketFactoryCom"; private static TLSSocketFactoryCompat instance = null; @@ -53,9 +56,7 @@ public class TLSSocketFactoryCompat extends SSLSocketFactory { try { HttpsURLConnection.setDefaultSSLSocketFactory(getInstance()); } catch (NoSuchAlgorithmException | KeyManagementException e) { - if (DEBUG) { - e.printStackTrace(); - } + Log.e(TAG, "Unable to setAsDefault", e); } } From 14e4b760ea5749560e5e0082bb9a2f1e35425901 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 5 Nov 2021 18:04:57 +0100 Subject: [PATCH 054/111] Removed dead code --- .../org/schabi/newpipe/util/TLSSocketFactoryCompat.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/TLSSocketFactoryCompat.java b/app/src/main/java/org/schabi/newpipe/util/TLSSocketFactoryCompat.java index bc4383758..bb30eca11 100644 --- a/app/src/main/java/org/schabi/newpipe/util/TLSSocketFactoryCompat.java +++ b/app/src/main/java/org/schabi/newpipe/util/TLSSocketFactoryCompat.java @@ -35,14 +35,6 @@ public class TLSSocketFactoryCompat extends SSLSocketFactory { internalSSLSocketFactory = context.getSocketFactory(); } - - public TLSSocketFactoryCompat(final TrustManager[] tm) - throws KeyManagementException, NoSuchAlgorithmException { - final SSLContext context = SSLContext.getInstance("TLS"); - context.init(null, tm, new java.security.SecureRandom()); - internalSSLSocketFactory = context.getSocketFactory(); - } - public static TLSSocketFactoryCompat getInstance() throws NoSuchAlgorithmException, KeyManagementException { if (instance != null) { From 5b6353d018229752abcfe5737e7bdd2ada19febf Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 5 Nov 2021 18:06:10 +0100 Subject: [PATCH 055/111] Added some doc --- .../org/schabi/newpipe/player/event/PlayerGestureListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java b/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java index 998324c9c..298533fcd 100644 --- a/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java +++ b/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java @@ -227,7 +227,7 @@ public class PlayerGestureListener if (player.isControlsVisible() && player.getCurrentState() == STATE_PLAYING) { player.hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME); } - } else { + } else /* Popup-Player */ { if (player.isControlsVisible() && player.getCurrentState() == STATE_PLAYING) { player.hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME); } From 7afec6feb2fb33d18bb5e6cef64f308675f94e0b Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 5 Nov 2021 18:06:32 +0100 Subject: [PATCH 056/111] Why log double? --- .../schabi/newpipe/player/event/PlayerGestureListener.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java b/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java index 298533fcd..005a0b2be 100644 --- a/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java +++ b/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java @@ -210,11 +210,8 @@ public class PlayerGestureListener Log.d(TAG, "onScrollEnd called with playerType = [" + player.getPlayerType() + "]"); } + if (playerType == MainPlayer.PlayerType.VIDEO) { - if (DEBUG) { - Log.d(TAG, "onScrollEnd() called"); - } - if (player.getVolumeRelativeLayout().getVisibility() == View.VISIBLE) { animate(player.getVolumeRelativeLayout(), false, 200, SCALE_AND_ALPHA, 200); From 9f49d535b4338dcc706f0ee145db38daa627a572 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 5 Nov 2021 18:07:21 +0100 Subject: [PATCH 057/111] De-Duplicated some code --- .../player/event/PlayerGestureListener.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java b/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java index 005a0b2be..689c0c1ff 100644 --- a/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java +++ b/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java @@ -210,7 +210,11 @@ public class PlayerGestureListener Log.d(TAG, "onScrollEnd called with playerType = [" + player.getPlayerType() + "]"); } - + + if (player.isControlsVisible() && player.getCurrentState() == STATE_PLAYING) { + player.hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME); + } + if (playerType == MainPlayer.PlayerType.VIDEO) { if (player.getVolumeRelativeLayout().getVisibility() == View.VISIBLE) { animate(player.getVolumeRelativeLayout(), false, 200, SCALE_AND_ALPHA, @@ -220,15 +224,7 @@ public class PlayerGestureListener animate(player.getBrightnessRelativeLayout(), false, 200, SCALE_AND_ALPHA, 200); } - - if (player.isControlsVisible() && player.getCurrentState() == STATE_PLAYING) { - player.hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME); - } } else /* Popup-Player */ { - if (player.isControlsVisible() && player.getCurrentState() == STATE_PLAYING) { - player.hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME); - } - if (player.isInsideClosingRadius(event)) { player.closePopup(); } else if (!player.isPopupClosing()) { From c219bdf8e2c8f87212359c873e10ea2253cfbb74 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 5 Nov 2021 18:10:55 +0100 Subject: [PATCH 058/111] Merged extremely similar code together / parity between video and popup player * Removed ``player.getPlayPauseButton().requestFocus();`` as there is no reason why it was introduced there documented * Use the same delay to hide the controls on both players --- .../player/event/PlayerGestureListener.java | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java b/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java index 689c0c1ff..25345c6ff 100644 --- a/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java +++ b/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java @@ -69,26 +69,22 @@ public class PlayerGestureListener if (DEBUG) { Log.d(TAG, "onSingleTap called with playerType = [" + player.getPlayerType() + "]"); } - if (playerType == MainPlayer.PlayerType.POPUP) { - if (player.isControlsVisible()) { - player.hideControls(100, 100); - } else { - player.getPlayPauseButton().requestFocus(); - player.showControlsThenHide(); - } + if (player.isControlsVisible()) { - } else /* playerType == MainPlayer.PlayerType.VIDEO */ { + // -- Controls visible -- - if (player.isControlsVisible()) { - player.hideControls(150, 0); - } else { - if (player.getCurrentState() == Player.STATE_COMPLETED) { - player.showControls(0); - } else { - player.showControlsThenHide(); - } - } + player.hideControls(150, 0); + return; + } + + // -- Controls are not visible -- + + // When player is completed show controls and don't hide them later + if (player.getCurrentState() == Player.STATE_COMPLETED) { + player.showControls(0); + } else { + player.showControlsThenHide(); } } From a2fb49092410ca51248ef625fae3a5fd2a387262 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 5 Nov 2021 19:07:56 +0100 Subject: [PATCH 059/111] Simplified some code and added some comments --- .../player/event/PlayerGestureListener.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java b/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java index 25345c6ff..fd63bea1a 100644 --- a/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java +++ b/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java @@ -99,6 +99,8 @@ public class PlayerGestureListener + player.getPlayerType() + "], portion = [" + portion + "]"); } if (playerType == MainPlayer.PlayerType.VIDEO) { + + // -- Brightness and Volume control -- final boolean isBrightnessGestureEnabled = PlayerHelper.isBrightnessGestureEnabled(service); final boolean isVolumeGestureEnabled = PlayerHelper.isVolumeGestureEnabled(service); @@ -117,15 +119,14 @@ public class PlayerGestureListener } } else /* MainPlayer.PlayerType.POPUP */ { + + // -- Determine if the ClosingOverlayView (red X) has to be shown or hidden -- final View closingOverlayView = player.getClosingOverlayView(); - if (player.isInsideClosingRadius(movingEvent)) { - if (closingOverlayView.getVisibility() == View.GONE) { - animate(closingOverlayView, true, 200); - } - } else { - if (closingOverlayView.getVisibility() == View.VISIBLE) { - animate(closingOverlayView, false, 200); - } + final boolean showClosingOverlayView = player.isInsideClosingRadius(movingEvent); + // Check if an view is in expected state and if not animate it into the correct state + final int expectedVisibility = showClosingOverlayView ? View.VISIBLE : View.GONE; + if (closingOverlayView.getVisibility() != expectedVisibility) { + animate(closingOverlayView, showClosingOverlayView, 200); } } } From 735f3e436e119bae4ad21b4f885f750b22ce2b4f Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sat, 6 Nov 2021 21:07:00 +0100 Subject: [PATCH 060/111] Removed unused imports --- .../java/org/schabi/newpipe/util/TLSSocketFactoryCompat.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/TLSSocketFactoryCompat.java b/app/src/main/java/org/schabi/newpipe/util/TLSSocketFactoryCompat.java index bb30eca11..05e69408a 100644 --- a/app/src/main/java/org/schabi/newpipe/util/TLSSocketFactoryCompat.java +++ b/app/src/main/java/org/schabi/newpipe/util/TLSSocketFactoryCompat.java @@ -10,9 +10,6 @@ import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; - -import static org.schabi.newpipe.MainActivity.DEBUG; import android.util.Log; From 2d21925daeeaa363044d4e6508c56c6d69696403 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sun, 7 Nov 2021 13:51:43 +0100 Subject: [PATCH 061/111] Removed obvious title from the "Playback Speed Controls" --- .../player/helper/PlaybackParameterDialog.java | 5 ----- .../layout/dialog_playback_parameter_title.xml | 18 ------------------ 2 files changed, 23 deletions(-) delete mode 100644 app/src/main/res/layout/dialog_playback_parameter_title.xml diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlaybackParameterDialog.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlaybackParameterDialog.java index 1d1e0d23a..5139ef9cd 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlaybackParameterDialog.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlaybackParameterDialog.java @@ -157,11 +157,6 @@ public class PlaybackParameterDialog extends DialogFragment { setupControlViews(view); final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(requireActivity()) - .setCustomTitle( - View.inflate( - getContext(), - R.layout.dialog_playback_parameter_title, - null)) .setView(view) .setCancelable(true) .setNegativeButton(R.string.cancel, (dialogInterface, i) -> diff --git a/app/src/main/res/layout/dialog_playback_parameter_title.xml b/app/src/main/res/layout/dialog_playback_parameter_title.xml deleted file mode 100644 index 0bebf67d1..000000000 --- a/app/src/main/res/layout/dialog_playback_parameter_title.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - From 412453d067959d10f110c1cde1387dad02018f13 Mon Sep 17 00:00:00 2001 From: Baji Shaik Date: Sun, 7 Nov 2021 23:11:10 -0500 Subject: [PATCH 062/111] added show watched items toggle preference default sharedpreference is used to persist and retrieve show watched menu option toggle state --- .../org/schabi/newpipe/local/feed/FeedFragment.kt | 4 +++- .../org/schabi/newpipe/local/feed/FeedViewModel.kt | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt index 965075bf3..61805715c 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt @@ -128,6 +128,7 @@ class FeedFragment : BaseStateFragment() { val factory = FeedViewModel.Factory(requireContext(), groupId, showPlayedItems) viewModel = ViewModelProvider(this, factory).get(FeedViewModel::class.java) + showPlayedItems = viewModel.getSavedPlayedItemsToggle() viewModel.stateLiveData.observe(viewLifecycleOwner, { it?.let(::handleResult) }) groupAdapter = GroupieAdapter().apply { @@ -158,7 +159,7 @@ class FeedFragment : BaseStateFragment() { } } - fun setupListViewMode() { + private fun setupListViewMode() { // does everything needed to setup the layouts for grid or list modes groupAdapter.spanCount = if (shouldUseGridLayout(context)) getGridSpanCountStreams(context) else 1 feedBinding.itemsList.layoutManager = GridLayoutManager(requireContext(), groupAdapter.spanCount).apply { @@ -213,6 +214,7 @@ class FeedFragment : BaseStateFragment() { showPlayedItems = !item.isChecked updateTogglePlayedItemsButton(item) viewModel.togglePlayedItems(showPlayedItems) + viewModel.savePlayedItemsToggle(showPlayedItems) } return super.onOptionsItemSelected(item) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt index 8bdf412b5..5f18b6342 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt @@ -1,10 +1,12 @@ package org.schabi.newpipe.local.feed import android.content.Context +import androidx.core.content.edit import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +import androidx.preference.PreferenceManager import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.functions.Function4 @@ -28,6 +30,10 @@ class FeedViewModel( initialShowPlayedItems: Boolean = true ) : ViewModel() { private var feedDatabaseManager: FeedDatabaseManager = FeedDatabaseManager(applicationContext) + private var sharedPreferences = PreferenceManager.getDefaultSharedPreferences(applicationContext) + companion object { + const val SHOW_PLAYED_ITEMS_PREFERENCE = "show_played_items_preference_tag" + } private val toggleShowPlayedItems = BehaviorProcessor.create() private val streamItems = toggleShowPlayedItems @@ -81,6 +87,13 @@ class FeedViewModel( toggleShowPlayedItems.onNext(showPlayedItems) } + fun savePlayedItemsToggle(showPlayedItems: Boolean) = sharedPreferences.edit { + this.putBoolean(SHOW_PLAYED_ITEMS_PREFERENCE, showPlayedItems) + this.apply() + } + + fun getSavedPlayedItemsToggle() = sharedPreferences.getBoolean(SHOW_PLAYED_ITEMS_PREFERENCE, true) + class Factory( private val context: Context, private val groupId: Long = FeedGroupEntity.GROUP_ALL_ID, From 2df6708f50910dca24a071a6ba802fa03b65ff97 Mon Sep 17 00:00:00 2001 From: Baji Shaik Date: Wed, 10 Nov 2021 16:16:17 -0500 Subject: [PATCH 063/111] moved preference key from viewmodel to settings_keys.xml --- .../org/schabi/newpipe/local/feed/FeedViewModel.kt | 10 ++++------ app/src/main/res/values/settings_keys.xml | 1 + 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt index 5f18b6342..cea787c5a 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt @@ -12,6 +12,7 @@ import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.functions.Function4 import io.reactivex.rxjava3.processors.BehaviorProcessor import io.reactivex.rxjava3.schedulers.Schedulers +import org.schabi.newpipe.R import org.schabi.newpipe.database.feed.model.FeedGroupEntity import org.schabi.newpipe.database.stream.StreamWithState import org.schabi.newpipe.local.feed.item.StreamItem @@ -25,15 +26,12 @@ import java.time.OffsetDateTime import java.util.concurrent.TimeUnit class FeedViewModel( - applicationContext: Context, + val applicationContext: Context, groupId: Long = FeedGroupEntity.GROUP_ALL_ID, initialShowPlayedItems: Boolean = true ) : ViewModel() { private var feedDatabaseManager: FeedDatabaseManager = FeedDatabaseManager(applicationContext) private var sharedPreferences = PreferenceManager.getDefaultSharedPreferences(applicationContext) - companion object { - const val SHOW_PLAYED_ITEMS_PREFERENCE = "show_played_items_preference_tag" - } private val toggleShowPlayedItems = BehaviorProcessor.create() private val streamItems = toggleShowPlayedItems @@ -88,11 +86,11 @@ class FeedViewModel( } fun savePlayedItemsToggle(showPlayedItems: Boolean) = sharedPreferences.edit { - this.putBoolean(SHOW_PLAYED_ITEMS_PREFERENCE, showPlayedItems) + this.putBoolean(applicationContext.getString(R.string.show_played_items_filter_key), showPlayedItems) this.apply() } - fun getSavedPlayedItemsToggle() = sharedPreferences.getBoolean(SHOW_PLAYED_ITEMS_PREFERENCE, true) + fun getSavedPlayedItemsToggle() = sharedPreferences.getBoolean(applicationContext.getString(R.string.show_played_items_filter_key), true) class Factory( private val context: Context, diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index 1c57178b4..e60cf17c9 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -14,6 +14,7 @@ saved_tabs_key + show_played_items_preference_key download_path download_path_audio From 1c615bc2929385e7fdea0acfc0fbd52980e85a18 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Thu, 11 Nov 2021 19:46:15 +0100 Subject: [PATCH 064/111] Fixed toggle not in sync with list after app restart + refactored the code a bit --- .../schabi/newpipe/local/feed/FeedFragment.kt | 6 ++-- .../newpipe/local/feed/FeedViewModel.kt | 30 ++++++++++++------- app/src/main/res/values/settings_keys.xml | 2 +- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt index 61805715c..305802cf5 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt @@ -126,9 +126,9 @@ class FeedFragment : BaseStateFragment() { _feedBinding = FragmentFeedBinding.bind(rootView) super.onViewCreated(rootView, savedInstanceState) - val factory = FeedViewModel.Factory(requireContext(), groupId, showPlayedItems) + val factory = FeedViewModel.Factory(requireContext(), groupId) viewModel = ViewModelProvider(this, factory).get(FeedViewModel::class.java) - showPlayedItems = viewModel.getSavedPlayedItemsToggle() + showPlayedItems = viewModel.getShowPlayedItemsFromPreferences() viewModel.stateLiveData.observe(viewLifecycleOwner, { it?.let(::handleResult) }) groupAdapter = GroupieAdapter().apply { @@ -214,7 +214,7 @@ class FeedFragment : BaseStateFragment() { showPlayedItems = !item.isChecked updateTogglePlayedItemsButton(item) viewModel.togglePlayedItems(showPlayedItems) - viewModel.savePlayedItemsToggle(showPlayedItems) + viewModel.saveShowPlayedItemsToPreferences(showPlayedItems) } return super.onOptionsItemSelected(item) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt index cea787c5a..ecdcb7349 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt @@ -26,12 +26,11 @@ import java.time.OffsetDateTime import java.util.concurrent.TimeUnit class FeedViewModel( - val applicationContext: Context, + private val applicationContext: Context, groupId: Long = FeedGroupEntity.GROUP_ALL_ID, initialShowPlayedItems: Boolean = true ) : ViewModel() { private var feedDatabaseManager: FeedDatabaseManager = FeedDatabaseManager(applicationContext) - private var sharedPreferences = PreferenceManager.getDefaultSharedPreferences(applicationContext) private val toggleShowPlayedItems = BehaviorProcessor.create() private val streamItems = toggleShowPlayedItems @@ -85,21 +84,32 @@ class FeedViewModel( toggleShowPlayedItems.onNext(showPlayedItems) } - fun savePlayedItemsToggle(showPlayedItems: Boolean) = sharedPreferences.edit { - this.putBoolean(applicationContext.getString(R.string.show_played_items_filter_key), showPlayedItems) - this.apply() - } + fun saveShowPlayedItemsToPreferences(showPlayedItems: Boolean) = + PreferenceManager.getDefaultSharedPreferences(applicationContext).edit { + this.putBoolean(applicationContext.getString(R.string.feed_show_played_items_key), showPlayedItems) + this.apply() + } - fun getSavedPlayedItemsToggle() = sharedPreferences.getBoolean(applicationContext.getString(R.string.show_played_items_filter_key), true) + fun getShowPlayedItemsFromPreferences() = getShowPlayedItemsFromPreferences(applicationContext) + + companion object { + private fun getShowPlayedItemsFromPreferences(context: Context) = + PreferenceManager.getDefaultSharedPreferences(context) + .getBoolean(context.getString(R.string.feed_show_played_items_key), true) + } class Factory( private val context: Context, - private val groupId: Long = FeedGroupEntity.GROUP_ALL_ID, - private val showPlayedItems: Boolean + private val groupId: Long = FeedGroupEntity.GROUP_ALL_ID ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T { - return FeedViewModel(context.applicationContext, groupId, showPlayedItems) as T + return FeedViewModel( + context.applicationContext, + groupId, + // Read initial value from preferences + getShowPlayedItemsFromPreferences(context.applicationContext) + ) as T } } } diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index e60cf17c9..01de6e977 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -14,7 +14,7 @@ saved_tabs_key - show_played_items_preference_key + feed_show_played_items download_path download_path_audio From c1293d286792de13641ef4472b827e691e768f86 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Thu, 11 Nov 2021 19:49:46 +0100 Subject: [PATCH 065/111] A feed settings-key better fits there --- app/src/main/res/values/settings_keys.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index 01de6e977..9db147deb 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -14,7 +14,6 @@ saved_tabs_key - feed_show_played_items download_path download_path_audio @@ -264,6 +263,7 @@ feed_update_threshold_key 300 + feed_show_played_items show_thumbnail_key From e09e1cb46816b5ff3ccdd4028809e426f5cacb4b Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Thu, 11 Nov 2021 20:17:54 +0100 Subject: [PATCH 066/111] Replaced deprecated ``with`` with ``using`` --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index b564e3700..0338fde6c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,6 +6,6 @@ include ':app' //includeBuild('../NewPipeExtractor') { // dependencySubstitution { -// substitute module('com.github.TeamNewPipe:NewPipeExtractor') with project(':extractor') +// substitute module('com.github.TeamNewPipe:NewPipeExtractor') using project(':extractor') // } //} From 6205dce2c890d72b34c42640a16f7cb75cfe441e Mon Sep 17 00:00:00 2001 From: Robin Date: Sat, 28 Aug 2021 19:41:58 +0200 Subject: [PATCH 067/111] Update ExoPlayer to 2.14.2 --- app/build.gradle | 2 +- .../org/schabi/newpipe/player/Player.java | 57 ++++++++++--------- .../newpipe/player/helper/AudioReactor.java | 9 +-- .../newpipe/player/helper/LoadController.java | 9 +-- .../player/helper/PlayerDataSource.java | 10 +--- .../newpipe/player/helper/PlayerHelper.java | 4 +- .../player/playback/CustomTrackSelector.java | 8 +-- .../player/resolver/PlaybackResolver.java | 17 ++++-- 8 files changed, 58 insertions(+), 58 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index e6a78a093..94bec47fe 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,7 +105,7 @@ ext { androidxRoomVersion = '2.3.0' icepickVersion = '3.2.0' - exoPlayerVersion = '2.12.3' + exoPlayerVersion = '2.14.2' googleAutoServiceVersion = '1.0' groupieVersion = '2.10.0' markwonVersion = '4.6.2' diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 5435b9f81..d2e89baa0 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -1,12 +1,13 @@ package org.schabi.newpipe.player; -import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_AD_INSERTION; +import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_AUTO_TRANSITION; import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_INTERNAL; -import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_PERIOD_TRANSITION; +import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_REMOVE; import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK; import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT; +import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SKIP; import static com.google.android.exoplayer2.Player.DiscontinuityReason; -import static com.google.android.exoplayer2.Player.EventListener; +import static com.google.android.exoplayer2.Player.Listener; import static com.google.android.exoplayer2.Player.REPEAT_MODE_ALL; import static com.google.android.exoplayer2.Player.REPEAT_MODE_OFF; import static com.google.android.exoplayer2.Player.REPEAT_MODE_ONE; @@ -116,6 +117,7 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.DefaultRenderersFactory; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.PlaybackParameters; +import com.google.android.exoplayer2.Player.PositionInfo; import com.google.android.exoplayer2.RenderersFactory; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.Timeline; @@ -123,13 +125,14 @@ import com.google.android.exoplayer2.source.BehindLiveWindowException; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroupArray; -import com.google.android.exoplayer2.text.CaptionStyleCompat; +import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.trackselection.TrackSelectionArray; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; +import com.google.android.exoplayer2.ui.CaptionStyleCompat; import com.google.android.exoplayer2.ui.SubtitleView; import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; import com.google.android.exoplayer2.util.Util; -import com.google.android.exoplayer2.video.VideoListener; +import com.google.android.exoplayer2.video.VideoSize; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.squareup.picasso.Picasso; import com.squareup.picasso.Target; @@ -197,9 +200,8 @@ import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.disposables.SerialDisposable; public final class Player implements - EventListener, PlaybackListener, - VideoListener, + Listener, SeekBar.OnSeekBarChangeListener, View.OnClickListener, PopupMenu.OnMenuItemClickListener, @@ -501,10 +503,6 @@ public final class Player implements // Setup video view setupVideoSurface(); - simpleExoPlayer.addVideoListener(this); - - // Setup subtitle view - simpleExoPlayer.addTextOutput(binding.subtitleView); // enable media tunneling if (DEBUG && PreferenceManager.getDefaultSharedPreferences(context) @@ -513,7 +511,7 @@ public final class Player implements + "media tunneling disabled in debug preferences"); } else if (DeviceUtils.shouldSupportMediaTunneling()) { trackSelector.setParameters(trackSelector.buildUponParameters() - .setTunnelingAudioSessionId(C.generateAudioSessionIdV21(context))); + .setTunnelingEnabled(true)); } else if (DEBUG) { Log.d(TAG, "[" + Util.DEVICE_DEBUG_INFO + "] does not support media tunneling"); } @@ -809,7 +807,6 @@ public final class Player implements if (!exoPlayerIsNull()) { simpleExoPlayer.removeListener(this); - simpleExoPlayer.removeVideoListener(this); simpleExoPlayer.stop(); simpleExoPlayer.release(); } @@ -898,7 +895,7 @@ public final class Player implements public void smoothStopPlayer() { // Pausing would make transition from one stream to a new stream not smooth, so only stop - simpleExoPlayer.stop(false); + simpleExoPlayer.stop(); } //endregion @@ -2437,7 +2434,9 @@ public final class Player implements } @Override - public void onPositionDiscontinuity(@DiscontinuityReason final int discontinuityReason) { + public void onPositionDiscontinuity( + final PositionInfo oldPosition, final PositionInfo newPosition, + @DiscontinuityReason final int discontinuityReason) { if (DEBUG) { Log.d(TAG, "ExoPlayer - onPositionDiscontinuity() called with " + "discontinuityReason = [" + discontinuityReason + "]"); @@ -2449,7 +2448,7 @@ public final class Player implements // Refresh the playback if there is a transition to the next video final int newWindowIndex = simpleExoPlayer.getCurrentWindowIndex(); switch (discontinuityReason) { - case DISCONTINUITY_REASON_PERIOD_TRANSITION: + case DISCONTINUITY_REASON_REMOVE: // When player is in single repeat mode and a period transition occurs, // we need to register a view count here since no metadata has changed if (getRepeatMode() == REPEAT_MODE_ONE && newWindowIndex == playQueue.getIndex()) { @@ -2470,7 +2469,8 @@ public final class Player implements playQueue.setIndex(newWindowIndex); } break; - case DISCONTINUITY_REASON_AD_INSERTION: + case DISCONTINUITY_REASON_SKIP: + case DISCONTINUITY_REASON_AUTO_TRANSITION: break; // only makes Android Studio linter happy, as there are no ads } @@ -2482,6 +2482,11 @@ public final class Player implements //TODO check if this causes black screen when switching to fullscreen animate(binding.surfaceForeground, false, DEFAULT_CONTROLS_DURATION); } + + @Override + public void onCues(final List cues) { + binding.subtitleView.onCues(cues); + } //endregion @@ -2503,7 +2508,7 @@ public final class Player implements * * * @see #processSourceError(IOException) - * @see com.google.android.exoplayer2.Player.EventListener#onPlayerError(ExoPlaybackException) + * @see com.google.android.exoplayer2.Player.Listener#onPlayerError(ExoPlaybackException) */ @Override public void onPlayerError(@NonNull final ExoPlaybackException error) { @@ -3867,19 +3872,17 @@ public final class Player implements } @Override // exoplayer listener - public void onVideoSizeChanged(final int width, final int height, - final int unappliedRotationDegrees, - final float pixelWidthHeightRatio) { + public void onVideoSizeChanged(final VideoSize videoSize) { if (DEBUG) { Log.d(TAG, "onVideoSizeChanged() called with: " - + "width / height = [" + width + " / " + height - + " = " + (((float) width) / height) + "], " - + "unappliedRotationDegrees = [" + unappliedRotationDegrees + "], " - + "pixelWidthHeightRatio = [" + pixelWidthHeightRatio + "]"); + + "width / height = [" + videoSize.width + " / " + videoSize.height + + " = " + (((float) videoSize.width) / videoSize.height) + "], " + + "unappliedRotationDegrees = [" + videoSize.unappliedRotationDegrees + "], " + + "pixelWidthHeightRatio = [" + videoSize.pixelWidthHeightRatio + "]"); } - binding.surfaceView.setAspectRatio(((float) width) / height); - isVerticalVideo = width < height; + binding.surfaceView.setAspectRatio(((float) videoSize.width) / videoSize.height); + isVerticalVideo = videoSize.width < videoSize.height; if (globalScreenOrientationLocked(context) && isFullscreen diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java b/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java index 2e2fda86c..b36f9f234 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java @@ -16,7 +16,6 @@ import androidx.media.AudioManagerCompat; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.analytics.AnalyticsListener; -import com.google.android.exoplayer2.decoder.DecoderCounters; public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, AnalyticsListener { @@ -150,15 +149,9 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, An //////////////////////////////////////////////////////////////////////////*/ @Override - public void onAudioSessionId(final EventTime eventTime, final int audioSessionId) { + public void onAudioSessionIdChanged(final EventTime eventTime, final int audioSessionId) { notifyAudioSessionUpdate(true, audioSessionId); } - - @Override - public void onAudioDisabled(final EventTime eventTime, final DecoderCounters counters) { - notifyAudioSessionUpdate(false, player.getAudioSessionId()); - } - private void notifyAudioSessionUpdate(final boolean active, final int audioSessionId) { if (!PlayerHelper.isUsingDSP()) { return; diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/LoadController.java b/app/src/main/java/org/schabi/newpipe/player/helper/LoadController.java index 71cfcc818..ca3b1a3c1 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/LoadController.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/LoadController.java @@ -4,7 +4,7 @@ import com.google.android.exoplayer2.DefaultLoadControl; import com.google.android.exoplayer2.LoadControl; import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.source.TrackGroupArray; -import com.google.android.exoplayer2.trackselection.TrackSelectionArray; +import com.google.android.exoplayer2.trackselection.ExoTrackSelection; import com.google.android.exoplayer2.upstream.Allocator; public class LoadController implements LoadControl { @@ -47,7 +47,7 @@ public class LoadController implements LoadControl { @Override public void onTracksSelected(final Renderer[] renderers, final TrackGroupArray trackGroups, - final TrackSelectionArray trackSelections) { + final ExoTrackSelection[] trackSelections) { internalLoadControl.onTracksSelected(renderers, trackGroups, trackSelections); } @@ -91,11 +91,12 @@ public class LoadController implements LoadControl { @Override public boolean shouldStartPlayback(final long bufferedDurationUs, final float playbackSpeed, - final boolean rebuffering) { + final boolean rebuffering, final long targetLiveOffsetUs) { final boolean isInitialPlaybackBufferFilled = bufferedDurationUs >= this.initialPlaybackBufferUs * playbackSpeed; final boolean isInternalStartingPlayback = internalLoadControl - .shouldStartPlayback(bufferedDurationUs, playbackSpeed, rebuffering); + .shouldStartPlayback(bufferedDurationUs, playbackSpeed, rebuffering, + targetLiveOffsetUs); return isInitialPlaybackBufferFilled || isInternalStartingPlayback; } diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java index 5fea4761b..42a7838c3 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java @@ -19,7 +19,7 @@ import com.google.android.exoplayer2.upstream.TransferListener; public class PlayerDataSource { private static final int MANIFEST_MINIMUM_RETRY = 5; private static final int EXTRACTOR_MINIMUM_RETRY = Integer.MAX_VALUE; - private static final int LIVE_STREAM_EDGE_GAP_MILLIS = 10000; + public static final int LIVE_STREAM_EDGE_GAP_MILLIS = 10000; private final DataSource.Factory cacheDataSourceFactory; private final DataSource.Factory cachelessDataSourceFactory; @@ -50,8 +50,7 @@ public class PlayerDataSource { return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory( cachelessDataSourceFactory), cachelessDataSourceFactory) .setLoadErrorHandlingPolicy( - new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)) - .setLivePresentationDelayMs(LIVE_STREAM_EDGE_GAP_MILLIS, true); + new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)); } public SsMediaSource.Factory getSsMediaSourceFactory() { @@ -74,11 +73,6 @@ public class PlayerDataSource { new DefaultLoadErrorHandlingPolicy(EXTRACTOR_MINIMUM_RETRY)); } - public ProgressiveMediaSource.Factory getExtractorMediaSourceFactory( - @NonNull final String key) { - return getExtractorMediaSourceFactory().setCustomCacheKey(key); - } - public SingleSampleMediaSource.Factory getSampleMediaSourceFactory() { return new SingleSampleMediaSource.Factory(cacheDataSourceFactory); } diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java index 828833a8d..80dacc801 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java @@ -21,11 +21,11 @@ import androidx.preference.PreferenceManager; import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player.RepeatMode; import com.google.android.exoplayer2.SeekParameters; -import com.google.android.exoplayer2.text.CaptionStyleCompat; import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection; -import com.google.android.exoplayer2.trackselection.TrackSelection; +import com.google.android.exoplayer2.trackselection.ExoTrackSelection; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode; +import com.google.android.exoplayer2.ui.CaptionStyleCompat; import com.google.android.exoplayer2.util.MimeTypes; import org.schabi.newpipe.R; diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/CustomTrackSelector.java b/app/src/main/java/org/schabi/newpipe/player/playback/CustomTrackSelector.java index d70707fdb..389be7062 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playback/CustomTrackSelector.java +++ b/app/src/main/java/org/schabi/newpipe/player/playback/CustomTrackSelector.java @@ -13,7 +13,7 @@ import com.google.android.exoplayer2.RendererCapabilities.Capabilities; import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; -import com.google.android.exoplayer2.trackselection.TrackSelection; +import com.google.android.exoplayer2.trackselection.ExoTrackSelection; import com.google.android.exoplayer2.util.Assertions; /** @@ -28,7 +28,7 @@ public class CustomTrackSelector extends DefaultTrackSelector { private String preferredTextLanguage; public CustomTrackSelector(final Context context, - final TrackSelection.Factory adaptiveTrackSelectionFactory) { + final ExoTrackSelection.Factory adaptiveTrackSelectionFactory) { super(context, adaptiveTrackSelectionFactory); } @@ -50,7 +50,7 @@ public class CustomTrackSelector extends DefaultTrackSelector { @Override @Nullable - protected Pair selectTextTrack( + protected Pair selectTextTrack( final TrackGroupArray groups, @NonNull final int[][] formatSupport, @NonNull final Parameters params, @@ -86,7 +86,7 @@ public class CustomTrackSelector extends DefaultTrackSelector { } } return selectedGroup == null ? null - : Pair.create(new TrackSelection.Definition(selectedGroup, selectedTrackIndex), + : Pair.create(new ExoTrackSelection.Definition(selectedGroup, selectedTrackIndex), Assertions.checkNotNull(selectedTrackScore)); } } diff --git a/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java b/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java index 81e629c2f..d0c2009a1 100644 --- a/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java +++ b/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java @@ -35,7 +35,7 @@ public interface PlaybackResolver extends Resolver { return null; } - +0 @NonNull default MediaSource buildLiveMediaSource(@NonNull final PlayerDataSource dataSource, @NonNull final String sourceUrl, @@ -48,7 +48,12 @@ public interface PlaybackResolver extends Resolver { .createMediaSource(MediaItem.fromUri(uri)); case C.TYPE_DASH: return dataSource.getLiveDashMediaSourceFactory().setTag(metadata) - .createMediaSource(MediaItem.fromUri(uri)); + .createMediaSource( + new MediaItem.Builder() + .setUri(uri) + .setLiveTargetOffsetMs( + PlayerDataSource.LIVE_STREAM_EDGE_GAP_MILLIS) + .build()); case C.TYPE_HLS: return dataSource.getLiveHlsMediaSourceFactory().setTag(metadata) .createMediaSource(MediaItem.fromUri(uri)); @@ -78,8 +83,12 @@ public interface PlaybackResolver extends Resolver { return dataSource.getHlsMediaSourceFactory().setTag(metadata) .createMediaSource(MediaItem.fromUri(uri)); case C.TYPE_OTHER: - return dataSource.getExtractorMediaSourceFactory(cacheKey).setTag(metadata) - .createMediaSource(MediaItem.fromUri(uri)); + return dataSource.getExtractorMediaSourceFactory().setTag(metadata) + .createMediaSource( + new MediaItem.Builder() + .setUri(uri) + .setCustomCacheKey(cacheKey) + .build()); default: throw new IllegalStateException("Unsupported type: " + type); } From 38360b5c92e2715fca78f6b3db805a05ade37327 Mon Sep 17 00:00:00 2001 From: Robin Date: Fri, 22 Oct 2021 12:07:25 +0200 Subject: [PATCH 068/111] Use Android11+ extractors --- .../org/schabi/newpipe/player/Player.java | 2 +- .../player/helper/PlayerDataSource.java | 66 +++++++++++++++---- .../newpipe/player/helper/PlayerHelper.java | 28 ++++---- .../player/resolver/PlaybackResolver.java | 2 +- 4 files changed, 68 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index d2e89baa0..b2708e075 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -177,12 +177,12 @@ import org.schabi.newpipe.player.resolver.MediaSourceTag; import org.schabi.newpipe.player.resolver.VideoPlaybackResolver; import org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHelper; import org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHolder; -import org.schabi.newpipe.util.StreamTypeUtil; import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.ListHelper; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.PicassoHelper; import org.schabi.newpipe.util.SerializedCache; +import org.schabi.newpipe.util.StreamTypeUtil; import org.schabi.newpipe.util.external_communication.KoreUtils; import org.schabi.newpipe.util.external_communication.ShareUtils; import org.schabi.newpipe.views.ExpandableSurfaceView; diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java index 42a7838c3..9f419520d 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java @@ -1,14 +1,18 @@ package org.schabi.newpipe.player.helper; import android.content.Context; +import android.os.Build; import androidx.annotation.NonNull; +import com.google.android.exoplayer2.source.MediaParserExtractorAdapter; import com.google.android.exoplayer2.source.ProgressiveMediaSource; import com.google.android.exoplayer2.source.SingleSampleMediaSource; +import com.google.android.exoplayer2.source.chunk.MediaParserChunkExtractor; import com.google.android.exoplayer2.source.dash.DashMediaSource; import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource; import com.google.android.exoplayer2.source.hls.HlsMediaSource; +import com.google.android.exoplayer2.source.hls.MediaParserHlsMediaChunkExtractor; import com.google.android.exoplayer2.source.smoothstreaming.DefaultSsChunkSource; import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource; import com.google.android.exoplayer2.upstream.DataSource; @@ -40,17 +44,33 @@ public class PlayerDataSource { } public HlsMediaSource.Factory getLiveHlsMediaSourceFactory() { - return new HlsMediaSource.Factory(cachelessDataSourceFactory) - .setAllowChunklessPreparation(true) - .setLoadErrorHandlingPolicy( - new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + return new HlsMediaSource.Factory(cachelessDataSourceFactory) + .setExtractorFactory(MediaParserHlsMediaChunkExtractor.FACTORY) + .setAllowChunklessPreparation(true) + .setLoadErrorHandlingPolicy( + new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)); + } else { + return new HlsMediaSource.Factory(cachelessDataSourceFactory) + .setAllowChunklessPreparation(true) + .setLoadErrorHandlingPolicy( + new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)); + } } public DashMediaSource.Factory getLiveDashMediaSourceFactory() { - return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory( - cachelessDataSourceFactory), cachelessDataSourceFactory) - .setLoadErrorHandlingPolicy( - new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory( + MediaParserChunkExtractor.FACTORY, + cachelessDataSourceFactory, 1), cachelessDataSourceFactory) + .setLoadErrorHandlingPolicy( + new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)); + } else { + return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory( + cachelessDataSourceFactory), cachelessDataSourceFactory) + .setLoadErrorHandlingPolicy( + new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)); + } } public SsMediaSource.Factory getSsMediaSourceFactory() { @@ -59,18 +79,36 @@ public class PlayerDataSource { } public HlsMediaSource.Factory getHlsMediaSourceFactory() { - return new HlsMediaSource.Factory(cacheDataSourceFactory); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + return new HlsMediaSource.Factory(cacheDataSourceFactory) + .setExtractorFactory(MediaParserHlsMediaChunkExtractor.FACTORY); + } else { + return new HlsMediaSource.Factory(cacheDataSourceFactory); + } } public DashMediaSource.Factory getDashMediaSourceFactory() { - return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory( - cacheDataSourceFactory), cacheDataSourceFactory); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory( + MediaParserChunkExtractor.FACTORY, + cacheDataSourceFactory, 1), cacheDataSourceFactory); + } else { + return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory( + cacheDataSourceFactory), cacheDataSourceFactory); + } } public ProgressiveMediaSource.Factory getExtractorMediaSourceFactory() { - return new ProgressiveMediaSource.Factory(cacheDataSourceFactory) - .setLoadErrorHandlingPolicy( - new DefaultLoadErrorHandlingPolicy(EXTRACTOR_MINIMUM_RETRY)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + return new ProgressiveMediaSource.Factory(cacheDataSourceFactory, + MediaParserExtractorAdapter.FACTORY) + .setLoadErrorHandlingPolicy( + new DefaultLoadErrorHandlingPolicy(EXTRACTOR_MINIMUM_RETRY)); + } else { + return new ProgressiveMediaSource.Factory(cacheDataSourceFactory) + .setLoadErrorHandlingPolicy( + new DefaultLoadErrorHandlingPolicy(EXTRACTOR_MINIMUM_RETRY)); + } } public SingleSampleMediaSource.Factory getSampleMediaSourceFactory() { diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java index 80dacc801..6cb94336b 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java @@ -1,5 +1,18 @@ package org.schabi.newpipe.player.helper; +import static com.google.android.exoplayer2.Player.REPEAT_MODE_ALL; +import static com.google.android.exoplayer2.Player.REPEAT_MODE_OFF; +import static com.google.android.exoplayer2.Player.REPEAT_MODE_ONE; +import static org.schabi.newpipe.player.Player.IDLE_WINDOW_FLAGS; +import static org.schabi.newpipe.player.Player.PLAYER_TYPE; +import static org.schabi.newpipe.player.helper.PlayerHelper.AutoplayType.AUTOPLAY_TYPE_ALWAYS; +import static org.schabi.newpipe.player.helper.PlayerHelper.AutoplayType.AUTOPLAY_TYPE_NEVER; +import static org.schabi.newpipe.player.helper.PlayerHelper.AutoplayType.AUTOPLAY_TYPE_WIFI; +import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_BACKGROUND; +import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_NONE; +import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_POPUP; +import static java.lang.annotation.RetentionPolicy.SOURCE; + import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; @@ -57,19 +70,6 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.TimeUnit; -import static com.google.android.exoplayer2.Player.REPEAT_MODE_ALL; -import static com.google.android.exoplayer2.Player.REPEAT_MODE_OFF; -import static com.google.android.exoplayer2.Player.REPEAT_MODE_ONE; -import static java.lang.annotation.RetentionPolicy.SOURCE; -import static org.schabi.newpipe.player.Player.IDLE_WINDOW_FLAGS; -import static org.schabi.newpipe.player.Player.PLAYER_TYPE; -import static org.schabi.newpipe.player.helper.PlayerHelper.AutoplayType.AUTOPLAY_TYPE_ALWAYS; -import static org.schabi.newpipe.player.helper.PlayerHelper.AutoplayType.AUTOPLAY_TYPE_NEVER; -import static org.schabi.newpipe.player.helper.PlayerHelper.AutoplayType.AUTOPLAY_TYPE_WIFI; -import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_BACKGROUND; -import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_NONE; -import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_POPUP; - public final class PlayerHelper { private static final StringBuilder STRING_BUILDER = new StringBuilder(); private static final Formatter STRING_FORMATTER @@ -312,7 +312,7 @@ public final class PlayerHelper { return 500; } - public static TrackSelection.Factory getQualitySelector() { + public static ExoTrackSelection.Factory getQualitySelector() { return new AdaptiveTrackSelection.Factory( 1000, AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, diff --git a/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java b/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java index d0c2009a1..48ee305ee 100644 --- a/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java +++ b/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java @@ -35,7 +35,7 @@ public interface PlaybackResolver extends Resolver { return null; } -0 + @NonNull default MediaSource buildLiveMediaSource(@NonNull final PlayerDataSource dataSource, @NonNull final String sourceUrl, From 24bf4487d037630762b06271ea31ba933429f365 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 12 Nov 2021 19:40:00 +0100 Subject: [PATCH 069/111] De-duplicated PlayerDataSource-code --- .../player/helper/PlayerDataSource.java | 98 ++++++++++--------- 1 file changed, 51 insertions(+), 47 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java index 9f419520d..b7584151d 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java @@ -36,79 +36,83 @@ public class PlayerDataSource { } public SsMediaSource.Factory getLiveSsMediaSourceFactory() { - return new SsMediaSource.Factory(new DefaultSsChunkSource.Factory( - cachelessDataSourceFactory), cachelessDataSourceFactory) + return new SsMediaSource.Factory( + new DefaultSsChunkSource.Factory(cachelessDataSourceFactory), + cachelessDataSourceFactory + ) .setLoadErrorHandlingPolicy( new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)) .setLivePresentationDelayMs(LIVE_STREAM_EDGE_GAP_MILLIS); } public HlsMediaSource.Factory getLiveHlsMediaSourceFactory() { + final HlsMediaSource.Factory factory = + new HlsMediaSource.Factory(cachelessDataSourceFactory) + .setAllowChunklessPreparation(true) + .setLoadErrorHandlingPolicy( + new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - return new HlsMediaSource.Factory(cachelessDataSourceFactory) - .setExtractorFactory(MediaParserHlsMediaChunkExtractor.FACTORY) - .setAllowChunklessPreparation(true) - .setLoadErrorHandlingPolicy( - new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)); - } else { - return new HlsMediaSource.Factory(cachelessDataSourceFactory) - .setAllowChunklessPreparation(true) - .setLoadErrorHandlingPolicy( - new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)); + factory.setExtractorFactory(MediaParserHlsMediaChunkExtractor.FACTORY); } + + return factory; } public DashMediaSource.Factory getLiveDashMediaSourceFactory() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory( - MediaParserChunkExtractor.FACTORY, - cachelessDataSourceFactory, 1), cachelessDataSourceFactory) - .setLoadErrorHandlingPolicy( - new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)); - } else { - return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory( - cachelessDataSourceFactory), cachelessDataSourceFactory) - .setLoadErrorHandlingPolicy( - new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)); - } + return new DashMediaSource.Factory( + getDefaultDashChunkSourceFactory(cachelessDataSourceFactory), + cachelessDataSourceFactory + ) + .setLoadErrorHandlingPolicy( + new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)); } - public SsMediaSource.Factory getSsMediaSourceFactory() { - return new SsMediaSource.Factory(new DefaultSsChunkSource.Factory( - cacheDataSourceFactory), cacheDataSourceFactory); + private DefaultDashChunkSource.Factory getDefaultDashChunkSourceFactory( + final DataSource.Factory dataSourceFactory + ) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + return new DefaultDashChunkSource.Factory( + MediaParserChunkExtractor.FACTORY, + dataSourceFactory, + 1 + ); + } + + return new DefaultDashChunkSource.Factory(dataSourceFactory); } public HlsMediaSource.Factory getHlsMediaSourceFactory() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - return new HlsMediaSource.Factory(cacheDataSourceFactory) - .setExtractorFactory(MediaParserHlsMediaChunkExtractor.FACTORY); - } else { - return new HlsMediaSource.Factory(cacheDataSourceFactory); + final HlsMediaSource.Factory factory = new HlsMediaSource.Factory(cacheDataSourceFactory); + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { + return factory; } + + // *** >= Android 11 / R / API 30 *** + return factory.setExtractorFactory(MediaParserHlsMediaChunkExtractor.FACTORY); } public DashMediaSource.Factory getDashMediaSourceFactory() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory( - MediaParserChunkExtractor.FACTORY, - cacheDataSourceFactory, 1), cacheDataSourceFactory); - } else { - return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory( - cacheDataSourceFactory), cacheDataSourceFactory); - } + return new DashMediaSource.Factory( + getDefaultDashChunkSourceFactory(cacheDataSourceFactory), + cacheDataSourceFactory + ); } public ProgressiveMediaSource.Factory getExtractorMediaSourceFactory() { + final ProgressiveMediaSource.Factory factory; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - return new ProgressiveMediaSource.Factory(cacheDataSourceFactory, - MediaParserExtractorAdapter.FACTORY) - .setLoadErrorHandlingPolicy( - new DefaultLoadErrorHandlingPolicy(EXTRACTOR_MINIMUM_RETRY)); + factory = new ProgressiveMediaSource.Factory( + cacheDataSourceFactory, + MediaParserExtractorAdapter.FACTORY + ); } else { - return new ProgressiveMediaSource.Factory(cacheDataSourceFactory) - .setLoadErrorHandlingPolicy( - new DefaultLoadErrorHandlingPolicy(EXTRACTOR_MINIMUM_RETRY)); + factory = new ProgressiveMediaSource.Factory(cacheDataSourceFactory); } + + return factory.setLoadErrorHandlingPolicy( + new DefaultLoadErrorHandlingPolicy(EXTRACTOR_MINIMUM_RETRY)); } public SingleSampleMediaSource.Factory getSampleMediaSourceFactory() { From 2a9d3f5f53ae64f0498426129e0b5ed295b1e373 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 12 Nov 2021 20:14:39 +0100 Subject: [PATCH 070/111] Refactored ``PlaybackResolver`` * fixes the deprecation of ``setTag`` * makes the code more consistent * de-duplicates some code --- .../player/resolver/PlaybackResolver.java | 57 +++++++++++-------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java b/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java index 48ee305ee..cfe9dbb62 100644 --- a/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java +++ b/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java @@ -9,6 +9,7 @@ import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.source.MediaSource; +import com.google.android.exoplayer2.source.MediaSourceFactory; import com.google.android.exoplayer2.util.Util; import org.schabi.newpipe.extractor.stream.StreamInfo; @@ -41,25 +42,28 @@ public interface PlaybackResolver extends Resolver { @NonNull final String sourceUrl, @C.ContentType final int type, @NonNull final MediaSourceTag metadata) { - final Uri uri = Uri.parse(sourceUrl); + final MediaSourceFactory factory; switch (type) { case C.TYPE_SS: - return dataSource.getLiveSsMediaSourceFactory().setTag(metadata) - .createMediaSource(MediaItem.fromUri(uri)); + factory = dataSource.getLiveSsMediaSourceFactory(); + break; case C.TYPE_DASH: - return dataSource.getLiveDashMediaSourceFactory().setTag(metadata) - .createMediaSource( - new MediaItem.Builder() - .setUri(uri) - .setLiveTargetOffsetMs( - PlayerDataSource.LIVE_STREAM_EDGE_GAP_MILLIS) - .build()); + factory = dataSource.getLiveDashMediaSourceFactory(); + break; case C.TYPE_HLS: - return dataSource.getLiveHlsMediaSourceFactory().setTag(metadata) - .createMediaSource(MediaItem.fromUri(uri)); + factory = dataSource.getLiveHlsMediaSourceFactory(); + break; default: throw new IllegalStateException("Unsupported type: " + type); } + + return factory.createMediaSource( + new MediaItem.Builder() + .setTag(metadata) + .setUri(Uri.parse(sourceUrl)) + .setLiveTargetOffsetMs(PlayerDataSource.LIVE_STREAM_EDGE_GAP_MILLIS) + .build() + ); } @NonNull @@ -72,25 +76,30 @@ public interface PlaybackResolver extends Resolver { @C.ContentType final int type = TextUtils.isEmpty(overrideExtension) ? Util.inferContentType(uri) : Util.inferContentType("." + overrideExtension); + final MediaSourceFactory factory; switch (type) { case C.TYPE_SS: - return dataSource.getLiveSsMediaSourceFactory().setTag(metadata) - .createMediaSource(MediaItem.fromUri(uri)); + factory = dataSource.getLiveSsMediaSourceFactory(); + break; case C.TYPE_DASH: - return dataSource.getDashMediaSourceFactory().setTag(metadata) - .createMediaSource(MediaItem.fromUri(uri)); + factory = dataSource.getDashMediaSourceFactory(); + break; case C.TYPE_HLS: - return dataSource.getHlsMediaSourceFactory().setTag(metadata) - .createMediaSource(MediaItem.fromUri(uri)); + factory = dataSource.getHlsMediaSourceFactory(); + break; case C.TYPE_OTHER: - return dataSource.getExtractorMediaSourceFactory().setTag(metadata) - .createMediaSource( - new MediaItem.Builder() - .setUri(uri) - .setCustomCacheKey(cacheKey) - .build()); + factory = dataSource.getExtractorMediaSourceFactory(); + break; default: throw new IllegalStateException("Unsupported type: " + type); } + + return factory.createMediaSource( + new MediaItem.Builder() + .setTag(metadata) + .setUri(uri) + .setCustomCacheKey(cacheKey) + .build() + ); } } From 4923a83a29474494cc887ee5cc059afd96b76e0e Mon Sep 17 00:00:00 2001 From: TobiGr Date: Fri, 15 Oct 2021 23:23:40 +0200 Subject: [PATCH 071/111] Remove JCenter All dependencies which were fetched from JCenter are now available via Maven Central. This source change is necessary becuase JCenter announced they werer going to be read-only starting at 31st March 2021 (https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter). --- build.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/build.gradle b/build.gradle index 1bcddd7cc..145515c1e 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,6 @@ buildscript { repositories { google() mavenCentral() - jcenter() } dependencies { classpath 'com.android.tools.build:gradle:7.0.3' @@ -20,7 +19,6 @@ allprojects { repositories { google() mavenCentral() - jcenter() maven { url "https://jitpack.io" } maven { url "https://clojars.org/repo" } } From 517a98bdf967dc521b74a3a8ffca0f1b17cc2112 Mon Sep 17 00:00:00 2001 From: Nathan Schulzke Date: Sat, 13 Nov 2021 10:14:54 -0700 Subject: [PATCH 072/111] Factor out shouldAddMarkAsWatched as a shared function --- .../newpipe/fragments/list/BaseListFragment.java | 8 +------- .../fragments/list/playlist/PlaylistFragment.java | 9 +-------- .../org/schabi/newpipe/local/feed/FeedFragment.kt | 8 +------- .../local/history/StatisticsPlaylistFragment.java | 12 ++++-------- .../local/playlist/LocalPlaylistFragment.java | 12 ++++-------- .../org/schabi/newpipe/util/StreamDialogEntry.java | 12 ++++++++++++ 6 files changed, 23 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java index 6a255b914..4899af353 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java @@ -380,13 +380,7 @@ public abstract class BaseListFragment extends BaseStateFragment } // show "mark as watched" only when watch history is enabled - final boolean isWatchHistoryEnabled = PreferenceManager - .getDefaultSharedPreferences(context) - .getBoolean(getString(R.string.enable_watch_history_key), false); - if (item.getStreamType() != StreamType.AUDIO_LIVE_STREAM - && item.getStreamType() != StreamType.LIVE_STREAM - && isWatchHistoryEnabled - ) { + if (StreamDialogEntry.shouldAddMarkAsWatched(item.getStreamType(), context)) { entries.add( StreamDialogEntry.mark_as_watched ); diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java index b03dddc20..a8763af73 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java @@ -15,7 +15,6 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.content.res.AppCompatResources; -import androidx.preference.PreferenceManager; import androidx.viewbinding.ViewBinding; import org.reactivestreams.Subscriber; @@ -178,13 +177,7 @@ public class PlaylistFragment extends BaseListInfoFragment { } // show "mark as watched" only when watch history is enabled - final boolean isWatchHistoryEnabled = PreferenceManager - .getDefaultSharedPreferences(context) - .getBoolean(getString(R.string.enable_watch_history_key), false); - if (item.getStreamType() != StreamType.AUDIO_LIVE_STREAM - && item.getStreamType() != StreamType.LIVE_STREAM - && isWatchHistoryEnabled - ) { + if (StreamDialogEntry.shouldAddMarkAsWatched(item.getStreamType(), context)) { entries.add( StreamDialogEntry.mark_as_watched ); diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt index b3619276d..4959244d8 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt @@ -356,13 +356,7 @@ class FeedFragment : BaseStateFragment() { } // show "mark as watched" only when watch history is enabled - val isWatchHistoryEnabled = PreferenceManager - .getDefaultSharedPreferences(context) - .getBoolean(getString(R.string.enable_watch_history_key), false) - if (item.streamType != StreamType.AUDIO_LIVE_STREAM && - item.streamType != StreamType.LIVE_STREAM && - isWatchHistoryEnabled - ) { + if (StreamDialogEntry.shouldAddMarkAsWatched(item.streamType, context)) { entries.add( StreamDialogEntry.mark_as_watched ) diff --git a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java index 4bb907abc..4f03debca 100644 --- a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java @@ -14,7 +14,6 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.preference.PreferenceManager; import androidx.viewbinding.ViewBinding; import com.google.android.material.snackbar.Snackbar; @@ -369,13 +368,10 @@ public class StatisticsPlaylistFragment } // show "mark as watched" only when watch history is enabled - final boolean isWatchHistoryEnabled = PreferenceManager - .getDefaultSharedPreferences(context) - .getBoolean(getString(R.string.enable_watch_history_key), false); - if (item.getStreamEntity().getStreamType() != StreamType.AUDIO_LIVE_STREAM - && item.getStreamEntity().getStreamType() != StreamType.LIVE_STREAM - && isWatchHistoryEnabled - ) { + if (StreamDialogEntry.shouldAddMarkAsWatched( + item.getStreamEntity().getStreamType(), + context + )) { entries.add( StreamDialogEntry.mark_as_watched ); diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index 2e33f3db4..11174e735 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -19,7 +19,6 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; -import androidx.preference.PreferenceManager; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; import androidx.viewbinding.ViewBinding; @@ -785,13 +784,10 @@ public class LocalPlaylistFragment extends BaseLocalListFragment Date: Sun, 14 Nov 2021 20:12:12 +0100 Subject: [PATCH 073/111] Use DefaultLoadcontrol --- .../newpipe/player/helper/LoadController.java | 74 ++----------------- .../newpipe/player/helper/PlayerHelper.java | 7 -- 2 files changed, 5 insertions(+), 76 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/LoadController.java b/app/src/main/java/org/schabi/newpipe/player/helper/LoadController.java index ca3b1a3c1..ec0e4e4a7 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/LoadController.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/LoadController.java @@ -1,81 +1,28 @@ package org.schabi.newpipe.player.helper; import com.google.android.exoplayer2.DefaultLoadControl; -import com.google.android.exoplayer2.LoadControl; -import com.google.android.exoplayer2.Renderer; -import com.google.android.exoplayer2.source.TrackGroupArray; -import com.google.android.exoplayer2.trackselection.ExoTrackSelection; -import com.google.android.exoplayer2.upstream.Allocator; -public class LoadController implements LoadControl { +public class LoadController extends DefaultLoadControl { public static final String TAG = "LoadController"; - - private final long initialPlaybackBufferUs; - private final LoadControl internalLoadControl; private boolean preloadingEnabled = true; - /*////////////////////////////////////////////////////////////////////////// - // Default Load Control - //////////////////////////////////////////////////////////////////////////*/ - - public LoadController() { - this(PlayerHelper.getPlaybackStartBufferMs()); - } - - private LoadController(final int initialPlaybackBufferMs) { - this.initialPlaybackBufferUs = initialPlaybackBufferMs * 1000; - - final DefaultLoadControl.Builder builder = new DefaultLoadControl.Builder(); - builder.setBufferDurationsMs( - DefaultLoadControl.DEFAULT_MIN_BUFFER_MS, - DefaultLoadControl.DEFAULT_MAX_BUFFER_MS, - initialPlaybackBufferMs, - DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS); - internalLoadControl = builder.build(); - } - - /*////////////////////////////////////////////////////////////////////////// - // Custom behaviours - //////////////////////////////////////////////////////////////////////////*/ - @Override public void onPrepared() { preloadingEnabled = true; - internalLoadControl.onPrepared(); - } - - @Override - public void onTracksSelected(final Renderer[] renderers, final TrackGroupArray trackGroups, - final ExoTrackSelection[] trackSelections) { - internalLoadControl.onTracksSelected(renderers, trackGroups, trackSelections); + super.onPrepared(); } @Override public void onStopped() { preloadingEnabled = true; - internalLoadControl.onStopped(); + super.onStopped(); } @Override public void onReleased() { preloadingEnabled = true; - internalLoadControl.onReleased(); - } - - @Override - public Allocator getAllocator() { - return internalLoadControl.getAllocator(); - } - - @Override - public long getBackBufferDurationUs() { - return internalLoadControl.getBackBufferDurationUs(); - } - - @Override - public boolean retainBackBufferFromKeyframe() { - return internalLoadControl.retainBackBufferFromKeyframe(); + super.onReleased(); } @Override @@ -85,21 +32,10 @@ public class LoadController implements LoadControl { if (!preloadingEnabled) { return false; } - return internalLoadControl.shouldContinueLoading( + return super.shouldContinueLoading( playbackPositionUs, bufferedDurationUs, playbackSpeed); } - @Override - public boolean shouldStartPlayback(final long bufferedDurationUs, final float playbackSpeed, - final boolean rebuffering, final long targetLiveOffsetUs) { - final boolean isInitialPlaybackBufferFilled - = bufferedDurationUs >= this.initialPlaybackBufferUs * playbackSpeed; - final boolean isInternalStartingPlayback = internalLoadControl - .shouldStartPlayback(bufferedDurationUs, playbackSpeed, rebuffering, - targetLiveOffsetUs); - return isInitialPlaybackBufferFilled || isInternalStartingPlayback; - } - public void disablePreloadingOfCurrentTrack() { preloadingEnabled = false; } diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java index 6cb94336b..c51b6d5dd 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java @@ -305,13 +305,6 @@ public final class PlayerHelper { return 2 * 1024 * 1024L; // ExoPlayer CacheDataSink.MIN_RECOMMENDED_FRAGMENT_SIZE } - /** - * @return the number of milliseconds the player buffers for before starting playback - */ - public static int getPlaybackStartBufferMs() { - return 500; - } - public static ExoTrackSelection.Factory getQualitySelector() { return new AdaptiveTrackSelection.Factory( 1000, From b85196aa4f7ce40dbd36fdf00d23440f14491385 Mon Sep 17 00:00:00 2001 From: Robin Date: Sun, 14 Nov 2021 21:19:36 +0100 Subject: [PATCH 074/111] Fixed Period Transition --- app/src/main/java/org/schabi/newpipe/player/Player.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index b2708e075..4cc0d4aa4 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -2448,6 +2448,7 @@ public final class Player implements // Refresh the playback if there is a transition to the next video final int newWindowIndex = simpleExoPlayer.getCurrentWindowIndex(); switch (discontinuityReason) { + case DISCONTINUITY_REASON_AUTO_TRANSITION: case DISCONTINUITY_REASON_REMOVE: // When player is in single repeat mode and a period transition occurs, // we need to register a view count here since no metadata has changed @@ -2470,7 +2471,6 @@ public final class Player implements } break; case DISCONTINUITY_REASON_SKIP: - case DISCONTINUITY_REASON_AUTO_TRANSITION: break; // only makes Android Studio linter happy, as there are no ads } From ca37d7cb66a4048f4551c06ac752db80af0ea75c Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Mon, 8 Nov 2021 19:41:13 +0100 Subject: [PATCH 075/111] Prevent automatic replay after returning from background See also https://github.com/TeamNewPipe/NewPipe/pull/7195#issuecomment-962624380 --- .../main/java/org/schabi/newpipe/player/Player.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index b2708e075..4310ccad7 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -857,9 +857,15 @@ public final class Player implements final int queuePos = playQueue.getIndex(); final long windowPos = simpleExoPlayer.getCurrentPosition(); + final long duration = simpleExoPlayer.getDuration(); - if (windowPos > 0 && windowPos <= simpleExoPlayer.getDuration()) { - setRecovery(queuePos, windowPos); + if (windowPos > 0 + // Sometimes (e.g. when the playback ended) the windowPos is a few milliseconds + // higher than the duration. Due to this a little buffer (100ms) was introduced. + // See also https://github.com/TeamNewPipe/NewPipe/pull/7195#issuecomment-962624380 + && windowPos <= duration + 100 + ) { + setRecovery(queuePos, Math.min(windowPos, duration)); } } From 5c1315641dfec2516a760e49337c26abb70947d0 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Mon, 15 Nov 2021 19:56:14 +0100 Subject: [PATCH 076/111] setRecovery: Remove checks and use Math.min/max --- .../main/java/org/schabi/newpipe/player/Player.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 4310ccad7..d448de5a4 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -859,14 +859,8 @@ public final class Player implements final long windowPos = simpleExoPlayer.getCurrentPosition(); final long duration = simpleExoPlayer.getDuration(); - if (windowPos > 0 - // Sometimes (e.g. when the playback ended) the windowPos is a few milliseconds - // higher than the duration. Due to this a little buffer (100ms) was introduced. - // See also https://github.com/TeamNewPipe/NewPipe/pull/7195#issuecomment-962624380 - && windowPos <= duration + 100 - ) { - setRecovery(queuePos, Math.min(windowPos, duration)); - } + // No checks due to https://github.com/TeamNewPipe/NewPipe/pull/7195#issuecomment-962624380 + setRecovery(queuePos, Math.max(0, Math.min(windowPos, duration))); } private void setRecovery(final int queuePos, final long windowPos) { From b98b4b59dcd057578fe9588b34c95f8d2a189867 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 3 Sep 2021 21:29:10 +0200 Subject: [PATCH 077/111] Enhanced ``View.slideUp`` --- .../main/java/org/schabi/newpipe/ktx/View.kt | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/ktx/View.kt b/app/src/main/java/org/schabi/newpipe/ktx/View.kt index 8f2249493..d7e5a1c42 100644 --- a/app/src/main/java/org/schabi/newpipe/ktx/View.kt +++ b/app/src/main/java/org/schabi/newpipe/ktx/View.kt @@ -299,18 +299,36 @@ private fun View.animateLightSlideAndAlpha(enterOrExit: Boolean, duration: Long, } } -fun View.slideUp(duration: Long, delay: Long, @FloatRange(from = 0.0, to = 1.0) translationPercent: Float) { +fun View.slideUp( + duration: Long, + delay: Long, + @FloatRange(from = 0.0, to = 1.0) translationPercent: Float +) { + slideUp(duration, delay, translationPercent) +} + +fun View.slideUp( + duration: Long, + delay: Long = 0L, + @FloatRange(from = 0.0, to = 1.0) translationPercent: Float = 1.0F, + execOnEnd: Runnable? = null +) { val newTranslationY = (resources.displayMetrics.heightPixels * translationPercent).toInt() animate().setListener(null).cancel() alpha = 0f translationY = newTranslationY.toFloat() - visibility = View.VISIBLE + isVisible = true animate() .alpha(1f) .translationY(0f) .setStartDelay(delay) .setDuration(duration) .setInterpolator(FastOutSlowInInterpolator()) + .setListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + execOnEnd?.run() + } + }) .start() } From 0dfbcb8c04325fa2d03d5846b0aae846bc485c8a Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 3 Sep 2021 21:35:23 +0200 Subject: [PATCH 078/111] No more reaction to unnecessary feed db-changes This caused duplicate events (https://github.com/TeamNewPipe/NewPipe/pull/6686#issuecomment-909575283) and unnecessary processing of items --- .../newpipe/database/feed/dao/FeedDAO.kt | 9 ++--- .../newpipe/local/feed/FeedDatabaseManager.kt | 2 +- .../newpipe/local/feed/FeedViewModel.kt | 34 ++++++++++++++----- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt b/app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt index 689f1ead6..72692a9f5 100644 --- a/app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt +++ b/app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt @@ -7,6 +7,7 @@ import androidx.room.Query import androidx.room.Transaction import androidx.room.Update import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.core.Maybe import org.schabi.newpipe.database.feed.model.FeedEntity import org.schabi.newpipe.database.feed.model.FeedLastUpdatedEntity import org.schabi.newpipe.database.stream.StreamWithState @@ -37,7 +38,7 @@ abstract class FeedDAO { LIMIT 500 """ ) - abstract fun getAllStreams(): Flowable> + abstract fun getAllStreams(): Maybe> @Query( """ @@ -62,7 +63,7 @@ abstract class FeedDAO { LIMIT 500 """ ) - abstract fun getAllStreamsForGroup(groupId: Long): Flowable> + abstract fun getAllStreamsForGroup(groupId: Long): Maybe> /** * @see StreamStateEntity.isFinished() @@ -97,7 +98,7 @@ abstract class FeedDAO { LIMIT 500 """ ) - abstract fun getLiveOrNotPlayedStreams(): Flowable> + abstract fun getLiveOrNotPlayedStreams(): Maybe> /** * @see StreamStateEntity.isFinished() @@ -137,7 +138,7 @@ abstract class FeedDAO { LIMIT 500 """ ) - abstract fun getLiveOrNotPlayedStreamsForGroup(groupId: Long): Flowable> + abstract fun getLiveOrNotPlayedStreamsForGroup(groupId: Long): Maybe> @Query( """ diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedDatabaseManager.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedDatabaseManager.kt index ff7c2848e..e28f2d31a 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedDatabaseManager.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedDatabaseManager.kt @@ -42,7 +42,7 @@ class FeedDatabaseManager(context: Context) { fun getStreams( groupId: Long = FeedGroupEntity.GROUP_ALL_ID, getPlayedStreams: Boolean = true - ): Flowable> { + ): Maybe> { return when (groupId) { FeedGroupEntity.GROUP_ALL_ID -> { if (getPlayedStreams) feedTable.getAllStreams() diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt index ecdcb7349..bdf5a60a8 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt @@ -33,12 +33,9 @@ class FeedViewModel( private var feedDatabaseManager: FeedDatabaseManager = FeedDatabaseManager(applicationContext) private val toggleShowPlayedItems = BehaviorProcessor.create() - private val streamItems = toggleShowPlayedItems + private val toggleShowPlayedItemsFlowable = toggleShowPlayedItems .startWithItem(initialShowPlayedItems) .distinctUntilChanged() - .switchMap { showPlayedItems -> - feedDatabaseManager.getStreams(groupId, showPlayedItems) - } private val mutableStateLiveData = MutableLiveData() val stateLiveData: LiveData = mutableStateLiveData @@ -46,17 +43,28 @@ class FeedViewModel( private var combineDisposable = Flowable .combineLatest( FeedEventManager.events(), - streamItems, + toggleShowPlayedItemsFlowable, feedDatabaseManager.notLoadedCount(groupId), feedDatabaseManager.oldestSubscriptionUpdate(groupId), - Function4 { t1: FeedEventManager.Event, t2: List, + Function4 { t1: FeedEventManager.Event, t2: Boolean, t3: Long, t4: List -> - return@Function4 CombineResultHolder(t1, t2, t3, t4.firstOrNull()) + return@Function4 CombineResultEventHolder(t1, t2, t3, t4.firstOrNull()) } ) .throttleLatest(DEFAULT_THROTTLE_TIMEOUT, TimeUnit.MILLISECONDS) .subscribeOn(Schedulers.io()) + .observeOn(Schedulers.io()) + .map { (event, showPlayedItems, notLoadedCount, oldestUpdate) -> + var streamItems = if (event is SuccessResultEvent || event is IdleEvent) + feedDatabaseManager + .getStreams(groupId, showPlayedItems) + .blockingGet(arrayListOf()) + else + arrayListOf() + + CombineResultDataHolder(event, streamItems, notLoadedCount, oldestUpdate) + } .observeOn(AndroidSchedulers.mainThread()) .subscribe { (event, listFromDB, notLoadedCount, oldestUpdate) -> mutableStateLiveData.postValue( @@ -78,7 +86,17 @@ class FeedViewModel( combineDisposable.dispose() } - private data class CombineResultHolder(val t1: FeedEventManager.Event, val t2: List, val t3: Long, val t4: OffsetDateTime?) + private data class CombineResultEventHolder( + val t1: FeedEventManager.Event, + val t2: Boolean, + val t3: Long, + val t4: OffsetDateTime?) + + private data class CombineResultDataHolder( + val t1: FeedEventManager.Event, + val t2: List, + val t3: Long, + val t4: OffsetDateTime?) fun togglePlayedItems(showPlayedItems: Boolean) { toggleShowPlayedItems.onNext(showPlayedItems) From 1b42543351f15815d36e72e1663490f754591548 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 3 Sep 2021 22:03:34 +0200 Subject: [PATCH 079/111] Implemented UI highlighting and "new feed items"-notification Fixed format --- .../main/java/org/schabi/newpipe/ktx/View.kt | 14 +- .../schabi/newpipe/local/feed/FeedFragment.kt | 128 +++++++++++++++++- .../newpipe/local/feed/FeedViewModel.kt | 24 ++-- .../newpipe/local/feed/item/StreamItem.kt | 9 ++ app/src/main/res/layout/fragment_feed.xml | 20 +++ app/src/main/res/values/strings.xml | 1 + 6 files changed, 176 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/ktx/View.kt b/app/src/main/java/org/schabi/newpipe/ktx/View.kt index d7e5a1c42..496ae814f 100644 --- a/app/src/main/java/org/schabi/newpipe/ktx/View.kt +++ b/app/src/main/java/org/schabi/newpipe/ktx/View.kt @@ -300,18 +300,18 @@ private fun View.animateLightSlideAndAlpha(enterOrExit: Boolean, duration: Long, } fun View.slideUp( - duration: Long, - delay: Long, - @FloatRange(from = 0.0, to = 1.0) translationPercent: Float + duration: Long, + delay: Long, + @FloatRange(from = 0.0, to = 1.0) translationPercent: Float ) { slideUp(duration, delay, translationPercent) } fun View.slideUp( - duration: Long, - delay: Long = 0L, - @FloatRange(from = 0.0, to = 1.0) translationPercent: Float = 1.0F, - execOnEnd: Runnable? = null + duration: Long, + delay: Long = 0L, + @FloatRange(from = 0.0, to = 1.0) translationPercent: Float = 1.0F, + execOnEnd: Runnable? = null ) { val newTranslationY = (resources.displayMetrics.heightPixels * translationPercent).toInt() animate().setListener(null).cancel() diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt index 118e65023..b408fa9b7 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt @@ -40,8 +40,10 @@ import androidx.core.view.isVisible import androidx.lifecycle.ViewModelProvider import androidx.preference.PreferenceManager import androidx.recyclerview.widget.GridLayoutManager -import com.xwray.groupie.GroupieAdapter +import androidx.recyclerview.widget.RecyclerView +import com.xwray.groupie.GroupAdapter import com.xwray.groupie.Item +import com.xwray.groupie.OnAsyncUpdateListener import com.xwray.groupie.OnItemClickListener import com.xwray.groupie.OnItemLongClickListener import icepick.State @@ -65,6 +67,7 @@ import org.schabi.newpipe.fragments.BaseStateFragment import org.schabi.newpipe.info_list.InfoItemDialog import org.schabi.newpipe.ktx.animate import org.schabi.newpipe.ktx.animateHideRecyclerViewAllowingScrolling +import org.schabi.newpipe.ktx.slideUp import org.schabi.newpipe.local.feed.item.StreamItem import org.schabi.newpipe.local.feed.service.FeedLoadService import org.schabi.newpipe.local.subscription.SubscriptionManager @@ -76,6 +79,7 @@ import org.schabi.newpipe.util.ThemeHelper.getGridSpanCountStreams import org.schabi.newpipe.util.ThemeHelper.shouldUseGridLayout import java.time.OffsetDateTime import java.util.ArrayList +import java.util.function.Consumer class FeedFragment : BaseStateFragment() { private var _feedBinding: FragmentFeedBinding? = null @@ -97,6 +101,8 @@ class FeedFragment : BaseStateFragment() { private var updateListViewModeOnResume = false private var isRefreshing = false + private var lastNewItemsCount = 0 + init { setHasOptionsMenu(true) } @@ -136,6 +142,20 @@ class FeedFragment : BaseStateFragment() { setOnItemLongClickListener(listenerStreamItem) } + feedBinding.itemsList.addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { + // Check if we scrolled to the top + if (newState == RecyclerView.SCROLL_STATE_IDLE && + !recyclerView.canScrollVertically(-1) + ) { + + if (feedBinding.newItemsLoadedLayout.isVisible) { + hideNewItemsLoaded(true) + } + } + } + }) + feedBinding.itemsList.adapter = groupAdapter setupListViewMode() } @@ -171,6 +191,10 @@ class FeedFragment : BaseStateFragment() { super.initListeners() feedBinding.refreshRootView.setOnClickListener { reloadContent() } feedBinding.swipeRefreshLayout.setOnRefreshListener { reloadContent() } + feedBinding.newItemsLoadedButton.setOnClickListener { + hideNewItemsLoaded(true) + feedBinding.itemsList.scrollToPosition(0) + } } // ///////////////////////////////////////////////////////////////////////// @@ -400,7 +424,17 @@ class FeedFragment : BaseStateFragment() { } loadedState.items.forEach { it.itemVersion = itemVersion } - groupAdapter.updateAsync(loadedState.items, false, null) + // This need to be saved in a variable as the update occurs async + val oldOldestSubscriptionUpdate = oldestSubscriptionUpdate + + groupAdapter.updateAsync( + loadedState.items, false, + OnAsyncUpdateListener { + oldOldestSubscriptionUpdate?.run { + highlightNewItemsAfter(oldOldestSubscriptionUpdate) + } + } + ) listState?.run { feedBinding.itemsList.layoutManager?.onRestoreInstanceState(listState) @@ -522,6 +556,94 @@ class FeedFragment : BaseStateFragment() { ) } + /** + * Highlights all items that are after the specified time + */ + private fun highlightNewItemsAfter(updateTime: OffsetDateTime) { + var highlightCount = 0 + + var doCheck = true + + for (i in 0 until groupAdapter.itemCount) { + val item = groupAdapter.getItem(i) as StreamItem + + var resid = R.attr.selectableItemBackground + if (doCheck) { + if (item.streamWithState.stream.uploadDate?.isAfter(updateTime) != false) { + resid = R.attr.dashed_border + highlightCount++ + } else { + // Increases execution time due to the order of the items (newest always on top) + // Once a item is is before the updateTime we can skip all following items + doCheck = false + } + } + + // The highlighter has to be always set + // When it's only set on items that are highlighted it will highlight all items + // due to the fact that itemRoot is getting recycled + item.execBindEnd = Consumer { viewBinding -> + val context = viewBinding.itemRoot.context + viewBinding.itemRoot.background = + androidx.core.content.ContextCompat.getDrawable( + context, + android.util.TypedValue().apply { + context.theme.resolveAttribute( + resid, + this, + true + ) + }.resourceId + ) + } + } + + // Force updates all items so that the highlighting is correct + // If this isn't done visible items that are already highlighted will stay in a highlighted + // state until the user scrolls them out of the visible area which causes a update/bind-call + groupAdapter.notifyItemRangeChanged( + 0, + groupAdapter.itemCount.coerceAtMost(highlightCount.coerceAtLeast(lastNewItemsCount)) + ) + + if (highlightCount > 0) { + showNewItemsLoaded() + } + + lastNewItemsCount = highlightCount + } + + private fun showNewItemsLoaded() { + feedBinding.newItemsLoadedLayout.clearAnimation() + feedBinding.newItemsLoadedLayout + .slideUp( + 250L, + delay = 100, + execOnEnd = { + // Hide the new items-"popup" after 10s + hideNewItemsLoaded(true, 10000) + } + ) + } + + private fun hideNewItemsLoaded(animate: Boolean, delay: Long = 0) { + feedBinding.newItemsLoadedLayout.clearAnimation() + if (animate) { + feedBinding.newItemsLoadedLayout.animate( + false, + 200, + delay = delay, + execOnEnd = { + // Make the layout invisible so that the onScroll toTop method + // only does necessary work + feedBinding.newItemsLoadedLayout.isVisible = false + } + ) + } else { + feedBinding.newItemsLoadedLayout.isVisible = false + } + } + // ///////////////////////////////////////////////////////////////////////// // Load Service Handling // ///////////////////////////////////////////////////////////////////////// @@ -529,6 +651,8 @@ class FeedFragment : BaseStateFragment() { override fun doInitialLoadLogic() {} override fun reloadContent() { + hideNewItemsLoaded(false) + getActivity()?.startService( Intent(requireContext(), FeedLoadService::class.java).apply { putExtra(FeedLoadService.EXTRA_GROUP_ID, groupId) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt index bdf5a60a8..2cbf9ad05 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt @@ -43,7 +43,7 @@ class FeedViewModel( private var combineDisposable = Flowable .combineLatest( FeedEventManager.events(), - toggleShowPlayedItemsFlowable, + toggleShowPlayedItemsFlowable, feedDatabaseManager.notLoadedCount(groupId), feedDatabaseManager.oldestSubscriptionUpdate(groupId), @@ -58,8 +58,8 @@ class FeedViewModel( .map { (event, showPlayedItems, notLoadedCount, oldestUpdate) -> var streamItems = if (event is SuccessResultEvent || event is IdleEvent) feedDatabaseManager - .getStreams(groupId, showPlayedItems) - .blockingGet(arrayListOf()) + .getStreams(groupId, showPlayedItems) + .blockingGet(arrayListOf()) else arrayListOf() @@ -87,16 +87,18 @@ class FeedViewModel( } private data class CombineResultEventHolder( - val t1: FeedEventManager.Event, - val t2: Boolean, - val t3: Long, - val t4: OffsetDateTime?) + val t1: FeedEventManager.Event, + val t2: Boolean, + val t3: Long, + val t4: OffsetDateTime? + ) private data class CombineResultDataHolder( - val t1: FeedEventManager.Event, - val t2: List, - val t3: Long, - val t4: OffsetDateTime?) + val t1: FeedEventManager.Event, + val t2: List, + val t3: Long, + val t4: OffsetDateTime? + ) fun togglePlayedItems(showPlayedItems: Boolean) { toggleShowPlayedItems.onNext(showPlayedItems) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt b/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt index 0d2caf126..217e3f3e3 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt @@ -19,6 +19,7 @@ import org.schabi.newpipe.util.Localization import org.schabi.newpipe.util.PicassoHelper import org.schabi.newpipe.util.StreamTypeUtil import java.util.concurrent.TimeUnit +import java.util.function.Consumer data class StreamItem( val streamWithState: StreamWithState, @@ -31,6 +32,12 @@ data class StreamItem( private val stream: StreamEntity = streamWithState.stream private val stateProgressTime: Long? = streamWithState.stateProgressMillis + /** + * Will be executed at the end of the [StreamItem.bind] (with (ListStreamItemBinding,Int)). + * Can be used e.g. for highlighting a item. + */ + var execBindEnd: Consumer? = null + override fun getId(): Long = stream.uid enum class ItemVersion { NORMAL, MINI, GRID } @@ -97,6 +104,8 @@ data class StreamItem( viewBinding.itemAdditionalDetails.text = getStreamInfoDetailLine(viewBinding.itemAdditionalDetails.context) } + + execBindEnd?.accept(viewBinding) } override fun isLongClickable() = when (stream.streamType) { diff --git a/app/src/main/res/layout/fragment_feed.xml b/app/src/main/res/layout/fragment_feed.xml index d5ba0e8e3..8b2a44141 100644 --- a/app/src/main/res/layout/fragment_feed.xml +++ b/app/src/main/res/layout/fragment_feed.xml @@ -87,6 +87,26 @@ + + +