From 108af48b76486d682f8c0c39548e8251358359f2 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 d844e0aba6550e60c417cd663a450ff14c5fcc89 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 87c958b2e711d70ce516ecbc4785d96d7ebc6e2b 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 ceb55d0ede4b7d6c6a9bda7023687adb2242054b 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 4fde62ff89407dc6169d59071f573e501897df2d 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 1c9f68bcae833fd2e3c6964fe29d30f19c800101 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 64d743285258e48033b3d806c68546ad8e368040 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 731640997e74af702a0df44a93ec6f3043b83292 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 d7d87691cb776c13cda8ccdb8a6d04448e53146a 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 12aac09c7bed2700e7966e3b2bf157cc2f47a175 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 9d7e9289bb88a4acb8ac9fb326f4f7b02797911c 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 658d9882544dd15cd2156dda1734b18fedc6f3ce 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 a2ff770afca39876817367ca6d11530dc655dacc 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 50634eb2b3963c70b22c16611bcfcbdb8562624a 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 afc8db8f816fb452aad407749ef032adaf9bf009 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 2271ea4281ef1e05e08593e3d9e1314f09a2428d 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 03d2ca9f9fe1c4ed55fb674cf88a6941fbf1f958 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 e7773d88077f57b4d37c0c4dd19449c9203fb1df 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 a55acd38dfad9027030f3668fbd895b947955448 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 3ded6feddb3921eeecf2b5b3030573bd39017a3a 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 aab09c0c656e9f74ada7736a58306d086a08d4b0 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 50b85a7734f9d463007e6352c5230349df4744ac 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 a744775fe771a9aad41668470ebe55193a83e5d7 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 ddaafb68c8561bb740c086d72c3b04ee69a9c22f 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 51837ce36f512f0469acbc7fec7f63f3b6280522 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 b6b19b474eba23369b5250c250ab7fe7e8adbef2 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 ed86b1c572bd9ca0b495e34ac7b57969caea95dd 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 d2306b0fd71e2d8fe6bf7efa90e1d3d1eadcd8e6 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 cf81c3768354dcf0127192cf054ac65cc2503d02 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 d66f933c69ff5064184e2502eac1c7dce520cef1 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 af936bc64602126f1ed06e477bc748ef617f6370 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 61972141aeeeacf2d921a28449413f65a524def8 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 f6efd302dcf2510cbcecc566a84538438df1f201 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 25e120bec1233b2e5d8ed7644408c7c0f49727a1 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 0bcc9bd3ba67b34ecf19aac98c4b1a65f85b4b6a 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 85fb5827aa30fb5f849b107e192e8529c0f1290b 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 5c9705d94e4821eb857f42a6af8a6903210b81c8 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 467bd21de2995ccd3278a358524663ce2c86d694 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 8dc34274a1682f4364b87c121df30b53bd453d13 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 e5fd24b0d19d35d56efb15219277821b4afd00d2 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 403154b2e1341a9127380ae22883c04ed1dac606 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 acaf92d671b4dce40632df97504958ccd68ee2c4 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 702adb53a7a0e5142805af6a85f2cdb239777f9c 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 ecac897e7b9e80690ed661bdb3c30df4f45ab3cd 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 ad8f791f71d593df9bde4176fb5a226e9056180e 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 cddb9bccb93f69ed61bd738164b14b1cd14ce287 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 f933db811711a29b7e3e61e60a33b01d799faccb 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 272be36dd934f3ae50343983bad70132099d81bf 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 28f167fd9932edc3bd11f0624a18de4923190773 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 2b2f1ee8f5e81ee328b39f1c393a92612c7c2131 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 0764983ac68b8d9d137c1dd51249bcd09381cd92 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 478ad42977f90ca07f447361a7ebfc93530801cc 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 b0a10f054293299db41cf9126f28845934efba91 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 a23f941ac89b003c0c6b01738473e01df1cdab1d 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 203ca9afc62527a64804d72bb5ed71c61f88873a 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 62efb588efd056b0414cca7c191a7b48ee155281 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 63291f81011757bc6a6709f9e4a4671f9e9471a2 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 c35fe4f3f199b59e3763c8983ac8851e2488eefd 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 adf9badbf6a8e49a7aba8953f977283a125ab985 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 90cc8e2144b93db9d3557e16c376c09b7922402f 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 53303ac5d39559ebd02f5c48a7bb248d2da1e74a 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 eae1f8b5976dd11cfc4435a3302b8913d1d2ac9a 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 1b9c2b37c5e1b1c74a4ad27ae3592b8b4a4f2f8d 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 dd2cde3c1adafd09734bd652f604ab4a8434c006 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 48a1ab64b01d5106fa7f7fc4790312b967607966 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 605b8fac5efda4e0f68c81a4e333dd7c2198f09c 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 dee32c3dc5753f470159efd446dfc4aa052ba535 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 3e099fb2a349622d04c62dba55bc576f8f42199d 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 010c607e40cc08314cd623b716c9ca10d263762d 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 316db0e4c626986f19565dded5f2d4f8d85bffbe 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 8b807b07069aa2ffd6650090b4be543f6366e1ed 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 676bc02d5256294e981c375216a6c04125d7d871 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 02789122a094628fdbd00f788e6870dcf6bf4470 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 @@ + + +