From f78983b16b6cd53269d14fc7fdf602703d47c11b Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sat, 27 Nov 2021 15:52:54 +0100 Subject: [PATCH 01/49] Show an alert/dialog when no appropriate file-manager was found --- .../newpipe/download/DownloadDialog.java | 18 +++++++++-- .../subscription/SubscriptionFragment.kt | 21 ++++++++++--- .../SubscriptionsImportFragment.java | 13 ++++++-- .../settings/ContentSettingsFragment.java | 26 +++++++++++----- .../settings/DownloadSettingsFragment.java | 9 +++++- .../streams/io/NoFileManagerHelper.java | 31 +++++++++++++++++++ .../giga/ui/fragment/MissionsFragment.java | 15 +++++++-- app/src/main/res/values/strings.xml | 1 + 8 files changed, 114 insertions(+), 20 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerHelper.java diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java index a7f5b938f..49b9024cd 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java @@ -1,6 +1,7 @@ package org.schabi.newpipe.download; import android.app.Activity; +import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; @@ -53,6 +54,7 @@ import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.SubtitlesStream; import org.schabi.newpipe.extractor.stream.VideoStream; import org.schabi.newpipe.settings.NewPipeSettings; +import org.schabi.newpipe.streams.io.NoFileManagerHelper; import org.schabi.newpipe.streams.io.StoredDirectoryHelper; import org.schabi.newpipe.streams.io.StoredFileHelper; import org.schabi.newpipe.util.FilePickerActivityHelper; @@ -687,7 +689,12 @@ public class DownloadDialog extends DialogFragment } private void launchDirectoryPicker(final ActivityResultLauncher launcher) { - launcher.launch(StoredDirectoryHelper.getPicker(context)); + try { + launcher.launch(StoredDirectoryHelper.getPicker(context)); + } catch (final ActivityNotFoundException aex) { + Log.w(TAG, "Unable to launch directory-picker", aex); + NoFileManagerHelper.showActivityNotFoundAlert(getContext()); + } } private void prepareSelectedDownload() { @@ -766,8 +773,13 @@ public class DownloadDialog extends DialogFragment initialPath = Uri.parse(initialSavePath.getAbsolutePath()); } - requestDownloadSaveAsLauncher.launch(StoredFileHelper.getNewPicker(context, - filenameTmp, mimeTmp, initialPath)); + try { + requestDownloadSaveAsLauncher.launch(StoredFileHelper.getNewPicker(context, + filenameTmp, mimeTmp, initialPath)); + } catch (final ActivityNotFoundException aex) { + Log.w(TAG, "Unable to launch file-picker", aex); + NoFileManagerHelper.showActivityNotFoundAlert(getContext()); + } return; } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index 57e1effbe..8b170279d 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -1,6 +1,7 @@ package org.schabi.newpipe.local.subscription import android.app.Activity +import android.content.ActivityNotFoundException import android.content.BroadcastReceiver import android.content.Context import android.content.DialogInterface @@ -8,6 +9,7 @@ import android.content.Intent import android.content.IntentFilter import android.os.Bundle import android.os.Parcelable +import android.util.Log import android.view.LayoutInflater import android.view.Menu import android.view.MenuInflater @@ -55,6 +57,7 @@ import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_MODE import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_VALUE import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.PREVIOUS_EXPORT_MODE +import org.schabi.newpipe.streams.io.NoFileManagerHelper import org.schabi.newpipe.streams.io.StoredFileHelper import org.schabi.newpipe.util.NavigationHelper import org.schabi.newpipe.util.OnClickGesture @@ -179,16 +182,26 @@ class SubscriptionFragment : BaseStateFragment() { } private fun onImportPreviousSelected() { - requestImportLauncher.launch(StoredFileHelper.getPicker(activity, JSON_MIME_TYPE)) + try { + requestImportLauncher.launch(StoredFileHelper.getPicker(activity, JSON_MIME_TYPE)) + } catch (aex: ActivityNotFoundException) { + Log.w(TAG, "Unable to launch file-picker", aex) + NoFileManagerHelper.showActivityNotFoundAlert(context) + } } private fun onExportSelected() { val date = SimpleDateFormat("yyyyMMddHHmm", Locale.ENGLISH).format(Date()) val exportName = "newpipe_subscriptions_$date.json" - requestExportLauncher.launch( - StoredFileHelper.getNewPicker(activity, exportName, JSON_MIME_TYPE, null) - ) + try { + requestExportLauncher.launch( + StoredFileHelper.getNewPicker(activity, exportName, JSON_MIME_TYPE, null) + ) + } catch (aex: ActivityNotFoundException) { + Log.w(TAG, "Unable to launch file-picker", aex) + NoFileManagerHelper.showActivityNotFoundAlert(context) + } } private fun openReorderDialog() { diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java index 675799586..10816922b 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java @@ -1,10 +1,12 @@ package org.schabi.newpipe.local.subscription; import android.app.Activity; +import android.content.ActivityNotFoundException; import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; import android.text.util.Linkify; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -30,6 +32,7 @@ import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor; import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService; +import org.schabi.newpipe.streams.io.NoFileManagerHelper; import org.schabi.newpipe.streams.io.StoredFileHelper; import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.ServiceHelper; @@ -175,8 +178,14 @@ public class SubscriptionsImportFragment extends BaseFragment { } public void onImportFile() { - // leave */* mime type to support all services with different mime types and file extensions - requestImportFileLauncher.launch(StoredFileHelper.getPicker(activity, "*/*")); + try { + // leave */* mime type to support all services + // with different mime types and file extensions + requestImportFileLauncher.launch(StoredFileHelper.getPicker(activity, "*/*")); + } catch (final ActivityNotFoundException aex) { + Log.w(TAG, "Unable to launch file-picker", aex); + NoFileManagerHelper.showActivityNotFoundAlert(getContext()); + } } private void requestImportFileResult(final ActivityResult result) { diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java index 6e7e75932..3e72cf9a6 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java @@ -1,6 +1,7 @@ package org.schabi.newpipe.settings; import android.app.Activity; +import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -25,6 +26,7 @@ import org.schabi.newpipe.error.ReCaptchaActivity; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.localization.ContentCountry; import org.schabi.newpipe.extractor.localization.Localization; +import org.schabi.newpipe.streams.io.NoFileManagerHelper; import org.schabi.newpipe.streams.io.StoredFileHelper; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.PicassoHelper; @@ -73,19 +75,29 @@ public class ContentSettingsFragment extends BasePreferenceFragment { final Preference importDataPreference = requirePreference(R.string.import_data); importDataPreference.setOnPreferenceClickListener((Preference p) -> { - requestImportPathLauncher.launch( - StoredFileHelper.getPicker(requireContext(), - ZIP_MIME_TYPE, getImportExportDataUri())); + try { + requestImportPathLauncher.launch( + StoredFileHelper.getPicker(requireContext(), + ZIP_MIME_TYPE, getImportExportDataUri())); + } catch (final ActivityNotFoundException aex) { + Log.w(TAG, "Unable to launch file-picker", aex); + NoFileManagerHelper.showActivityNotFoundAlert(getContext()); + } return true; }); final Preference exportDataPreference = requirePreference(R.string.export_data); exportDataPreference.setOnPreferenceClickListener((final Preference p) -> { - requestExportPathLauncher.launch( - StoredFileHelper.getNewPicker(requireContext(), - "NewPipeData-" + exportDateFormat.format(new Date()) + ".zip", - ZIP_MIME_TYPE, getImportExportDataUri())); + try { + requestExportPathLauncher.launch( + StoredFileHelper.getNewPicker(requireContext(), + "NewPipeData-" + exportDateFormat.format(new Date()) + ".zip", + ZIP_MIME_TYPE, getImportExportDataUri())); + } catch (final ActivityNotFoundException aex) { + Log.w(TAG, "Unable to launch file-picker", aex); + NoFileManagerHelper.showActivityNotFoundAlert(getContext()); + } return true; }); diff --git a/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java index dfd77f049..b083cc71d 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java @@ -1,6 +1,7 @@ package org.schabi.newpipe.settings; import android.app.Activity; +import android.content.ActivityNotFoundException; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -21,6 +22,7 @@ import androidx.preference.SwitchPreferenceCompat; import com.nononsenseapps.filepicker.Utils; import org.schabi.newpipe.R; +import org.schabi.newpipe.streams.io.NoFileManagerHelper; import org.schabi.newpipe.streams.io.StoredDirectoryHelper; import org.schabi.newpipe.util.FilePickerActivityHelper; @@ -214,7 +216,12 @@ public class DownloadSettingsFragment extends BasePreferenceFragment { } private void launchDirectoryPicker(final ActivityResultLauncher launcher) { - launcher.launch(StoredDirectoryHelper.getPicker(ctx)); + try { + launcher.launch(StoredDirectoryHelper.getPicker(ctx)); + } catch (final ActivityNotFoundException aex) { + Log.w(TAG, "Unable to launch directory-picker", aex); + NoFileManagerHelper.showActivityNotFoundAlert(getContext()); + } } private void requestDownloadVideoPathResult(final ActivityResult result) { diff --git a/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerHelper.java b/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerHelper.java new file mode 100644 index 000000000..cd9119c08 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerHelper.java @@ -0,0 +1,31 @@ +package org.schabi.newpipe.streams.io; + +import android.content.Context; + +import androidx.appcompat.app.AlertDialog; + +import org.schabi.newpipe.R; + +/** + * Helper for when no file-manager/activity was found. + */ +public final class NoFileManagerHelper { + private NoFileManagerHelper() { + // No impl + } + + /** + * Shows an alert dialog when no file-manager is found. + * @param context Context + */ + public static void showActivityNotFoundAlert(final Context context) { + new AlertDialog.Builder(context) + .setTitle(R.string.no_app_to_open_intent) + .setMessage( + context.getString( + R.string.no_appropriate_file_manager_message, + context.getString(R.string.downloads_storage_use_saf_title))) + .setPositiveButton(R.string.ok, null) + .show(); + } +} diff --git a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java index 2cca3239b..5aa3d2a53 100644 --- a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java +++ b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java @@ -1,6 +1,7 @@ package us.shandian.giga.ui.fragment; import android.app.Activity; +import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -10,6 +11,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.os.IBinder; +import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; @@ -32,6 +34,7 @@ import com.nononsenseapps.filepicker.Utils; import org.schabi.newpipe.R; import org.schabi.newpipe.settings.NewPipeSettings; +import org.schabi.newpipe.streams.io.NoFileManagerHelper; import org.schabi.newpipe.streams.io.StoredFileHelper; import org.schabi.newpipe.util.FilePickerActivityHelper; @@ -46,6 +49,7 @@ import us.shandian.giga.ui.adapter.MissionAdapter; public class MissionsFragment extends Fragment { + private static final String TAG = "MissionsFragment"; private static final int SPAN_SIZE = 2; private SharedPreferences mPrefs; @@ -257,9 +261,14 @@ public class MissionsFragment extends Fragment { initialPath = Uri.parse(initialSavePath.getAbsolutePath()); } - requestDownloadSaveAsLauncher.launch( - StoredFileHelper.getNewPicker(mContext, mission.storage.getName(), - mission.storage.getType(), initialPath)); + try { + requestDownloadSaveAsLauncher.launch( + StoredFileHelper.getNewPicker(mContext, mission.storage.getName(), + mission.storage.getType(), initialPath)); + } catch (final ActivityNotFoundException aex) { + Log.w(TAG, "Unable to launch file-picker", aex); + NoFileManagerHelper.showActivityNotFoundAlert(getContext()); + } } @Override diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7c8fd98ab..112f1a94c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -671,6 +671,7 @@ Recent Chapters No app on your device can open this + No appropriate file-manager was found for this action.\nPlease install a file-manager or try to enable/disable \'%s\' in the download-settings. This content is not available in your country. This is a SoundCloud Go+ track, at least in your country, so it cannot be streamed or downloaded by NewPipe. This content is private, so it cannot be streamed or downloaded by NewPipe. From 68e7fcf8ee3870754487142f5281730674a450a7 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sat, 27 Nov 2021 23:39:17 +0100 Subject: [PATCH 02/49] Fixed typos --- .../main/java/org/schabi/newpipe/download/DownloadDialog.java | 4 ++-- .../schabi/newpipe/local/subscription/SubscriptionFragment.kt | 4 ++-- .../local/subscription/SubscriptionsImportFragment.java | 2 +- .../org/schabi/newpipe/settings/ContentSettingsFragment.java | 4 ++-- .../org/schabi/newpipe/settings/DownloadSettingsFragment.java | 2 +- .../java/us/shandian/giga/ui/fragment/MissionsFragment.java | 2 +- app/src/main/res/values/strings.xml | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java index 49b9024cd..0386b890d 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java @@ -692,7 +692,7 @@ public class DownloadDialog extends DialogFragment try { launcher.launch(StoredDirectoryHelper.getPicker(context)); } catch (final ActivityNotFoundException aex) { - Log.w(TAG, "Unable to launch directory-picker", aex); + Log.w(TAG, "Unable to launch directory picker", aex); NoFileManagerHelper.showActivityNotFoundAlert(getContext()); } } @@ -777,7 +777,7 @@ public class DownloadDialog extends DialogFragment requestDownloadSaveAsLauncher.launch(StoredFileHelper.getNewPicker(context, filenameTmp, mimeTmp, initialPath)); } catch (final ActivityNotFoundException aex) { - Log.w(TAG, "Unable to launch file-picker", aex); + Log.w(TAG, "Unable to launch file picker", aex); NoFileManagerHelper.showActivityNotFoundAlert(getContext()); } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index 8b170279d..264fb17e7 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -185,7 +185,7 @@ class SubscriptionFragment : BaseStateFragment() { try { requestImportLauncher.launch(StoredFileHelper.getPicker(activity, JSON_MIME_TYPE)) } catch (aex: ActivityNotFoundException) { - Log.w(TAG, "Unable to launch file-picker", aex) + Log.w(TAG, "Unable to launch file picker", aex) NoFileManagerHelper.showActivityNotFoundAlert(context) } } @@ -199,7 +199,7 @@ class SubscriptionFragment : BaseStateFragment() { StoredFileHelper.getNewPicker(activity, exportName, JSON_MIME_TYPE, null) ) } catch (aex: ActivityNotFoundException) { - Log.w(TAG, "Unable to launch file-picker", aex) + Log.w(TAG, "Unable to launch file picker", aex) NoFileManagerHelper.showActivityNotFoundAlert(context) } } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java index 10816922b..112300f1f 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java @@ -183,7 +183,7 @@ public class SubscriptionsImportFragment extends BaseFragment { // with different mime types and file extensions requestImportFileLauncher.launch(StoredFileHelper.getPicker(activity, "*/*")); } catch (final ActivityNotFoundException aex) { - Log.w(TAG, "Unable to launch file-picker", aex); + Log.w(TAG, "Unable to launch file picker", aex); NoFileManagerHelper.showActivityNotFoundAlert(getContext()); } } diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java index 3e72cf9a6..0a5e50be0 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java @@ -80,7 +80,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment { StoredFileHelper.getPicker(requireContext(), ZIP_MIME_TYPE, getImportExportDataUri())); } catch (final ActivityNotFoundException aex) { - Log.w(TAG, "Unable to launch file-picker", aex); + Log.w(TAG, "Unable to launch file picker", aex); NoFileManagerHelper.showActivityNotFoundAlert(getContext()); } return true; @@ -95,7 +95,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment { "NewPipeData-" + exportDateFormat.format(new Date()) + ".zip", ZIP_MIME_TYPE, getImportExportDataUri())); } catch (final ActivityNotFoundException aex) { - Log.w(TAG, "Unable to launch file-picker", aex); + Log.w(TAG, "Unable to launch file picker", aex); NoFileManagerHelper.showActivityNotFoundAlert(getContext()); } return true; diff --git a/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java index b083cc71d..45006bec4 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java @@ -219,7 +219,7 @@ public class DownloadSettingsFragment extends BasePreferenceFragment { try { launcher.launch(StoredDirectoryHelper.getPicker(ctx)); } catch (final ActivityNotFoundException aex) { - Log.w(TAG, "Unable to launch directory-picker", aex); + Log.w(TAG, "Unable to launch directory picker", aex); NoFileManagerHelper.showActivityNotFoundAlert(getContext()); } } diff --git a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java index 5aa3d2a53..e08cc4dec 100644 --- a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java +++ b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java @@ -266,7 +266,7 @@ public class MissionsFragment extends Fragment { StoredFileHelper.getNewPicker(mContext, mission.storage.getName(), mission.storage.getType(), initialPath)); } catch (final ActivityNotFoundException aex) { - Log.w(TAG, "Unable to launch file-picker", aex); + Log.w(TAG, "Unable to launch file picker", aex); NoFileManagerHelper.showActivityNotFoundAlert(getContext()); } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 112f1a94c..a8d308cd9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -671,7 +671,7 @@ Recent Chapters No app on your device can open this - No appropriate file-manager was found for this action.\nPlease install a file-manager or try to enable/disable \'%s\' in the download-settings. + No appropriate file manager was found for this action.\nPlease install a file manager or try to enable/disable \'%s\' in the download settings. This content is not available in your country. This is a SoundCloud Go+ track, at least in your country, so it cannot be streamed or downloaded by NewPipe. This content is private, so it cannot be streamed or downloaded by NewPipe. From b2323859e5c243856a989fd34a9bb2ed4c4adf27 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sun, 28 Nov 2021 14:07:45 +0100 Subject: [PATCH 03/49] Refactoring + deduplicated code --- .../newpipe/download/DownloadDialog.java | 28 ++++---- .../subscription/SubscriptionFragment.kt | 30 ++++----- .../SubscriptionsImportFragment.java | 20 +++--- .../settings/ContentSettingsFragment.java | 36 +++++----- .../settings/DownloadSettingsFragment.java | 15 ++--- .../streams/io/NoFileManagerHelper.java | 31 --------- .../streams/io/NoFileManagerSafeGuard.java | 67 +++++++++++++++++++ .../giga/ui/fragment/MissionsFragment.java | 19 +++--- 8 files changed, 134 insertions(+), 112 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerHelper.java create mode 100644 app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerSafeGuard.java diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java index 0386b890d..439efda20 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java @@ -1,7 +1,6 @@ package org.schabi.newpipe.download; import android.app.Activity; -import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; @@ -54,7 +53,7 @@ import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.SubtitlesStream; import org.schabi.newpipe.extractor.stream.VideoStream; import org.schabi.newpipe.settings.NewPipeSettings; -import org.schabi.newpipe.streams.io.NoFileManagerHelper; +import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard; import org.schabi.newpipe.streams.io.StoredDirectoryHelper; import org.schabi.newpipe.streams.io.StoredFileHelper; import org.schabi.newpipe.util.FilePickerActivityHelper; @@ -689,12 +688,12 @@ public class DownloadDialog extends DialogFragment } private void launchDirectoryPicker(final ActivityResultLauncher launcher) { - try { - launcher.launch(StoredDirectoryHelper.getPicker(context)); - } catch (final ActivityNotFoundException aex) { - Log.w(TAG, "Unable to launch directory picker", aex); - NoFileManagerHelper.showActivityNotFoundAlert(getContext()); - } + NoFileManagerSafeGuard.launchSafe( + launcher, + StoredDirectoryHelper.getPicker(context), + TAG, + context + ); } private void prepareSelectedDownload() { @@ -773,13 +772,12 @@ public class DownloadDialog extends DialogFragment initialPath = Uri.parse(initialSavePath.getAbsolutePath()); } - try { - requestDownloadSaveAsLauncher.launch(StoredFileHelper.getNewPicker(context, - filenameTmp, mimeTmp, initialPath)); - } catch (final ActivityNotFoundException aex) { - Log.w(TAG, "Unable to launch file picker", aex); - NoFileManagerHelper.showActivityNotFoundAlert(getContext()); - } + NoFileManagerSafeGuard.launchSafe( + requestDownloadSaveAsLauncher, + StoredFileHelper.getNewPicker(context, filenameTmp, mimeTmp, initialPath), + TAG, + context + ); return; } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index 264fb17e7..008228083 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -1,7 +1,6 @@ package org.schabi.newpipe.local.subscription import android.app.Activity -import android.content.ActivityNotFoundException import android.content.BroadcastReceiver import android.content.Context import android.content.DialogInterface @@ -9,7 +8,6 @@ import android.content.Intent import android.content.IntentFilter import android.os.Bundle import android.os.Parcelable -import android.util.Log import android.view.LayoutInflater import android.view.Menu import android.view.MenuInflater @@ -57,7 +55,7 @@ import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_MODE import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_VALUE import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.PREVIOUS_EXPORT_MODE -import org.schabi.newpipe.streams.io.NoFileManagerHelper +import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard import org.schabi.newpipe.streams.io.StoredFileHelper import org.schabi.newpipe.util.NavigationHelper import org.schabi.newpipe.util.OnClickGesture @@ -182,26 +180,24 @@ class SubscriptionFragment : BaseStateFragment() { } private fun onImportPreviousSelected() { - try { - requestImportLauncher.launch(StoredFileHelper.getPicker(activity, JSON_MIME_TYPE)) - } catch (aex: ActivityNotFoundException) { - Log.w(TAG, "Unable to launch file picker", aex) - NoFileManagerHelper.showActivityNotFoundAlert(context) - } + NoFileManagerSafeGuard.launchSafe( + requestImportLauncher, + StoredFileHelper.getPicker(activity, JSON_MIME_TYPE), + TAG, + requireContext() + ) } private fun onExportSelected() { val date = SimpleDateFormat("yyyyMMddHHmm", Locale.ENGLISH).format(Date()) val exportName = "newpipe_subscriptions_$date.json" - try { - requestExportLauncher.launch( - StoredFileHelper.getNewPicker(activity, exportName, JSON_MIME_TYPE, null) - ) - } catch (aex: ActivityNotFoundException) { - Log.w(TAG, "Unable to launch file picker", aex) - NoFileManagerHelper.showActivityNotFoundAlert(context) - } + NoFileManagerSafeGuard.launchSafe( + requestExportLauncher, + StoredFileHelper.getNewPicker(activity, exportName, JSON_MIME_TYPE, null), + TAG, + requireContext() + ) } private fun openReorderDialog() { diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java index 112300f1f..4fbcfbec1 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java @@ -1,12 +1,10 @@ package org.schabi.newpipe.local.subscription; import android.app.Activity; -import android.content.ActivityNotFoundException; import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; import android.text.util.Linkify; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -32,7 +30,7 @@ import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor; import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService; -import org.schabi.newpipe.streams.io.NoFileManagerHelper; +import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard; import org.schabi.newpipe.streams.io.StoredFileHelper; import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.ServiceHelper; @@ -178,14 +176,14 @@ public class SubscriptionsImportFragment extends BaseFragment { } public void onImportFile() { - try { - // leave */* mime type to support all services - // with different mime types and file extensions - requestImportFileLauncher.launch(StoredFileHelper.getPicker(activity, "*/*")); - } catch (final ActivityNotFoundException aex) { - Log.w(TAG, "Unable to launch file picker", aex); - NoFileManagerHelper.showActivityNotFoundAlert(getContext()); - } + NoFileManagerSafeGuard.launchSafe( + requestImportFileLauncher, + // leave */* mime type to support all services + // with different mime types and file extensions + StoredFileHelper.getPicker(activity, "*/*"), + TAG, + getContext() + ); } private void requestImportFileResult(final ActivityResult result) { diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java index 0a5e50be0..1511a23ae 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java @@ -1,7 +1,6 @@ package org.schabi.newpipe.settings; import android.app.Activity; -import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -26,7 +25,7 @@ import org.schabi.newpipe.error.ReCaptchaActivity; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.localization.ContentCountry; import org.schabi.newpipe.extractor.localization.Localization; -import org.schabi.newpipe.streams.io.NoFileManagerHelper; +import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard; import org.schabi.newpipe.streams.io.StoredFileHelper; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.PicassoHelper; @@ -75,29 +74,28 @@ public class ContentSettingsFragment extends BasePreferenceFragment { final Preference importDataPreference = requirePreference(R.string.import_data); importDataPreference.setOnPreferenceClickListener((Preference p) -> { - try { - requestImportPathLauncher.launch( - StoredFileHelper.getPicker(requireContext(), - ZIP_MIME_TYPE, getImportExportDataUri())); - } catch (final ActivityNotFoundException aex) { - Log.w(TAG, "Unable to launch file picker", aex); - NoFileManagerHelper.showActivityNotFoundAlert(getContext()); - } + NoFileManagerSafeGuard.launchSafe( + requestImportPathLauncher, + StoredFileHelper.getPicker(requireContext(), + ZIP_MIME_TYPE, getImportExportDataUri()), + TAG, + getContext() + ); + return true; }); final Preference exportDataPreference = requirePreference(R.string.export_data); exportDataPreference.setOnPreferenceClickListener((final Preference p) -> { + NoFileManagerSafeGuard.launchSafe( + requestExportPathLauncher, + StoredFileHelper.getNewPicker(requireContext(), + "NewPipeData-" + exportDateFormat.format(new Date()) + ".zip", + ZIP_MIME_TYPE, getImportExportDataUri()), + TAG, + getContext() + ); - try { - requestExportPathLauncher.launch( - StoredFileHelper.getNewPicker(requireContext(), - "NewPipeData-" + exportDateFormat.format(new Date()) + ".zip", - ZIP_MIME_TYPE, getImportExportDataUri())); - } catch (final ActivityNotFoundException aex) { - Log.w(TAG, "Unable to launch file picker", aex); - NoFileManagerHelper.showActivityNotFoundAlert(getContext()); - } return true; }); diff --git a/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java index 45006bec4..681aee409 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java @@ -1,7 +1,6 @@ package org.schabi.newpipe.settings; import android.app.Activity; -import android.content.ActivityNotFoundException; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -22,7 +21,7 @@ import androidx.preference.SwitchPreferenceCompat; import com.nononsenseapps.filepicker.Utils; import org.schabi.newpipe.R; -import org.schabi.newpipe.streams.io.NoFileManagerHelper; +import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard; import org.schabi.newpipe.streams.io.StoredDirectoryHelper; import org.schabi.newpipe.util.FilePickerActivityHelper; @@ -216,12 +215,12 @@ public class DownloadSettingsFragment extends BasePreferenceFragment { } private void launchDirectoryPicker(final ActivityResultLauncher launcher) { - try { - launcher.launch(StoredDirectoryHelper.getPicker(ctx)); - } catch (final ActivityNotFoundException aex) { - Log.w(TAG, "Unable to launch directory picker", aex); - NoFileManagerHelper.showActivityNotFoundAlert(getContext()); - } + NoFileManagerSafeGuard.launchSafe( + launcher, + StoredDirectoryHelper.getPicker(ctx), + TAG, + ctx + ); } private void requestDownloadVideoPathResult(final ActivityResult result) { diff --git a/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerHelper.java b/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerHelper.java deleted file mode 100644 index cd9119c08..000000000 --- a/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerHelper.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.schabi.newpipe.streams.io; - -import android.content.Context; - -import androidx.appcompat.app.AlertDialog; - -import org.schabi.newpipe.R; - -/** - * Helper for when no file-manager/activity was found. - */ -public final class NoFileManagerHelper { - private NoFileManagerHelper() { - // No impl - } - - /** - * Shows an alert dialog when no file-manager is found. - * @param context Context - */ - public static void showActivityNotFoundAlert(final Context context) { - new AlertDialog.Builder(context) - .setTitle(R.string.no_app_to_open_intent) - .setMessage( - context.getString( - R.string.no_appropriate_file_manager_message, - context.getString(R.string.downloads_storage_use_saf_title))) - .setPositiveButton(R.string.ok, null) - .show(); - } -} diff --git a/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerSafeGuard.java b/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerSafeGuard.java new file mode 100644 index 000000000..1d14d1669 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerSafeGuard.java @@ -0,0 +1,67 @@ +package org.schabi.newpipe.streams.io; + +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.util.Log; + +import androidx.activity.result.ActivityResultLauncher; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; + +import org.schabi.newpipe.R; + +/** + * Helper for when no file-manager/activity was found. + */ +public final class NoFileManagerSafeGuard { + private NoFileManagerSafeGuard() { + // No impl + } + + /** + * Shows an alert dialog when no file-manager is found. + * @param context Context + */ + private static void showActivityNotFoundAlert(@NonNull final Context context) { + if (context == null) { + throw new IllegalArgumentException( + "Unable to open no file manager alert dialog: Context is null"); + } + + new AlertDialog.Builder(context) + .setTitle(R.string.no_app_to_open_intent) + .setMessage( + context.getString( + R.string.no_appropriate_file_manager_message, + context.getString(R.string.downloads_storage_use_saf_title))) + .setPositiveButton(R.string.ok, null) + .show(); + } + + /** + * Launches the file manager safely. + * + * If no file manager is found (which is normally only the case when the user uninstalled + * the default file manager or the OS lacks one) an alert dialog shows up, asking the user + * to fix the situation. + * + * @param activityResultLauncher see {@link ActivityResultLauncher#launch(Object)} + * @param input see {@link ActivityResultLauncher#launch(Object)} + * @param tag Tag used for logging + * @param context Context + * @param see {@link ActivityResultLauncher#launch(Object)} + */ + public static void launchSafe( + final ActivityResultLauncher activityResultLauncher, + final I input, + @NonNull final String tag, + @NonNull final Context context + ) { + try { + activityResultLauncher.launch(input); + } catch (final ActivityNotFoundException aex) { + Log.w(tag, "Unable to launch file/directory picker", aex); + NoFileManagerSafeGuard.showActivityNotFoundAlert(context); + } + } +} diff --git a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java index e08cc4dec..dda2d6dee 100644 --- a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java +++ b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java @@ -1,7 +1,6 @@ package us.shandian.giga.ui.fragment; import android.app.Activity; -import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -11,7 +10,6 @@ import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.os.IBinder; -import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; @@ -34,7 +32,7 @@ import com.nononsenseapps.filepicker.Utils; import org.schabi.newpipe.R; import org.schabi.newpipe.settings.NewPipeSettings; -import org.schabi.newpipe.streams.io.NoFileManagerHelper; +import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard; import org.schabi.newpipe.streams.io.StoredFileHelper; import org.schabi.newpipe.util.FilePickerActivityHelper; @@ -261,14 +259,13 @@ public class MissionsFragment extends Fragment { initialPath = Uri.parse(initialSavePath.getAbsolutePath()); } - try { - requestDownloadSaveAsLauncher.launch( - StoredFileHelper.getNewPicker(mContext, mission.storage.getName(), - mission.storage.getType(), initialPath)); - } catch (final ActivityNotFoundException aex) { - Log.w(TAG, "Unable to launch file picker", aex); - NoFileManagerHelper.showActivityNotFoundAlert(getContext()); - } + NoFileManagerSafeGuard.launchSafe( + requestDownloadSaveAsLauncher, + StoredFileHelper.getNewPicker(mContext, mission.storage.getName(), + mission.storage.getType(), initialPath), + TAG, + mContext + ); } @Override From 17724a901c10535d99436d8bdb59bc4f9cc574cd Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Mon, 29 Nov 2021 21:03:59 +0100 Subject: [PATCH 04/49] Removed annotations due to wrong warnings --- .../schabi/newpipe/streams/io/NoFileManagerSafeGuard.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerSafeGuard.java b/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerSafeGuard.java index 1d14d1669..09ef16d47 100644 --- a/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerSafeGuard.java +++ b/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerSafeGuard.java @@ -22,7 +22,7 @@ public final class NoFileManagerSafeGuard { * Shows an alert dialog when no file-manager is found. * @param context Context */ - private static void showActivityNotFoundAlert(@NonNull final Context context) { + private static void showActivityNotFoundAlert(final Context context) { if (context == null) { throw new IllegalArgumentException( "Unable to open no file manager alert dialog: Context is null"); @@ -54,8 +54,8 @@ public final class NoFileManagerSafeGuard { public static void launchSafe( final ActivityResultLauncher activityResultLauncher, final I input, - @NonNull final String tag, - @NonNull final Context context + final String tag, + final Context context ) { try { activityResultLauncher.launch(input); From 744cfe5672b04eb54442884131b8818b49d42fca Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Mon, 29 Nov 2021 21:13:22 +0100 Subject: [PATCH 05/49] Removed unused import --- .../org/schabi/newpipe/streams/io/NoFileManagerSafeGuard.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerSafeGuard.java b/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerSafeGuard.java index 09ef16d47..c7dcb9975 100644 --- a/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerSafeGuard.java +++ b/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerSafeGuard.java @@ -5,7 +5,6 @@ import android.content.Context; import android.util.Log; import androidx.activity.result.ActivityResultLauncher; -import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import org.schabi.newpipe.R; From 7adebbe98905b1fc5abd16db4f54ce0fcac444c6 Mon Sep 17 00:00:00 2001 From: mhmdanas Date: Wed, 1 Dec 2021 20:24:53 +0300 Subject: [PATCH 06/49] Add FSFE-Tube PeerTube instance --- app/src/main/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cc631af7a..28cdbf020 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -338,6 +338,7 @@ + From 2c88e9d068802becaae32f6d8a5e0c1611f8bcf9 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Tue, 30 Nov 2021 22:00:10 +0100 Subject: [PATCH 07/49] Updated version to 0.21.14 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 4d4c2d9d1..cd1d32453 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,8 +17,8 @@ android { resValue "string", "app_name", "NewPipe" minSdkVersion 19 targetSdkVersion 29 - versionCode 979 - versionName "0.21.13" + versionCode 980 + versionName "0.21.14" multiDexEnabled true From 1d2642f1e333089d52876907536b30aaa1a88750 Mon Sep 17 00:00:00 2001 From: Stypox Date: Wed, 1 Dec 2021 09:10:59 +0100 Subject: [PATCH 08/49] Create ErrorUtil class with three ways to report errors Activity, snackbar and notification --- app/src/main/java/org/schabi/newpipe/App.java | 15 ++- .../schabi/newpipe/error/ErrorActivity.java | 73 +------------- .../org/schabi/newpipe/error/ErrorUtil.kt | 96 +++++++++++++++++++ app/src/main/res/values/strings.xml | 13 ++- 4 files changed, 119 insertions(+), 78 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt diff --git a/app/src/main/java/org/schabi/newpipe/App.java b/app/src/main/java/org/schabi/newpipe/App.java index 3785249b4..7ae2b42bd 100644 --- a/app/src/main/java/org/schabi/newpipe/App.java +++ b/app/src/main/java/org/schabi/newpipe/App.java @@ -227,28 +227,35 @@ public class App extends MultiDexApplication { // the main and update channels final NotificationChannelCompat mainChannel = new NotificationChannelCompat .Builder(getString(R.string.notification_channel_id), - NotificationManagerCompat.IMPORTANCE_LOW) + NotificationManagerCompat.IMPORTANCE_LOW) .setName(getString(R.string.notification_channel_name)) .setDescription(getString(R.string.notification_channel_description)) .build(); final NotificationChannelCompat appUpdateChannel = new NotificationChannelCompat .Builder(getString(R.string.app_update_notification_channel_id), - NotificationManagerCompat.IMPORTANCE_LOW) + NotificationManagerCompat.IMPORTANCE_LOW) .setName(getString(R.string.app_update_notification_channel_name)) .setDescription(getString(R.string.app_update_notification_channel_description)) .build(); final NotificationChannelCompat hashChannel = new NotificationChannelCompat .Builder(getString(R.string.hash_channel_id), - NotificationManagerCompat.IMPORTANCE_HIGH) + NotificationManagerCompat.IMPORTANCE_HIGH) .setName(getString(R.string.hash_channel_name)) .setDescription(getString(R.string.hash_channel_description)) .build(); + final NotificationChannelCompat errorReportChannel = new NotificationChannelCompat + .Builder(getString(R.string.error_report_channel_id), + NotificationManagerCompat.IMPORTANCE_LOW) + .setName(getString(R.string.error_report_channel_name)) + .setDescription(getString(R.string.error_report_channel_description)) + .build(); + final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); notificationManager.createNotificationChannelsCompat(Arrays.asList(mainChannel, - appUpdateChannel, hashChannel)); + appUpdateChannel, hashChannel, errorReportChannel)); } protected boolean isDisposedRxExceptionsReported() { diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java index db3a92d4f..257048e0e 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java @@ -1,9 +1,10 @@ package org.schabi.newpipe.error; +import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; + import android.app.Activity; import android.content.Context; import android.content.Intent; -import android.graphics.Color; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -11,15 +12,12 @@ import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; -import android.view.View; import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; -import androidx.fragment.app.Fragment; -import com.google.android.material.snackbar.Snackbar; import com.grack.nanojson.JsonWriter; import org.schabi.newpipe.BuildConfig; @@ -27,15 +25,13 @@ import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; import org.schabi.newpipe.databinding.ActivityErrorBinding; import org.schabi.newpipe.util.Localization; -import org.schabi.newpipe.util.external_communication.ShareUtils; import org.schabi.newpipe.util.ThemeHelper; +import org.schabi.newpipe.util.external_communication.ShareUtils; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Arrays; -import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; - /* * Created by Christian Schabesberger on 24.10.15. * @@ -56,7 +52,7 @@ import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; * along with NewPipe. If not, see . */ -public class ErrorActivity extends AppCompatActivity { +class ErrorActivity extends AppCompatActivity { // LOG TAGS public static final String TAG = ErrorActivity.class.toString(); // BUNDLE TAGS @@ -77,67 +73,6 @@ public class ErrorActivity extends AppCompatActivity { private ActivityErrorBinding activityErrorBinding; - /** - * Reports a new error by starting a new activity. - *
- * Ensure that the data within errorInfo is serializable otherwise - * an exception will be thrown!
- * {@link EnsureExceptionSerializable} might help. - * - * @param context - * @param errorInfo - */ - public static void reportError(final Context context, final ErrorInfo errorInfo) { - final Intent intent = new Intent(context, ErrorActivity.class); - intent.putExtra(ERROR_INFO, errorInfo); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent); - } - - public static void reportErrorInSnackbar(final Context context, final ErrorInfo errorInfo) { - final View rootView = context instanceof Activity - ? ((Activity) context).findViewById(android.R.id.content) : null; - reportErrorInSnackbar(context, rootView, errorInfo); - } - - public static void reportErrorInSnackbar(final Fragment fragment, final ErrorInfo errorInfo) { - View rootView = fragment.getView(); - if (rootView == null && fragment.getActivity() != null) { - rootView = fragment.getActivity().findViewById(android.R.id.content); - } - reportErrorInSnackbar(fragment.requireContext(), rootView, errorInfo); - } - - public static void reportUiErrorInSnackbar(final Context context, - final String request, - final Throwable throwable) { - reportErrorInSnackbar(context, new ErrorInfo(throwable, UserAction.UI_ERROR, request)); - } - - public static void reportUiErrorInSnackbar(final Fragment fragment, - final String request, - final Throwable throwable) { - reportErrorInSnackbar(fragment, new ErrorInfo(throwable, UserAction.UI_ERROR, request)); - } - - - //////////////////////////////////////////////////////////////////////// - // Utils - //////////////////////////////////////////////////////////////////////// - - private static void reportErrorInSnackbar(final Context context, - @Nullable final View rootView, - final ErrorInfo errorInfo) { - if (rootView != null) { - Snackbar.make(rootView, R.string.error_snackbar_message, Snackbar.LENGTH_LONG) - .setActionTextColor(Color.YELLOW) - .setAction(context.getString(R.string.error_snackbar_action).toUpperCase(), v -> - reportError(context, errorInfo)).show(); - } else { - reportError(context, errorInfo); - } - } - //////////////////////////////////////////////////////////////////////// // Activity lifecycle diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt new file mode 100644 index 000000000..66ddee9d8 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt @@ -0,0 +1,96 @@ +package org.schabi.newpipe.error + +import android.app.Activity +import android.app.NotificationManager +import android.content.Context +import android.content.Intent +import android.graphics.Color +import android.view.View +import androidx.core.app.NotificationCompat +import androidx.core.content.ContextCompat +import androidx.fragment.app.Fragment +import com.google.android.material.snackbar.Snackbar +import org.schabi.newpipe.R + +class ErrorUtil { + companion object { + private const val ERROR_REPORT_NOTIFICATION_ID = 5340681; + + /** + * Reports a new error by starting a new activity. + *

+ * Ensure that the data within errorInfo is serializable otherwise + * an exception will be thrown!

+ * [EnsureExceptionSerializable] might help. + * + * @param context + * @param errorInfo + */ + @JvmStatic + fun openActivity(context: Context, errorInfo: ErrorInfo) { + val intent = Intent(context, ErrorActivity::class.java) + intent.putExtra(ErrorActivity.ERROR_INFO, errorInfo) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + context.startActivity(intent) + } + + @JvmStatic + fun showSnackbar(context: Context, errorInfo: ErrorInfo) { + val rootView = if (context is Activity) context.findViewById(R.id.content) else null + showSnackbar(context, rootView, errorInfo) + } + + @JvmStatic + fun showSnackbar(fragment: Fragment, errorInfo: ErrorInfo) { + var rootView = fragment.view + if (rootView == null && fragment.activity != null) { + rootView = fragment.requireActivity().findViewById(R.id.content) + } + showSnackbar(fragment.requireContext(), rootView, errorInfo) + } + + @JvmStatic + fun showUiErrorSnackbar(context: Context, request: String, throwable: Throwable) { + showSnackbar(context, ErrorInfo(throwable, UserAction.UI_ERROR, request)) + } + + @JvmStatic + fun showUiErrorSnackbar(fragment: Fragment, request: String, throwable: Throwable) { + showSnackbar(fragment, ErrorInfo(throwable, UserAction.UI_ERROR, request)) + } + + @JvmStatic + fun createNotification(context: Context, errorInfo: ErrorInfo) { + val notificationManager = + ContextCompat.getSystemService(context, NotificationManager::class.java) + if (notificationManager == null) { + // this should never happen, but just in case open error activity + openActivity(context, errorInfo) + } + + val notificationBuilder: NotificationCompat.Builder = + NotificationCompat.Builder(context, + context.getString(R.string.error_report_channel_id)) + .setSmallIcon(R.drawable.ic_bug_report) + .setContentTitle(context.getString(R.string.error_report_title)) + .setContentText(context.getString(errorInfo.messageStringId)) + + notificationManager!!.notify(ERROR_REPORT_NOTIFICATION_ID, notificationBuilder.build()) + } + + + private fun showSnackbar(context: Context, rootView: View?, errorInfo: ErrorInfo) { + if (rootView == null) { + // fallback to showing a notification if no root view is available + createNotification(context, errorInfo) + + } else { + Snackbar.make(rootView, R.string.error_snackbar_message, Snackbar.LENGTH_LONG) + .setActionTextColor(Color.YELLOW) + .setAction(context.getString(R.string.error_snackbar_action).uppercase()) { + openActivity(context, errorInfo) + }.show() + } + } + } +} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a8bb4c788..2824c9efb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -182,14 +182,17 @@ Just Once File newpipe - NewPipe Notification - Notifications for NewPipe background and popup players + NewPipe notification + Notifications for NewPipe\'s player newpipeAppUpdate - App Update Notification - Notifications for new NewPipe version + App update notification + Notifications for new NewPipe versions newpipeHash - Video Hash Notification + Video hash notification Notifications for video hashing progress + newpipeErrorReport + Error report notification + Notifications to report errors [Unknown] Switch to Background Switch to Popup From 81f740d409054b3846d9246c41a19e2f076472fe Mon Sep 17 00:00:00 2001 From: Stypox Date: Wed, 1 Dec 2021 09:43:24 +0100 Subject: [PATCH 09/49] Replace ErrorActivity with ErrorUtil --- app/src/main/java/org/schabi/newpipe/App.java | 4 +-- .../schabi/newpipe/CheckForNewAppVersion.java | 8 +++--- .../java/org/schabi/newpipe/MainActivity.java | 14 +++++----- .../org/schabi/newpipe/RouterActivity.java | 4 +-- .../newpipe/download/DownloadDialog.java | 10 +++---- .../newpipe/error/AcraReportSender.java | 2 +- .../schabi/newpipe/error/ErrorActivity.java | 2 +- .../schabi/newpipe/error/ErrorPanelHelper.kt | 4 +-- .../org/schabi/newpipe/error/ErrorUtil.kt | 28 +++++++++---------- .../newpipe/fragments/BaseStateFragment.java | 10 +++---- .../newpipe/fragments/MainFragment.java | 13 +++------ .../fragments/detail/VideoDetailFragment.java | 9 +++--- .../fragments/list/BaseListFragment.java | 6 ++-- .../list/channel/ChannelFragment.java | 4 +-- .../list/playlist/PlaylistFragment.java | 4 +-- .../fragments/list/search/SearchFragment.java | 5 ++-- .../holder/CommentsMiniInfoItemHolder.java | 4 +-- .../SubscriptionsImportFragment.java | 4 +-- .../services/BaseImportExportService.java | 4 +-- .../playererror/PlayerErrorHandler.java | 4 +-- .../settings/ContentSettingsFragment.java | 6 ++-- .../settings/HistorySettingsFragment.java | 10 +++---- .../settings/SelectChannelFragment.java | 4 +-- .../newpipe/settings/SelectKioskFragment.java | 7 ++--- .../settings/SelectPlaylistFragment.java | 6 ++-- .../newpipe/settings/SettingMigrations.java | 4 +-- .../settings/tabs/ChooseTabsFragment.java | 4 +-- .../org/schabi/newpipe/settings/tabs/Tab.java | 4 +-- .../giga/ui/adapter/MissionAdapter.java | 4 +-- 29 files changed, 91 insertions(+), 101 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/App.java b/app/src/main/java/org/schabi/newpipe/App.java index 7ae2b42bd..6c02b6f57 100644 --- a/app/src/main/java/org/schabi/newpipe/App.java +++ b/app/src/main/java/org/schabi/newpipe/App.java @@ -16,8 +16,8 @@ import org.acra.ACRA; import org.acra.config.ACRAConfigurationException; import org.acra.config.CoreConfiguration; import org.acra.config.CoreConfigurationBuilder; -import org.schabi.newpipe.error.ErrorActivity; import org.schabi.newpipe.error.ErrorInfo; +import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.ReCaptchaActivity; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.extractor.NewPipe; @@ -217,7 +217,7 @@ public class App extends MultiDexApplication { ACRA.init(this, acraConfig); } catch (final ACRAConfigurationException exception) { exception.printStackTrace(); - ErrorActivity.reportError(this, new ErrorInfo(exception, + ErrorUtil.openActivity(this, new ErrorInfo(exception, UserAction.SOMETHING_ELSE, "Could not initialize ACRA crash report")); } } diff --git a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java index 9e43394ac..122660d64 100644 --- a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java +++ b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java @@ -21,8 +21,8 @@ import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParserException; -import org.schabi.newpipe.error.ErrorActivity; import org.schabi.newpipe.error.ErrorInfo; +import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.extractor.downloader.Response; import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; @@ -64,7 +64,7 @@ public final class CheckForNewAppVersion extends IntentService { signatures = PackageInfoCompat.getSignatures(application.getPackageManager(), application.getPackageName()); } catch (final PackageManager.NameNotFoundException e) { - ErrorActivity.reportError(application, new ErrorInfo(e, + ErrorUtil.createNotification(application, new ErrorInfo(e, UserAction.CHECK_FOR_NEW_APP_VERSION, "Could not find package info")); return ""; } @@ -79,7 +79,7 @@ public final class CheckForNewAppVersion extends IntentService { final CertificateFactory cf = CertificateFactory.getInstance("X509"); c = (X509Certificate) cf.generateCertificate(input); } catch (final CertificateException e) { - ErrorActivity.reportError(application, new ErrorInfo(e, + ErrorUtil.createNotification(application, new ErrorInfo(e, UserAction.CHECK_FOR_NEW_APP_VERSION, "Certificate error")); return ""; } @@ -89,7 +89,7 @@ public final class CheckForNewAppVersion extends IntentService { final byte[] publicKey = md.digest(c.getEncoded()); return byte2HexFormatted(publicKey); } catch (NoSuchAlgorithmException | CertificateEncodingException e) { - ErrorActivity.reportError(application, new ErrorInfo(e, + ErrorUtil.createNotification(application, new ErrorInfo(e, UserAction.CHECK_FOR_NEW_APP_VERSION, "Could not retrieve SHA1 key")); return ""; } diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 0a49e00e4..95663ea0a 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -63,7 +63,7 @@ import org.schabi.newpipe.databinding.DrawerHeaderBinding; import org.schabi.newpipe.databinding.DrawerLayoutBinding; import org.schabi.newpipe.databinding.InstanceSpinnerLayoutBinding; import org.schabi.newpipe.databinding.ToolbarLayoutBinding; -import org.schabi.newpipe.error.ErrorActivity; +import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ExtractionException; @@ -157,7 +157,7 @@ public class MainActivity extends AppCompatActivity { try { setupDrawer(); } catch (final Exception e) { - ErrorActivity.reportUiErrorInSnackbar(this, "Setting up drawer", e); + ErrorUtil.showUiErrorSnackbar(this, "Setting up drawer", e); } if (DeviceUtils.isTv(this)) { @@ -214,7 +214,7 @@ public class MainActivity extends AppCompatActivity { /** * Builds the drawer menu for the current service. * - * @throws ExtractionException + * @throws ExtractionException if the service didn't provide available kiosks */ private void addDrawerMenuForCurrentService() throws ExtractionException { //Tabs @@ -266,7 +266,7 @@ public class MainActivity extends AppCompatActivity { try { tabSelected(item); } catch (final Exception e) { - ErrorActivity.reportUiErrorInSnackbar(this, "Selecting main page tab", e); + ErrorUtil.showUiErrorSnackbar(this, "Selecting main page tab", e); } break; case R.id.menu_options_about_group: @@ -372,7 +372,7 @@ public class MainActivity extends AppCompatActivity { try { addDrawerMenuForCurrentService(); } catch (final Exception e) { - ErrorActivity.reportUiErrorInSnackbar(this, "Showing main page tabs", e); + ErrorUtil.showUiErrorSnackbar(this, "Showing main page tabs", e); } } } @@ -475,7 +475,7 @@ public class MainActivity extends AppCompatActivity { drawerHeaderBinding.drawerHeaderActionButton.setContentDescription( getString(R.string.drawer_header_description) + selectedServiceName); } catch (final Exception e) { - ErrorActivity.reportUiErrorInSnackbar(this, "Setting up service toggle", e); + ErrorUtil.showUiErrorSnackbar(this, "Setting up service toggle", e); } final SharedPreferences sharedPreferences @@ -785,7 +785,7 @@ public class MainActivity extends AppCompatActivity { NavigationHelper.gotoMainFragment(getSupportFragmentManager()); } } catch (final Exception e) { - ErrorActivity.reportUiErrorInSnackbar(this, "Handling intent", e); + ErrorUtil.showUiErrorSnackbar(this, "Handling intent", e); } } diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java index 4e96f3bb6..9d6e44f04 100644 --- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java +++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java @@ -37,8 +37,8 @@ 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; -import org.schabi.newpipe.error.ErrorActivity; import org.schabi.newpipe.error.ErrorInfo; +import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.ReCaptchaActivity; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.extractor.Info; @@ -231,7 +231,7 @@ public class RouterActivity extends AppCompatActivity { } else if (errorInfo.getThrowable() instanceof ContentNotSupportedException) { Toast.makeText(context, R.string.content_not_supported, Toast.LENGTH_LONG).show(); } else { - ErrorActivity.reportError(context, errorInfo); + ErrorUtil.createNotification(context, errorInfo); } if (context instanceof RouterActivity) { diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java index a7f5b938f..69e975a49 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java @@ -41,8 +41,8 @@ import com.nononsenseapps.filepicker.Utils; import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; import org.schabi.newpipe.databinding.DownloadDialogBinding; -import org.schabi.newpipe.error.ErrorActivity; import org.schabi.newpipe.error.ErrorInfo; +import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.extractor.MediaFormat; import org.schabi.newpipe.extractor.NewPipe; @@ -402,7 +402,7 @@ public class DownloadDialog extends DialogFragment == R.id.video_button) { setupVideoSpinner(); } - }, throwable -> ErrorActivity.reportErrorInSnackbar(context, + }, throwable -> ErrorUtil.showSnackbar(context, new ErrorInfo(throwable, UserAction.DOWNLOAD_OPEN_DIALOG, "Downloading video stream size", currentInfo.getServiceId())))); @@ -412,7 +412,7 @@ public class DownloadDialog extends DialogFragment == R.id.audio_button) { setupAudioSpinner(); } - }, throwable -> ErrorActivity.reportErrorInSnackbar(context, + }, throwable -> ErrorUtil.showSnackbar(context, new ErrorInfo(throwable, UserAction.DOWNLOAD_OPEN_DIALOG, "Downloading audio stream size", currentInfo.getServiceId())))); @@ -422,7 +422,7 @@ public class DownloadDialog extends DialogFragment == R.id.subtitle_button) { setupSubtitleSpinner(); } - }, throwable -> ErrorActivity.reportErrorInSnackbar(context, + }, throwable -> ErrorUtil.showSnackbar(context, new ErrorInfo(throwable, UserAction.DOWNLOAD_OPEN_DIALOG, "Downloading subtitle stream size", currentInfo.getServiceId())))); @@ -799,7 +799,7 @@ public class DownloadDialog extends DialogFragment mainStorage.getTag()); } } catch (final Exception e) { - ErrorActivity.reportErrorInSnackbar(this, + ErrorUtil.createNotification(requireContext(), new ErrorInfo(e, UserAction.DOWNLOAD_FAILED, "Getting storage")); return; } diff --git a/app/src/main/java/org/schabi/newpipe/error/AcraReportSender.java b/app/src/main/java/org/schabi/newpipe/error/AcraReportSender.java index 60d4908eb..bf9030509 100644 --- a/app/src/main/java/org/schabi/newpipe/error/AcraReportSender.java +++ b/app/src/main/java/org/schabi/newpipe/error/AcraReportSender.java @@ -33,7 +33,7 @@ public class AcraReportSender implements ReportSender { @Override public void send(@NonNull final Context context, @NonNull final CrashReportData report) { - ErrorActivity.reportError(context, new ErrorInfo( + ErrorUtil.openActivity(context, new ErrorInfo( new String[]{report.getString(ReportField.STACK_TRACE)}, UserAction.UI_ERROR, ErrorInfo.SERVICE_NONE, diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java index 257048e0e..07f736af3 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java @@ -52,7 +52,7 @@ import java.util.Arrays; * along with NewPipe. If not, see . */ -class ErrorActivity extends AppCompatActivity { +public class ErrorActivity extends AppCompatActivity { // LOG TAGS public static final String TAG = ErrorActivity.class.toString(); // BUNDLE TAGS diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt index 228c17f8c..692cb427a 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt @@ -118,7 +118,7 @@ class ErrorPanelHelper( showAndSetErrorButtonAction( R.string.error_snackbar_action ) { - ErrorActivity.reportError(context, errorInfo) + ErrorUtil.openActivity(context, errorInfo) } errorTextView.setText(getExceptionDescription(errorInfo.throwable)) @@ -178,7 +178,7 @@ class ErrorPanelHelper( val DEBUG: Boolean = MainActivity.DEBUG @StringRes - public fun getExceptionDescription(throwable: Throwable?): Int { + fun getExceptionDescription(throwable: Throwable?): Int { return when (throwable) { is AgeRestrictedContentException -> R.string.restricted_video_no_stream is GeographicRestrictionException -> R.string.georestricted_content diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt index 66ddee9d8..7e10d5608 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt @@ -14,7 +14,7 @@ import org.schabi.newpipe.R class ErrorUtil { companion object { - private const val ERROR_REPORT_NOTIFICATION_ID = 5340681; + private const val ERROR_REPORT_NOTIFICATION_ID = 5340681 /** * Reports a new error by starting a new activity. @@ -62,35 +62,35 @@ class ErrorUtil { @JvmStatic fun createNotification(context: Context, errorInfo: ErrorInfo) { val notificationManager = - ContextCompat.getSystemService(context, NotificationManager::class.java) + ContextCompat.getSystemService(context, NotificationManager::class.java) if (notificationManager == null) { // this should never happen, but just in case open error activity openActivity(context, errorInfo) } val notificationBuilder: NotificationCompat.Builder = - NotificationCompat.Builder(context, - context.getString(R.string.error_report_channel_id)) - .setSmallIcon(R.drawable.ic_bug_report) - .setContentTitle(context.getString(R.string.error_report_title)) - .setContentText(context.getString(errorInfo.messageStringId)) + NotificationCompat.Builder( + context, + context.getString(R.string.error_report_channel_id) + ) + .setSmallIcon(R.drawable.ic_bug_report) + .setContentTitle(context.getString(R.string.error_report_title)) + .setContentText(context.getString(errorInfo.messageStringId)) notificationManager!!.notify(ERROR_REPORT_NOTIFICATION_ID, notificationBuilder.build()) } - private fun showSnackbar(context: Context, rootView: View?, errorInfo: ErrorInfo) { if (rootView == null) { // fallback to showing a notification if no root view is available createNotification(context, errorInfo) - } else { Snackbar.make(rootView, R.string.error_snackbar_message, Snackbar.LENGTH_LONG) - .setActionTextColor(Color.YELLOW) - .setAction(context.getString(R.string.error_snackbar_action).uppercase()) { - openActivity(context, errorInfo) - }.show() + .setActionTextColor(Color.YELLOW) + .setAction(context.getString(R.string.error_snackbar_action).uppercase()) { + openActivity(context, errorInfo) + }.show() } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/schabi/newpipe/fragments/BaseStateFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/BaseStateFragment.java index db91755df..9b4bf8377 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/BaseStateFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/BaseStateFragment.java @@ -7,12 +7,13 @@ import android.widget.ProgressBar; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; import org.schabi.newpipe.BaseFragment; import org.schabi.newpipe.R; -import org.schabi.newpipe.error.ErrorActivity; import org.schabi.newpipe.error.ErrorInfo; import org.schabi.newpipe.error.ErrorPanelHelper; +import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.util.InfoCache; import java.util.concurrent.atomic.AtomicBoolean; @@ -198,9 +199,8 @@ public abstract class BaseStateFragment extends BaseFragment implements ViewC } /** - * Show a SnackBar and only call - * {@link ErrorActivity#reportErrorInSnackbar(androidx.fragment.app.Fragment, ErrorInfo)} - * IF we a find a valid view (otherwise the error screen appears). + * Directly calls {@link ErrorUtil#showSnackbar(Fragment, ErrorInfo)}, that shows a snackbar if + * a valid view can be found, otherwise creates an error report notification. * * @param errorInfo The error information */ @@ -208,6 +208,6 @@ public abstract class BaseStateFragment extends BaseFragment implements ViewC if (DEBUG) { Log.d(TAG, "showSnackBarError() called with: errorInfo = [" + errorInfo + "]"); } - ErrorActivity.reportErrorInSnackbar(this, errorInfo); + ErrorUtil.showSnackbar(this, errorInfo); } } diff --git a/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java index 7e0186e1c..de68269e9 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java @@ -23,7 +23,7 @@ import com.google.android.material.tabs.TabLayout; import org.schabi.newpipe.BaseFragment; import org.schabi.newpipe.R; import org.schabi.newpipe.databinding.FragmentMainBinding; -import org.schabi.newpipe.error.ErrorActivity; +import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.settings.tabs.Tab; import org.schabi.newpipe.settings.tabs.TabsManager; @@ -145,7 +145,7 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte NavigationHelper.openSearchFragment(getFM(), ServiceHelper.getSelectedServiceId(activity), ""); } catch (final Exception e) { - ErrorActivity.reportUiErrorInSnackbar(this, "Opening search fragment", e); + ErrorUtil.showUiErrorSnackbar(this, "Opening search fragment", e); } return true; } @@ -227,16 +227,11 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte public Fragment getItem(final int position) { final Tab tab = internalTabsList.get(position); - Throwable throwable = null; - Fragment fragment = null; + final Fragment fragment; try { fragment = tab.getFragment(context); } catch (final ExtractionException e) { - throwable = e; - } - - if (throwable != null) { - ErrorActivity.reportUiErrorInSnackbar(context, "Getting fragment item", throwable); + ErrorUtil.showUiErrorSnackbar(context, "Getting fragment item", e); return new BlankFragment(); } 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 8c6e01537..b5129f0b1 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 @@ -55,8 +55,8 @@ 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; import org.schabi.newpipe.error.ErrorInfo; +import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.ReCaptchaActivity; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.extractor.InfoItem; @@ -533,7 +533,7 @@ public final class VideoDetailFragment NavigationHelper.openChannelFragment(getFM(), currentInfo.getServiceId(), subChannelUrl, subChannelName); } catch (final Exception e) { - ErrorActivity.reportUiErrorInSnackbar(this, "Opening channel fragment", e); + ErrorUtil.showUiErrorSnackbar(this, "Opening channel fragment", e); } } @@ -1681,9 +1681,8 @@ public final class VideoDetailFragment downloadDialog.show(activity.getSupportFragmentManager(), "downloadDialog"); } catch (final Exception e) { - ErrorActivity.reportErrorInSnackbar(activity, - new ErrorInfo(e, UserAction.DOWNLOAD_OPEN_DIALOG, "Showing download dialog", - currentInfo)); + ErrorUtil.showSnackbar(activity, new ErrorInfo(e, UserAction.DOWNLOAD_OPEN_DIALOG, + "Showing download dialog", currentInfo)); } } 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 b9065c969..4319d42ee 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 @@ -21,7 +21,7 @@ import androidx.viewbinding.ViewBinding; import org.schabi.newpipe.R; import org.schabi.newpipe.databinding.PignateFooterBinding; -import org.schabi.newpipe.error.ErrorActivity; +import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.channel.ChannelInfoItem; import org.schabi.newpipe.extractor.comments.CommentsInfoItem; @@ -293,7 +293,7 @@ public abstract class BaseListFragment extends BaseStateFragment selectedItem.getUrl(), selectedItem.getName()); } catch (final Exception e) { - ErrorActivity.reportUiErrorInSnackbar( + ErrorUtil.showUiErrorSnackbar( BaseListFragment.this, "Opening channel fragment", e); } } @@ -309,7 +309,7 @@ public abstract class BaseListFragment extends BaseStateFragment selectedItem.getUrl(), selectedItem.getName()); } catch (final Exception e) { - ErrorActivity.reportUiErrorInSnackbar(BaseListFragment.this, + ErrorUtil.showUiErrorSnackbar(BaseListFragment.this, "Opening playlist fragment", e); } } 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 30e38a966..37954478d 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 @@ -26,8 +26,8 @@ import org.schabi.newpipe.database.subscription.SubscriptionEntity; import org.schabi.newpipe.databinding.ChannelHeaderBinding; import org.schabi.newpipe.databinding.FragmentChannelBinding; import org.schabi.newpipe.databinding.PlaylistControlBinding; -import org.schabi.newpipe.error.ErrorActivity; import org.schabi.newpipe.error.ErrorInfo; +import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.ListExtractor; @@ -407,7 +407,7 @@ public class ChannelFragment extends BaseListInfoFragment currentInfo.getParentChannelUrl(), currentInfo.getParentChannelName()); } catch (final Exception e) { - ErrorActivity.reportUiErrorInSnackbar(this, "Opening channel fragment", e); + ErrorUtil.showUiErrorSnackbar(this, "Opening channel fragment", e); } } else if (DEBUG) { Log.i(TAG, "Can't open parent channel because we got no channel URL"); 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 a8763af73..a61cec11d 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 @@ -24,8 +24,8 @@ import org.schabi.newpipe.R; import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity; import org.schabi.newpipe.databinding.PlaylistControlBinding; import org.schabi.newpipe.databinding.PlaylistHeaderBinding; -import org.schabi.newpipe.error.ErrorActivity; import org.schabi.newpipe.error.ErrorInfo; +import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.ListExtractor; @@ -310,7 +310,7 @@ public class PlaylistFragment extends BaseListInfoFragment { NavigationHelper.openChannelFragment(getFM(), result.getServiceId(), result.getUploaderUrl(), result.getUploaderName()); } catch (final Exception e) { - ErrorActivity.reportUiErrorInSnackbar(this, "Opening channel fragment", e); + ErrorUtil.showUiErrorSnackbar(this, "Opening channel fragment", e); } }); } 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 d4d73f74f..ba0bd50c6 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 @@ -38,8 +38,8 @@ import androidx.recyclerview.widget.RecyclerView; import org.schabi.newpipe.R; import org.schabi.newpipe.database.history.model.SearchHistoryEntry; import org.schabi.newpipe.databinding.FragmentSearchBinding; -import org.schabi.newpipe.error.ErrorActivity; import org.schabi.newpipe.error.ErrorInfo; +import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.ReCaptchaActivity; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.extractor.InfoItem; @@ -225,8 +225,7 @@ public class SearchFragment extends BaseListFragment Toast.makeText(context, R.string.watch_history_states_deleted, Toast.LENGTH_SHORT).show(), - throwable -> ErrorActivity.reportError(context, + throwable -> ErrorUtil.openActivity(context, new ErrorInfo(throwable, UserAction.DELETE_FROM_HISTORY, "Delete playback states"))); } @@ -76,7 +76,7 @@ public class HistorySettingsFragment extends BasePreferenceFragment { .subscribe( howManyDeleted -> Toast.makeText(context, R.string.watch_history_deleted, Toast.LENGTH_SHORT).show(), - throwable -> ErrorActivity.reportError(context, + throwable -> ErrorUtil.openActivity(context, new ErrorInfo(throwable, UserAction.DELETE_FROM_HISTORY, "Delete from history"))); } @@ -87,7 +87,7 @@ public class HistorySettingsFragment extends BasePreferenceFragment { .observeOn(AndroidSchedulers.mainThread()) .subscribe( howManyDeleted -> { }, - throwable -> ErrorActivity.reportError(context, + throwable -> ErrorUtil.openActivity(context, new ErrorInfo(throwable, UserAction.DELETE_FROM_HISTORY, "Clear orphaned records"))); } @@ -99,7 +99,7 @@ public class HistorySettingsFragment extends BasePreferenceFragment { .subscribe( howManyDeleted -> Toast.makeText(context, R.string.search_history_deleted, Toast.LENGTH_SHORT).show(), - throwable -> ErrorActivity.reportError(context, + throwable -> ErrorUtil.openActivity(context, new ErrorInfo(throwable, UserAction.DELETE_FROM_HISTORY, "Delete search history"))); } diff --git a/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java b/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java index a0105a11f..116807cbc 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java @@ -16,7 +16,7 @@ import androidx.recyclerview.widget.RecyclerView; import org.schabi.newpipe.R; import org.schabi.newpipe.database.subscription.SubscriptionEntity; -import org.schabi.newpipe.error.ErrorActivity; +import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.local.subscription.SubscriptionManager; import org.schabi.newpipe.util.PicassoHelper; import org.schabi.newpipe.util.ThemeHelper; @@ -153,7 +153,7 @@ public class SelectChannelFragment extends DialogFragment { @Override public void onError(@NonNull final Throwable exception) { - ErrorActivity.reportUiErrorInSnackbar(SelectChannelFragment.this, + ErrorUtil.showUiErrorSnackbar(SelectChannelFragment.this, "Loading subscription", exception); } diff --git a/app/src/main/java/org/schabi/newpipe/settings/SelectKioskFragment.java b/app/src/main/java/org/schabi/newpipe/settings/SelectKioskFragment.java index 9d8736076..a766ee074 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SelectKioskFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SelectKioskFragment.java @@ -16,7 +16,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import org.schabi.newpipe.R; -import org.schabi.newpipe.error.ErrorActivity; +import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.util.KioskTranslator; @@ -48,7 +48,6 @@ import java.util.Vector; */ public class SelectKioskFragment extends DialogFragment { - private RecyclerView recyclerView = null; private SelectKioskAdapter selectKioskAdapter = null; private OnSelectedListener onSelectedListener = null; @@ -76,12 +75,12 @@ public class SelectKioskFragment extends DialogFragment { public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { final View v = inflater.inflate(R.layout.select_kiosk_fragment, container, false); - recyclerView = v.findViewById(R.id.items_list); + final RecyclerView recyclerView = v.findViewById(R.id.items_list); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); try { selectKioskAdapter = new SelectKioskAdapter(); } catch (final Exception e) { - ErrorActivity.reportUiErrorInSnackbar(this, "Selecting kiosk", e); + ErrorUtil.showUiErrorSnackbar(this, "Selecting kiosk", e); } recyclerView.setAdapter(selectKioskAdapter); diff --git a/app/src/main/java/org/schabi/newpipe/settings/SelectPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/settings/SelectPlaylistFragment.java index f94e391ba..e8491d52c 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SelectPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SelectPlaylistFragment.java @@ -1,6 +1,5 @@ package org.schabi.newpipe.settings; -import android.app.Activity; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -21,8 +20,8 @@ import org.schabi.newpipe.database.LocalItem; import org.schabi.newpipe.database.playlist.PlaylistLocalItem; import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry; import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity; -import org.schabi.newpipe.error.ErrorActivity; import org.schabi.newpipe.error.ErrorInfo; +import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.local.playlist.LocalPlaylistManager; import org.schabi.newpipe.local.playlist.RemotePlaylistManager; @@ -105,8 +104,7 @@ public class SelectPlaylistFragment extends DialogFragment { } protected void onError(final Throwable e) { - final Activity activity = requireActivity(); - ErrorActivity.reportErrorInSnackbar(activity, new ErrorInfo(e, + ErrorUtil.showSnackbar(requireActivity(), new ErrorInfo(e, UserAction.UI_ERROR, "Loading playlists")); } diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java b/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java index b0b9567d8..8924ecbe1 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java @@ -8,8 +8,8 @@ import android.util.Log; import androidx.preference.PreferenceManager; import org.schabi.newpipe.R; -import org.schabi.newpipe.error.ErrorActivity; import org.schabi.newpipe.error.ErrorInfo; +import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.util.DeviceUtils; @@ -157,7 +157,7 @@ public final class SettingMigrations { } catch (final Exception e) { // save the version with the last successful migration and report the error sp.edit().putInt(lastPrefVersionKey, currentVersion).apply(); - ErrorActivity.reportError(context, new ErrorInfo( + ErrorUtil.openActivity(context, new ErrorInfo( e, UserAction.PREFERENCES_MIGRATION, "Migrating preferences from version " + lastPrefVersion + " to " diff --git a/app/src/main/java/org/schabi/newpipe/settings/tabs/ChooseTabsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/tabs/ChooseTabsFragment.java index c9eb42fca..95f7f50ba 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/tabs/ChooseTabsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/tabs/ChooseTabsFragment.java @@ -27,8 +27,8 @@ import androidx.recyclerview.widget.RecyclerView; import com.google.android.material.floatingactionbutton.FloatingActionButton; import org.schabi.newpipe.R; -import org.schabi.newpipe.error.ErrorActivity; import org.schabi.newpipe.error.ErrorInfo; +import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.settings.SelectChannelFragment; @@ -182,7 +182,7 @@ public class ChooseTabsFragment extends Fragment { final Tab.Type type = typeFrom(tabId); if (type == null) { - ErrorActivity.reportErrorInSnackbar(this, + ErrorUtil.showSnackbar(this, new ErrorInfo(new IllegalStateException("Tab id not found: " + tabId), UserAction.SOMETHING_ELSE, "Choosing tabs on settings")); return; diff --git a/app/src/main/java/org/schabi/newpipe/settings/tabs/Tab.java b/app/src/main/java/org/schabi/newpipe/settings/tabs/Tab.java index a148255b3..eac5ce311 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/tabs/Tab.java +++ b/app/src/main/java/org/schabi/newpipe/settings/tabs/Tab.java @@ -12,8 +12,8 @@ import com.grack.nanojson.JsonSink; import org.schabi.newpipe.R; import org.schabi.newpipe.database.LocalItem.LocalItemType; -import org.schabi.newpipe.error.ErrorActivity; import org.schabi.newpipe.error.ErrorInfo; +import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.StreamingService; @@ -506,7 +506,7 @@ public abstract class Tab { final StreamingService service = NewPipe.getService(kioskServiceId); kioskId = service.getKioskList().getDefaultKioskId(); } catch (final ExtractionException e) { - ErrorActivity.reportErrorInSnackbar(context, new ErrorInfo(e, + ErrorUtil.showSnackbar(context, new ErrorInfo(e, UserAction.REQUESTED_KIOSK, "Loading default kiosk for selected service")); } return kioskId; diff --git a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java index 057b9cb09..569c50001 100644 --- a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java +++ b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java @@ -39,8 +39,8 @@ import com.google.android.material.snackbar.Snackbar; import org.schabi.newpipe.BuildConfig; import org.schabi.newpipe.R; +import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.extractor.NewPipe; -import org.schabi.newpipe.error.ErrorActivity; import org.schabi.newpipe.error.ErrorInfo; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.util.Localization; @@ -581,7 +581,7 @@ public class MissionAdapter extends Adapter implements Handler.Callb service = ErrorInfo.SERVICE_NONE; } - ErrorActivity.reportError(mContext, + ErrorUtil.createNotification(mContext, new ErrorInfo(ErrorInfo.Companion.throwableToStringList(mission.errObject), action, service, request.toString(), reason, null)); } From 09d137f7407f3a0674d46b5c46c7283e1b6be9f9 Mon Sep 17 00:00:00 2001 From: Stypox Date: Wed, 1 Dec 2021 10:13:28 +0100 Subject: [PATCH 10/49] Add PendingIntent to ErrorUtil.createNotification --- .../org/schabi/newpipe/error/ErrorUtil.kt | 30 +++++++++++++++---- app/src/main/res/values/strings.xml | 1 + 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt index 7e10d5608..e62aad1df 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt @@ -2,9 +2,11 @@ package org.schabi.newpipe.error import android.app.Activity import android.app.NotificationManager +import android.app.PendingIntent import android.content.Context import android.content.Intent import android.graphics.Color +import android.os.Build import android.view.View import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat @@ -28,10 +30,7 @@ class ErrorUtil { */ @JvmStatic fun openActivity(context: Context, errorInfo: ErrorInfo) { - val intent = Intent(context, ErrorActivity::class.java) - intent.putExtra(ErrorActivity.ERROR_INFO, errorInfo) - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - context.startActivity(intent) + context.startActivity(getErrorActivityIntent(context, errorInfo)) } @JvmStatic @@ -68,18 +67,39 @@ class ErrorUtil { openActivity(context, errorInfo) } + var pendingIntentFlags = PendingIntent.FLAG_UPDATE_CURRENT + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + pendingIntentFlags = pendingIntentFlags or PendingIntent.FLAG_IMMUTABLE + } + val notificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder( context, context.getString(R.string.error_report_channel_id) ) .setSmallIcon(R.drawable.ic_bug_report) - .setContentTitle(context.getString(R.string.error_report_title)) + .setContentTitle(context.getString(R.string.error_report_notification_title)) .setContentText(context.getString(errorInfo.messageStringId)) + .setAutoCancel(true) + .setContentIntent( + PendingIntent.getActivity( + context, + 0, + getErrorActivityIntent(context, errorInfo), + pendingIntentFlags + ) + ) notificationManager!!.notify(ERROR_REPORT_NOTIFICATION_ID, notificationBuilder.build()) } + private fun getErrorActivityIntent(context: Context, errorInfo: ErrorInfo): Intent { + val intent = Intent(context, ErrorActivity::class.java) + intent.putExtra(ErrorActivity.ERROR_INFO, errorInfo) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + return intent + } + private fun showSnackbar(context: Context, rootView: View?, errorInfo: ErrorInfo) { if (rootView == null) { // fallback to showing a notification if no root view is available diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2824c9efb..f47322b79 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -246,6 +246,7 @@ Do you want to restore defaults? Give permission to display over other apps + NewPipe encountered an error, tap to report Sorry, that should not have happened. Guru Meditation. Report this error via e-mail From 397f93b079fb118c3f17650057f5ad13484b60d3 Mon Sep 17 00:00:00 2001 From: Stypox Date: Wed, 1 Dec 2021 10:28:35 +0100 Subject: [PATCH 11/49] Prevent exception from being serialized in ErrorInfo The wrong @Decorator was put in the wrong place to mark the throwable fieldd as transient, now this is fixed and the exception is not serialized. So if a non-serializable throwable is passed, that's not an issue, since it's not going to be serialized. The need for EnsureExceptionSerializable is also gone. --- .../newpipe/error/AcraReportSender.java | 3 +- .../error/EnsureExceptionSerializable.java | 103 ------------------ .../org/schabi/newpipe/error/ErrorInfo.kt | 24 ++-- .../org/schabi/newpipe/error/ErrorUtil.kt | 4 - .../SubscriptionsImportFragment.java | 3 +- .../playererror/PlayerErrorHandler.java | 3 +- .../giga/ui/adapter/MissionAdapter.java | 2 +- 7 files changed, 19 insertions(+), 123 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/error/EnsureExceptionSerializable.java diff --git a/app/src/main/java/org/schabi/newpipe/error/AcraReportSender.java b/app/src/main/java/org/schabi/newpipe/error/AcraReportSender.java index bf9030509..4d9966364 100644 --- a/app/src/main/java/org/schabi/newpipe/error/AcraReportSender.java +++ b/app/src/main/java/org/schabi/newpipe/error/AcraReportSender.java @@ -38,7 +38,6 @@ public class AcraReportSender implements ReportSender { UserAction.UI_ERROR, ErrorInfo.SERVICE_NONE, "ACRA report", - R.string.app_ui_crash, - null)); + R.string.app_ui_crash)); } } diff --git a/app/src/main/java/org/schabi/newpipe/error/EnsureExceptionSerializable.java b/app/src/main/java/org/schabi/newpipe/error/EnsureExceptionSerializable.java deleted file mode 100644 index db94de5e5..000000000 --- a/app/src/main/java/org/schabi/newpipe/error/EnsureExceptionSerializable.java +++ /dev/null @@ -1,103 +0,0 @@ -package org.schabi.newpipe.error; - -import android.util.Log; - -import androidx.annotation.NonNull; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectOutputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Ensures that a Exception is serializable. - * This is - */ -public final class EnsureExceptionSerializable { - private static final String TAG = "EnsureExSerializable"; - - private EnsureExceptionSerializable() { - // No instance - } - - /** - * Ensures that an exception is serializable. - *
- * If that is not the case a {@link WorkaroundNotSerializableException} is created. - * - * @param exception - * @return if an exception is not serializable a new {@link WorkaroundNotSerializableException} - * otherwise the exception from the parameter - */ - public static Exception ensureSerializable(@NonNull final Exception exception) { - return checkIfSerializable(exception) - ? exception - : WorkaroundNotSerializableException.create(exception); - } - - public static boolean checkIfSerializable(@NonNull final Exception exception) { - try { - // Check by creating a new ObjectOutputStream which does the serialization - try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(bos) - ) { - oos.writeObject(exception); - oos.flush(); - - bos.toByteArray(); - } - - return true; - } catch (final IOException ex) { - Log.d(TAG, "Exception is not serializable", ex); - return false; - } - } - - public static class WorkaroundNotSerializableException extends Exception { - protected WorkaroundNotSerializableException( - final Throwable notSerializableException, - final Throwable cause) { - super(notSerializableException.toString(), cause); - setStackTrace(notSerializableException.getStackTrace()); - } - - protected WorkaroundNotSerializableException(final Throwable notSerializableException) { - super(notSerializableException.toString()); - setStackTrace(notSerializableException.getStackTrace()); - } - - public static WorkaroundNotSerializableException create( - @NonNull final Exception notSerializableException - ) { - // Build a list of the exception + all causes - final List throwableList = new ArrayList<>(); - - int pos = 0; - Throwable throwableToProcess = notSerializableException; - - while (throwableToProcess != null) { - throwableList.add(throwableToProcess); - - pos++; - throwableToProcess = throwableToProcess.getCause(); - } - - // Reverse list so that it starts with the last one - Collections.reverse(throwableList); - - // Build exception stack - WorkaroundNotSerializableException cause = null; - for (final Throwable t : throwableList) { - cause = cause == null - ? new WorkaroundNotSerializableException(t) - : new WorkaroundNotSerializableException(t, cause); - } - - return cause; - } - - } -} diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt index 6581b5752..ba1204e12 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt @@ -2,6 +2,7 @@ package org.schabi.newpipe.error import android.os.Parcelable import androidx.annotation.StringRes +import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize import org.schabi.newpipe.R import org.schabi.newpipe.extractor.Info @@ -21,11 +22,14 @@ class ErrorInfo( val userAction: UserAction, val serviceName: String, val request: String, - val messageStringId: Int, - @Transient // no need to store throwable, all data for report is in other variables - var throwable: Throwable? = null + val messageStringId: Int ) : Parcelable { + // no need to store throwable, all data for report is in other variables + // also, the throwable might not be serializable, see TeamNewPipe/NewPipe#7302 + @IgnoredOnParcel + var throwable: Throwable? = null + private constructor( throwable: Throwable, userAction: UserAction, @@ -36,9 +40,10 @@ class ErrorInfo( userAction, serviceName, request, - getMessageStringId(throwable, userAction), - throwable - ) + getMessageStringId(throwable, userAction) + ) { + this.throwable = throwable + } private constructor( throwable: List, @@ -50,9 +55,10 @@ class ErrorInfo( userAction, serviceName, request, - getMessageStringId(throwable.firstOrNull(), userAction), - throwable.firstOrNull() - ) + getMessageStringId(throwable.firstOrNull(), userAction) + ) { + this.throwable = throwable.firstOrNull() + } // constructors with single throwable constructor(throwable: Throwable, userAction: UserAction, request: String) : diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt index e62aad1df..5fb8bff92 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt @@ -20,10 +20,6 @@ class ErrorUtil { /** * Reports a new error by starting a new activity. - *

- * Ensure that the data within errorInfo is serializable otherwise - * an exception will be thrown!

- * [EnsureExceptionSerializable] might help. * * @param context * @param errorInfo diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java index 8164c656d..8dbd7b2c5 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java @@ -90,8 +90,7 @@ public class SubscriptionsImportFragment extends BaseFragment { new ErrorInfo(new String[]{}, UserAction.SUBSCRIPTION_IMPORT_EXPORT, NewPipe.getNameOfService(currentServiceId), "Service does not support importing subscriptions", - R.string.general_error, - null)); + R.string.general_error)); activity.finish(); } } diff --git a/app/src/main/java/org/schabi/newpipe/player/playererror/PlayerErrorHandler.java b/app/src/main/java/org/schabi/newpipe/player/playererror/PlayerErrorHandler.java index d77073e00..ca9b4e7df 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playererror/PlayerErrorHandler.java +++ b/app/src/main/java/org/schabi/newpipe/player/playererror/PlayerErrorHandler.java @@ -12,7 +12,6 @@ import androidx.preference.PreferenceManager; import com.google.android.exoplayer2.ExoPlaybackException; import org.schabi.newpipe.R; -import org.schabi.newpipe.error.EnsureExceptionSerializable; import org.schabi.newpipe.error.ErrorInfo; import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.UserAction; @@ -70,7 +69,7 @@ public class PlayerErrorHandler { ErrorUtil.createNotification( context, new ErrorInfo( - EnsureExceptionSerializable.ensureSerializable(exception), + exception, UserAction.PLAY_STREAM, "Player error[type=" + exception.type + "] occurred while playing: " + info.getUrl(), diff --git a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java index 569c50001..39bdefbe0 100644 --- a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java +++ b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java @@ -583,7 +583,7 @@ public class MissionAdapter extends Adapter implements Handler.Callb ErrorUtil.createNotification(mContext, new ErrorInfo(ErrorInfo.Companion.throwableToStringList(mission.errObject), action, - service, request.toString(), reason, null)); + service, request.toString(), reason)); } public void clearFinishedDownloads(boolean delete) { From c8e2ab4c83f93a3ce3561a30f53f584af40dce2e Mon Sep 17 00:00:00 2001 From: Stypox Date: Thu, 2 Dec 2021 14:24:45 +0100 Subject: [PATCH 12/49] Remove PlayerErrorHandler and correctly set ErrorInfo msg --- .../org/schabi/newpipe/error/ErrorInfo.kt | 8 ++ .../org/schabi/newpipe/player/Player.java | 33 ++++--- .../playererror/PlayerErrorHandler.java | 88 ------------------- app/src/main/res/values/settings_keys.xml | 2 - app/src/main/res/values/strings.xml | 2 - app/src/main/res/xml/debug_settings.xml | 8 -- 6 files changed, 24 insertions(+), 117 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/player/playererror/PlayerErrorHandler.java diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt index ba1204e12..b2ba912ec 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt @@ -2,6 +2,7 @@ package org.schabi.newpipe.error import android.os.Parcelable import androidx.annotation.StringRes +import com.google.android.exoplayer2.ExoPlaybackException import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize import org.schabi.newpipe.R @@ -108,6 +109,13 @@ class ErrorInfo( throwable is ContentNotSupportedException -> R.string.content_not_supported throwable is DeobfuscateException -> R.string.youtube_signature_deobfuscation_error throwable is ExtractionException -> R.string.parsing_error + throwable is ExoPlaybackException -> { + when (throwable.type) { + ExoPlaybackException.TYPE_SOURCE -> R.string.player_stream_failure + ExoPlaybackException.TYPE_UNEXPECTED -> R.string.player_recoverable_failure + else -> R.string.player_unrecoverable_failure + } + } action == UserAction.UI_ERROR -> R.string.app_ui_crash action == UserAction.REQUESTED_COMMENTS -> R.string.error_unable_to_load_comments action == UserAction.SUBSCRIPTION_CHANGE -> R.string.subscription_change_failed 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 2d8c1a830..ee09cb866 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -141,6 +141,9 @@ import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; import org.schabi.newpipe.databinding.PlayerBinding; import org.schabi.newpipe.databinding.PlayerPopupCloseOverlayBinding; +import org.schabi.newpipe.error.ErrorInfo; +import org.schabi.newpipe.error.ErrorUtil; +import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.extractor.MediaFormat; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamSegment; @@ -165,7 +168,6 @@ import org.schabi.newpipe.player.playback.MediaSourceManager; import org.schabi.newpipe.player.playback.PlaybackListener; import org.schabi.newpipe.player.playback.PlayerMediaSession; import org.schabi.newpipe.player.playback.SurfaceHolderCallback; -import org.schabi.newpipe.player.playererror.PlayerErrorHandler; import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.player.playqueue.PlayQueueAdapter; import org.schabi.newpipe.player.playqueue.PlayQueueItem; @@ -268,8 +270,6 @@ public final class Player implements @Nullable private MediaSourceTag currentMetadata; @Nullable private Bitmap currentThumbnail; - @NonNull private PlayerErrorHandler playerErrorHandler; - /*////////////////////////////////////////////////////////////////////////// // Player //////////////////////////////////////////////////////////////////////////*/ @@ -413,8 +413,6 @@ public final class Player implements videoResolver = new VideoPlaybackResolver(context, dataSource, getQualityResolver()); audioResolver = new AudioPlaybackResolver(context, dataSource); - playerErrorHandler = new PlayerErrorHandler(context); - windowManager = ContextCompat.getSystemService(context, WindowManager.class); } @@ -2518,29 +2516,30 @@ public final class Player implements saveStreamProgressState(); + // create error notification + final ErrorInfo errorInfo; + if (currentMetadata == null) { + errorInfo = new ErrorInfo(error, UserAction.PLAY_STREAM, + "Player error[type=" + error.type + "] occurred, currentMetadata is null"); + } else { + errorInfo = new ErrorInfo(error, UserAction.PLAY_STREAM, + "Player error[type=" + error.type + "] occurred while playing " + + currentMetadata.getMetadata().getUrl(), + currentMetadata.getMetadata()); + } + ErrorUtil.createNotification(context, errorInfo); + switch (error.type) { case ExoPlaybackException.TYPE_SOURCE: processSourceError(error.getSourceException()); - playerErrorHandler.showPlayerError( - error, - currentMetadata.getMetadata(), - R.string.player_stream_failure); break; case ExoPlaybackException.TYPE_UNEXPECTED: - playerErrorHandler.showPlayerError( - error, - currentMetadata.getMetadata(), - R.string.player_recoverable_failure); setRecovery(); reloadPlayQueueManager(); break; case ExoPlaybackException.TYPE_REMOTE: case ExoPlaybackException.TYPE_RENDERER: default: - playerErrorHandler.showPlayerError( - error, - currentMetadata.getMetadata(), - R.string.player_unrecoverable_failure); onPlaybackShutdown(); break; } diff --git a/app/src/main/java/org/schabi/newpipe/player/playererror/PlayerErrorHandler.java b/app/src/main/java/org/schabi/newpipe/player/playererror/PlayerErrorHandler.java deleted file mode 100644 index ca9b4e7df..000000000 --- a/app/src/main/java/org/schabi/newpipe/player/playererror/PlayerErrorHandler.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.schabi.newpipe.player.playererror; - -import android.content.Context; -import android.util.Log; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.StringRes; -import androidx.preference.PreferenceManager; - -import com.google.android.exoplayer2.ExoPlaybackException; - -import org.schabi.newpipe.R; -import org.schabi.newpipe.error.ErrorInfo; -import org.schabi.newpipe.error.ErrorUtil; -import org.schabi.newpipe.error.UserAction; -import org.schabi.newpipe.extractor.Info; - -/** - * Handles (exoplayer)errors that occur in the player. - */ -public class PlayerErrorHandler { - // This has to be <= 23 chars on devices running Android 7 or lower (API <= 25) - // or it fails with an IllegalArgumentException - // https://stackoverflow.com/a/54744028 - private static final String TAG = "PlayerErrorHandler"; - - @Nullable - private Toast errorToast; - - @NonNull - private final Context context; - - public PlayerErrorHandler(@NonNull final Context context) { - this.context = context; - } - - public void showPlayerError( - @NonNull final ExoPlaybackException exception, - @NonNull final Info info, - @StringRes final int textResId - ) { - // Hide existing toast message - if (errorToast != null) { - Log.d(TAG, "Trying to cancel previous player error error toast"); - errorToast.cancel(); - errorToast = null; - } - - if (shouldReportError()) { - try { - reportError(exception, info); - // When a report pops up we need no toast - return; - } catch (final Exception ex) { - Log.w(TAG, "Unable to report error:", ex); - // This will show the toast as fallback - } - } - - Log.d(TAG, "Showing player error toast"); - errorToast = Toast.makeText(context, textResId, Toast.LENGTH_SHORT); - errorToast.show(); - } - - private void reportError(@NonNull final ExoPlaybackException exception, - @NonNull final Info info) { - ErrorUtil.createNotification( - context, - new ErrorInfo( - exception, - UserAction.PLAY_STREAM, - "Player error[type=" + exception.type + "] occurred while playing: " - + info.getUrl(), - info - ) - ); - } - - private boolean shouldReportError() { - return PreferenceManager - .getDefaultSharedPreferences(context) - .getBoolean( - context.getString(R.string.report_player_errors_key), - false); - } -} diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index e2b797576..b88b2d064 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -89,8 +89,6 @@ @string/never - report_player_errors_key - seekbar_preview_thumbnail_key seekbar_preview_thumbnail_high_quality seekbar_preview_thumbnail_low_quality diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f47322b79..3319d5fb9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -53,8 +53,6 @@ Show \"Play with Kodi\" option Display an option to play a video via Kodi media center Crash the player - Report player errors - Reports player errors in full detail instead of showing a short-lived toast message (useful for diagnosing problems) Scale thumbnail to 1:1 aspect ratio Scale the video thumbnail shown in the notification from 16:9 to 1:1 aspect ratio (may introduce distortions) First action button diff --git a/app/src/main/res/xml/debug_settings.xml b/app/src/main/res/xml/debug_settings.xml index 5e2cc28ed..df1559c37 100644 --- a/app/src/main/res/xml/debug_settings.xml +++ b/app/src/main/res/xml/debug_settings.xml @@ -49,14 +49,6 @@ android:title="@string/show_image_indicators_title" app:iconSpaceReserved="false" /> - - Date: Thu, 2 Dec 2021 14:56:45 +0100 Subject: [PATCH 13/49] Add debug prefs to show error snackbar/notification --- .../settings/DebugSettingsFragment.java | 21 ++++++++++++++++ app/src/main/res/values/settings_keys.xml | 4 +++- app/src/main/res/values/strings.xml | 4 +++- app/src/main/res/xml/debug_settings.xml | 24 +++++++++++++------ 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsFragment.java b/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsFragment.java index 55b2c7708..f48be553f 100644 --- a/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsFragment.java +++ b/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsFragment.java @@ -5,6 +5,9 @@ import android.os.Bundle; import androidx.preference.Preference; import org.schabi.newpipe.R; +import org.schabi.newpipe.error.ErrorInfo; +import org.schabi.newpipe.error.ErrorUtil; +import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.util.PicassoHelper; import leakcanary.LeakCanary; @@ -20,10 +23,16 @@ public class DebugSettingsFragment extends BasePreferenceFragment { = findPreference(getString(R.string.show_image_indicators_key)); final Preference crashTheAppPreference = findPreference(getString(R.string.crash_the_app_key)); + final Preference showErrorSnackbarPreference + = findPreference(getString(R.string.show_error_snackbar_key)); + final Preference createErrorNotificationPreference + = findPreference(getString(R.string.create_error_notification_key)); assert showMemoryLeaksPreference != null; assert showImageIndicatorsPreference != null; assert crashTheAppPreference != null; + assert showErrorSnackbarPreference != null; + assert createErrorNotificationPreference != null; showMemoryLeaksPreference.setOnPreferenceClickListener(preference -> { startActivity(LeakCanary.INSTANCE.newLeakDisplayActivityIntent()); @@ -38,5 +47,17 @@ public class DebugSettingsFragment extends BasePreferenceFragment { crashTheAppPreference.setOnPreferenceClickListener(preference -> { throw new RuntimeException(); }); + + showErrorSnackbarPreference.setOnPreferenceClickListener(preference -> { + ErrorUtil.showUiErrorSnackbar(DebugSettingsFragment.this, + "Dummy", new RuntimeException("Dummy")); + return true; + }); + + createErrorNotificationPreference.setOnPreferenceClickListener(preference -> { + ErrorUtil.createNotification(requireContext(), + new ErrorInfo(new RuntimeException("Dummy"), UserAction.UI_ERROR, "Dummy")); + return true; + }); } } diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index b88b2d064..b6f76fce2 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -186,9 +186,11 @@ allow_disposed_exceptions_key show_original_time_ago_key disable_media_tunneling_key - crash_the_app_key show_image_indicators_key show_crash_the_player_key + crash_the_app_key + show_error_snackbar_key + create_error_notification_key theme diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3319d5fb9..4acd04d27 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -477,9 +477,11 @@ Disable media tunneling if you experience a black screen or stuttering on video playback Show image indicators Show Picasso colored ribbons on top of images indicating their source: red for network, blue for disk and green for memory - Crash the app Show \"crash the player\" Shows a crash option when using the player + Crash the app + Show an error snackbar + Create an error notification Import Import from diff --git a/app/src/main/res/xml/debug_settings.xml b/app/src/main/res/xml/debug_settings.xml index df1559c37..0052125a2 100644 --- a/app/src/main/res/xml/debug_settings.xml +++ b/app/src/main/res/xml/debug_settings.xml @@ -49,18 +49,28 @@ android:title="@string/show_image_indicators_title" app:iconSpaceReserved="false" /> + + - + + From 950956ebf22ef72c54c73cf30941bb1a87e6df3b Mon Sep 17 00:00:00 2001 From: Stypox Date: Sat, 4 Dec 2021 10:45:15 +0100 Subject: [PATCH 14/49] Also show a toast on error notification since the notification is silent, also show a toast, otherwise the user is confused --- app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt | 5 +++++ app/src/main/res/values/strings.xml | 1 + 2 files changed, 6 insertions(+) diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt index 5fb8bff92..b766d91c6 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt @@ -8,6 +8,7 @@ import android.content.Intent import android.graphics.Color import android.os.Build import android.view.View +import android.widget.Toast import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment @@ -87,6 +88,10 @@ class ErrorUtil { ) notificationManager!!.notify(ERROR_REPORT_NOTIFICATION_ID, notificationBuilder.build()) + + // since the notification is silent, also show a toast, otherwise the user is confused + Toast.makeText(context, R.string.error_report_notification_toast, Toast.LENGTH_SHORT) + .show() } private fun getErrorActivityIntent(context: Context, errorInfo: ErrorInfo): Intent { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4acd04d27..cc518e2bb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -245,6 +245,7 @@ Give permission to display over other apps NewPipe encountered an error, tap to report + An error occurred, see the notification Sorry, that should not have happened. Guru Meditation. Report this error via e-mail From 84d87a2e608978d82ab4f06393fb94839d0342b9 Mon Sep 17 00:00:00 2001 From: TacoTheDank Date: Sat, 4 Dec 2021 21:16:37 -0500 Subject: [PATCH 15/49] Move plugins to the DSL block --- app/build.gradle | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 4d4c2d9d1..94c623e13 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,13 +1,12 @@ plugins { + id "com.android.application" + id "kotlin-android" + id "kotlin-kapt" + id "kotlin-parcelize" + id "checkstyle" id "org.sonarqube" version "3.1.1" } -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-parcelize' -apply plugin: 'kotlin-kapt' -apply plugin: 'checkstyle' - android { compileSdkVersion 30 buildToolsVersion '30.0.3' @@ -80,13 +79,13 @@ android { // Flag to enable support for the new language APIs coreLibraryDesugaringEnabled true - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 encoding 'utf-8' } kotlinOptions { - jvmTarget = JavaVersion.VERSION_1_8 + jvmTarget = JavaVersion.VERSION_11 } sourceSets { From dbfa4e554b85064e6c29b78df6512dec397912f6 Mon Sep 17 00:00:00 2001 From: TacoTheDank Date: Sat, 4 Dec 2021 21:22:15 -0500 Subject: [PATCH 16/49] Update Sonarqube to 3.3 --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 94c623e13..25ad5c43c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,7 +4,7 @@ plugins { id "kotlin-kapt" id "kotlin-parcelize" id "checkstyle" - id "org.sonarqube" version "3.1.1" + id "org.sonarqube" version "3.3" } android { From 75db002369aa9c709806e4c39c01629fa1436e81 Mon Sep 17 00:00:00 2001 From: TacoTheDank Date: Sat, 4 Dec 2021 21:22:29 -0500 Subject: [PATCH 17/49] Update ktlint to 0.43.2 --- app/build.gradle | 2 +- .../schabi/newpipe/local/feed/service/FeedLoadService.kt | 8 -------- .../schabi/newpipe/settings/ContentSettingsManagerTest.kt | 2 +- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 25ad5c43c..ba92d97c7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -192,7 +192,7 @@ dependencies { /** Checkstyle **/ checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}" - ktlint 'com.pinterest:ktlint:0.40.0' + ktlint 'com.pinterest:ktlint:0.43.2' /** Kotlin **/ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlin_version}" diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadService.kt b/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadService.kt index 98ff5914d..5bc097fe5 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadService.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadService.kt @@ -183,28 +183,23 @@ class FeedLoadService : Service() { subscriptions .take(1) - .doOnNext { currentProgress.set(0) maxProgress.set(it.size) } .filter { it.isNotEmpty() } - .observeOn(AndroidSchedulers.mainThread()) .doOnNext { startForeground(NOTIFICATION_ID, notificationBuilder.build()) updateNotificationProgress(null) broadcastProgress() } - .observeOn(Schedulers.io()) .flatMap { Flowable.fromIterable(it) } .takeWhile { !cancelSignal.get() } - .parallel(PARALLEL_EXTRACTIONS, PARALLEL_EXTRACTIONS * 2) .runOn(Schedulers.io(), PARALLEL_EXTRACTIONS * 2) .filter { !cancelSignal.get() } - .map { subscriptionEntity -> var error: Throwable? = null try { @@ -239,14 +234,11 @@ class FeedLoadService : Service() { } } .sequential() - .observeOn(AndroidSchedulers.mainThread()) .doOnNext(notificationsConsumer) - .observeOn(Schedulers.io()) .buffer(BUFFER_COUNT_BEFORE_INSERT) .doOnNext(databaseConsumer) - .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(resultSubscriber) diff --git a/app/src/test/java/org/schabi/newpipe/settings/ContentSettingsManagerTest.kt b/app/src/test/java/org/schabi/newpipe/settings/ContentSettingsManagerTest.kt index 2311b41ce..ec41a77f8 100644 --- a/app/src/test/java/org/schabi/newpipe/settings/ContentSettingsManagerTest.kt +++ b/app/src/test/java/org/schabi/newpipe/settings/ContentSettingsManagerTest.kt @@ -9,12 +9,12 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito -import org.mockito.Mockito.`when` import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.anyInt import org.mockito.Mockito.anyString import org.mockito.Mockito.atLeastOnce import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` import org.mockito.Mockito.withSettings import org.mockito.junit.MockitoJUnitRunner import org.schabi.newpipe.streams.io.StoredFileHelper From f86fc03c466a0b2417071cd9ec37b78788ee3eae Mon Sep 17 00:00:00 2001 From: TacoTheDank Date: Sat, 4 Dec 2021 21:30:23 -0500 Subject: [PATCH 18/49] Update Checkstyle to 9.2 --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index ba92d97c7..319306901 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -98,7 +98,7 @@ android { } ext { - checkstyleVersion = '8.38' + checkstyleVersion = '9.2' androidxLifecycleVersion = '2.3.1' androidxRoomVersion = '2.3.0' From bb49b1cfb1cdb4fa04a8ec2fd472ccc01b34ae56 Mon Sep 17 00:00:00 2001 From: Stypox Date: Tue, 7 Dec 2021 18:11:36 +0100 Subject: [PATCH 19/49] Add javadoc to ErrorUtil and ErrorActivity --- .../schabi/newpipe/error/ErrorActivity.java | 4 ++ .../org/schabi/newpipe/error/ErrorUtil.kt | 54 +++++++++++++++++-- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java index 07f736af3..bd8430296 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java @@ -52,6 +52,10 @@ import java.util.Arrays; * along with NewPipe. If not, see . */ +/** + * This activity is used to show error details and allow reporting them in various ways. Use {@link + * ErrorUtil#openActivity(Context, ErrorInfo)} to correctly open this activity. + */ public class ErrorActivity extends AppCompatActivity { // LOG TAGS public static final String TAG = ErrorActivity.class.toString(); diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt index b766d91c6..3fd743c69 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt @@ -15,27 +15,59 @@ import androidx.fragment.app.Fragment import com.google.android.material.snackbar.Snackbar import org.schabi.newpipe.R +/** + * This class contains all of the methods that should be used to let the user know that an error has + * occurred in the least intrusive way possible for each case. This class is for unexpected errors, + * for handled errors (e.g. network errors) use e.g. [ErrorPanelHelper] instead. + * - Use a snackbar if the exception is not critical and it happens in a place where a root view + * is available. + * - Use a notification if the exception happens inside a background service (player, subscription + * import, ...) or there is no activity/fragment from which to extract a root view. + * - Finally use the error activity only as a last resort in case the exception is critical and + * happens in an open activity (since the workflow would be interrupted anyway in that case). + */ class ErrorUtil { companion object { private const val ERROR_REPORT_NOTIFICATION_ID = 5340681 /** - * Reports a new error by starting a new activity. + * Starts a new error activity allowing the user to report the provided error. Only use this + * method directly as a last resort in case the exception is critical and happens in an open + * activity (since the workflow would be interrupted anyway in that case). So never use this + * for background services. * - * @param context - * @param errorInfo + * @param context the context to use to start the new activity + * @param errorInfo the error info to be reported */ @JvmStatic fun openActivity(context: Context, errorInfo: ErrorInfo) { context.startActivity(getErrorActivityIntent(context, errorInfo)) } + /** + * Show a bottom snackbar to the user, with a report button that opens the error activity. + * Use this method if the exception is not critical and it happens in a place where a root + * view is available. + * + * @param context will be used to obtain the root view if it is an [Activity]; if no root + * view can be found an error notification is shown instead + * @param errorInfo the error info to be reported + */ @JvmStatic fun showSnackbar(context: Context, errorInfo: ErrorInfo) { val rootView = if (context is Activity) context.findViewById(R.id.content) else null showSnackbar(context, rootView, errorInfo) } + /** + * Show a bottom snackbar to the user, with a report button that opens the error activity. + * Use this method if the exception is not critical and it happens in a place where a root + * view is available. + * + * @param fragment will be used to obtain the root view if it has a connected [Activity]; if + * no root view can be found an error notification is shown instead + * @param errorInfo the error info to be reported + */ @JvmStatic fun showSnackbar(fragment: Fragment, errorInfo: ErrorInfo) { var rootView = fragment.view @@ -45,16 +77,32 @@ class ErrorUtil { showSnackbar(fragment.requireContext(), rootView, errorInfo) } + /** + * Shortcut to calling [showSnackbar] with an [ErrorInfo] of type [UserAction.UI_ERROR] + */ @JvmStatic fun showUiErrorSnackbar(context: Context, request: String, throwable: Throwable) { showSnackbar(context, ErrorInfo(throwable, UserAction.UI_ERROR, request)) } + /** + * Shortcut to calling [showSnackbar] with an [ErrorInfo] of type [UserAction.UI_ERROR] + */ @JvmStatic fun showUiErrorSnackbar(fragment: Fragment, request: String, throwable: Throwable) { showSnackbar(fragment, ErrorInfo(throwable, UserAction.UI_ERROR, request)) } + /** + * Create an error notification. Tapping on the notification opens the error activity. Use + * this method if the exception happens inside a background service (player, subscription + * import, ...) or there is no activity/fragment from which to extract a root view. + * + * @param context the context to use to show the notification + * @param errorInfo the error info to be reported; the error message + * [ErrorInfo.messageStringId] will be shown in the notification + * description + */ @JvmStatic fun createNotification(context: Context, errorInfo: ErrorInfo) { val notificationManager = From b9ee14ac303d10f3a5f56a8e550a682a12b196c0 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Tue, 7 Dec 2021 21:31:12 +0100 Subject: [PATCH 20/49] Update string-resource Co-authored-by: Stypox --- 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 a8d308cd9..8d82c3dd7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -671,7 +671,7 @@ Recent Chapters No app on your device can open this - No appropriate file manager was found for this action.\nPlease install a file manager or try to enable/disable \'%s\' in the download settings. + No appropriate file manager was found for this action.\nPlease install a file manager or try to disable \'%s\' in the download settings. This content is not available in your country. This is a SoundCloud Go+ track, at least in your country, so it cannot be streamed or downloaded by NewPipe. This content is private, so it cannot be streamed or downloaded by NewPipe. From 8a5e2ffa579beb8f14d60455f1a9e43d19deb704 Mon Sep 17 00:00:00 2001 From: Stypox Date: Sat, 4 Dec 2021 10:22:17 +0100 Subject: [PATCH 21/49] Fix order of local search results --- .../history/dao/SearchHistoryDAO.java | 13 +++++----- .../fragments/list/search/SearchFragment.java | 25 ++++++++----------- .../local/history/HistoryRecordManager.java | 6 ++--- 3 files changed, 20 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/database/history/dao/SearchHistoryDAO.java b/app/src/main/java/org/schabi/newpipe/database/history/dao/SearchHistoryDAO.java index a0010a419..8a281bdb4 100644 --- a/app/src/main/java/org/schabi/newpipe/database/history/dao/SearchHistoryDAO.java +++ b/app/src/main/java/org/schabi/newpipe/database/history/dao/SearchHistoryDAO.java @@ -19,6 +19,7 @@ import static org.schabi.newpipe.database.history.model.SearchHistoryEntry.TABLE @Dao public interface SearchHistoryDAO extends HistoryDAO { String ORDER_BY_CREATION_DATE = " ORDER BY " + CREATION_DATE + " DESC"; + String ORDER_BY_MAX_CREATION_DATE = " ORDER BY MAX(" + CREATION_DATE + ") DESC"; @Query("SELECT * FROM " + TABLE_NAME + " WHERE " + ID + " = (SELECT MAX(" + ID + ") FROM " + TABLE_NAME + ")") @@ -36,16 +37,16 @@ public interface SearchHistoryDAO extends HistoryDAO { @Override Flowable> getAll(); - @Query("SELECT * FROM " + TABLE_NAME + " GROUP BY " + SEARCH + ORDER_BY_CREATION_DATE - + " LIMIT :limit") - Flowable> getUniqueEntries(int limit); + @Query("SELECT " + SEARCH + " FROM " + TABLE_NAME + " GROUP BY " + SEARCH + + ORDER_BY_MAX_CREATION_DATE + " LIMIT :limit") + Flowable> getUniqueEntries(int limit); @Query("SELECT * FROM " + TABLE_NAME + " WHERE " + SERVICE_ID + " = :serviceId" + ORDER_BY_CREATION_DATE) @Override Flowable> listByService(int serviceId); - @Query("SELECT * FROM " + TABLE_NAME + " WHERE " + SEARCH + " LIKE :query || '%'" - + " GROUP BY " + SEARCH + " LIMIT :limit") - Flowable> getSimilarEntries(String query, int limit); + @Query("SELECT " + SEARCH + " FROM " + TABLE_NAME + " WHERE " + SEARCH + " LIKE :query || '%'" + + " GROUP BY " + SEARCH + ORDER_BY_MAX_CREATION_DATE + " LIMIT :limit") + Flowable> getSimilarEntries(String query, int limit); } 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 d4d73f74f..3f199f411 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 @@ -1,5 +1,10 @@ package org.schabi.newpipe.fragments.list.search; +import static androidx.recyclerview.widget.ItemTouchHelper.Callback.makeMovementFlags; +import static org.schabi.newpipe.ktx.ViewUtils.animate; +import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView; +import static java.util.Arrays.asList; + import android.app.Activity; import android.content.Context; import android.content.Intent; @@ -36,7 +41,6 @@ import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; import org.schabi.newpipe.R; -import org.schabi.newpipe.database.history.model.SearchHistoryEntry; import org.schabi.newpipe.databinding.FragmentSearchBinding; import org.schabi.newpipe.error.ErrorActivity; import org.schabi.newpipe.error.ErrorInfo; @@ -68,12 +72,11 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Queue; -import java.util.Set; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import icepick.State; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; @@ -84,11 +87,6 @@ import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subjects.PublishSubject; -import static androidx.recyclerview.widget.ItemTouchHelper.Callback.makeMovementFlags; -import static java.util.Arrays.asList; -import static org.schabi.newpipe.ktx.ViewUtils.animate; -import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView; - public class SearchFragment extends BaseListFragment> implements BackPressable { /*////////////////////////////////////////////////////////////////////////// @@ -743,13 +741,10 @@ public class SearchFragment extends BaseListFragment { - final Set result = new HashSet<>(); // remove duplicates - for (final SearchHistoryEntry entry : searchHistoryEntries) { - result.add(new SuggestionItem(true, entry.getSearch())); - } - return new ArrayList<>(result); - }); + .map(searchHistoryEntries -> + searchHistoryEntries.stream() + .map(entry -> new SuggestionItem(true, entry)) + .collect(Collectors.toList())); } private Observable> getRemoteSuggestionsObservable(final String query) { 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 d94088cd0..45445cf58 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 @@ -244,9 +244,9 @@ public class HistoryRecordManager { .subscribeOn(Schedulers.io()); } - public Flowable> getRelatedSearches(final String query, - final int similarQueryLimit, - final int uniqueQueryLimit) { + public Flowable> getRelatedSearches(final String query, + final int similarQueryLimit, + final int uniqueQueryLimit) { return query.length() > 0 ? searchHistoryTable.getSimilarEntries(query, similarQueryLimit) : searchHistoryTable.getUniqueEntries(uniqueQueryLimit); From e806f8c4e602697eddeb7525e71ca5fe14d4d8fa Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Wed, 8 Dec 2021 20:22:26 +0100 Subject: [PATCH 22/49] Android 10+ only allows SAF -> Respect that in the dialog --- .../streams/io/NoFileManagerSafeGuard.java | 17 +++++++++++++---- app/src/main/res/values/strings.xml | 1 + 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerSafeGuard.java b/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerSafeGuard.java index c7dcb9975..df43c34c1 100644 --- a/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerSafeGuard.java +++ b/app/src/main/java/org/schabi/newpipe/streams/io/NoFileManagerSafeGuard.java @@ -2,6 +2,7 @@ package org.schabi.newpipe.streams.io; import android.content.ActivityNotFoundException; import android.content.Context; +import android.os.Build; import android.util.Log; import androidx.activity.result.ActivityResultLauncher; @@ -27,12 +28,20 @@ public final class NoFileManagerSafeGuard { "Unable to open no file manager alert dialog: Context is null"); } + final String message; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + // Android 10+ only allows SAF + message = context.getString(R.string.no_appropriate_file_manager_message_android_10); + } else { + message = context.getString( + R.string.no_appropriate_file_manager_message, + context.getString(R.string.downloads_storage_use_saf_title)); + } + + new AlertDialog.Builder(context) .setTitle(R.string.no_app_to_open_intent) - .setMessage( - context.getString( - R.string.no_appropriate_file_manager_message, - context.getString(R.string.downloads_storage_use_saf_title))) + .setMessage(message) .setPositiveButton(R.string.ok, null) .show(); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8d82c3dd7..22051939b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -672,6 +672,7 @@ Chapters No app on your device can open this No appropriate file manager was found for this action.\nPlease install a file manager or try to disable \'%s\' in the download settings. + No appropriate file manager was found for this action.\nPlease install a Storage Access Framework compatible file manager. This content is not available in your country. This is a SoundCloud Go+ track, at least in your country, so it cannot be streamed or downloaded by NewPipe. This content is private, so it cannot be streamed or downloaded by NewPipe. From c92a90749ef1188f50afe528245a54afd180613c Mon Sep 17 00:00:00 2001 From: Cheechaii <95134933+Cheechaii@users.noreply.github.com> Date: Sat, 27 Nov 2021 15:58:48 +0100 Subject: [PATCH 23/49] Respect cutouts when playing in MultiWindow --- .../fragments/detail/VideoDetailFragment.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) 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 5552cf73f..c5d4693de 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 @@ -1958,7 +1958,9 @@ public final class VideoDetailFragment // Prevent jumping of the player on devices with cutout if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { activity.getWindow().getAttributes().layoutInDisplayCutoutMode = - WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT; + isMultiWindowOrFullscreen() + ? WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER + : WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT; } activity.getWindow().getDecorView().setSystemUiVisibility(0); activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); @@ -1980,7 +1982,9 @@ public final class VideoDetailFragment // Prevent jumping of the player on devices with cutout if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { activity.getWindow().getAttributes().layoutInDisplayCutoutMode = - WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; + isMultiWindowOrFullscreen() + ? WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER + : WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; } int visibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN @@ -1997,7 +2001,7 @@ public final class VideoDetailFragment activity.getWindow().getDecorView().setSystemUiVisibility(visibility); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP - && (isInMultiWindow || (isPlayerAvailable() && player.isFullscreen()))) { + && isMultiWindowOrFullscreen()) { activity.getWindow().setStatusBarColor(Color.TRANSPARENT); activity.getWindow().setNavigationBarColor(Color.TRANSPARENT); } @@ -2013,6 +2017,11 @@ public final class VideoDetailFragment } } + private boolean isMultiWindowOrFullscreen() { + return DeviceUtils.isInMultiWindow(activity) + || (isPlayerAvailable() && player.isFullscreen()); + } + private boolean playerIsNotStopped() { return isPlayerAvailable() && !player.isStopped(); } From 1ee137bbda54f17e4ae36dcaa3d1f59bc8f28852 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sat, 11 Dec 2021 16:21:34 +0100 Subject: [PATCH 24/49] Updated to NewPipeExtractor to version ``v0.21.12`` --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index cd1d32453..35bdd998e 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:f6f2724634' + implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.21.12' /** Checkstyle **/ checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}" From 6b026557d415dfa329b81f705e4bb3767c36b3e2 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Sat, 11 Dec 2021 16:43:05 +0100 Subject: [PATCH 25/49] Translated using Weblate (French) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 99.5% (628 of 631 strings) Translated using Weblate (Hungarian) Currently translated at 3.2% (2 of 61 strings) Translated using Weblate (Punjabi) Currently translated at 4.9% (3 of 61 strings) Translated using Weblate (Telugu) Currently translated at 6.5% (4 of 61 strings) Translated using Weblate (German) Currently translated at 50.8% (31 of 61 strings) Translated using Weblate (Portuguese (Portugal)) Currently translated at 100.0% (631 of 631 strings) Translated using Weblate (Punjabi) Currently translated at 91.4% (577 of 631 strings) Translated using Weblate (Telugu) Currently translated at 38.1% (241 of 631 strings) Translated using Weblate (Indonesian) Currently translated at 100.0% (631 of 631 strings) Translated using Weblate (Japanese) Currently translated at 99.2% (626 of 631 strings) Translated using Weblate (Russian) Currently translated at 99.8% (630 of 631 strings) Translated using Weblate (Serbian) Currently translated at 96.5% (609 of 631 strings) Translated using Weblate (German) Currently translated at 100.0% (631 of 631 strings) Translated using Weblate (Tamil) Currently translated at 1.6% (1 of 61 strings) Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (61 of 61 strings) Translated using Weblate (Polish) Currently translated at 55.7% (34 of 61 strings) Translated using Weblate (Hebrew) Currently translated at 50.8% (31 of 61 strings) Translated using Weblate (Ukrainian) Currently translated at 80.3% (49 of 61 strings) Translated using Weblate (Swedish) Currently translated at 100.0% (631 of 631 strings) Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (631 of 631 strings) Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (631 of 631 strings) Translated using Weblate (Polish) Currently translated at 100.0% (631 of 631 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (631 of 631 strings) Translated using Weblate (Greek) Currently translated at 100.0% (631 of 631 strings) Translated using Weblate (Portuguese) Currently translated at 100.0% (631 of 631 strings) Translated using Weblate (Japanese) Currently translated at 98.8% (624 of 631 strings) Translated using Weblate (Dutch) Currently translated at 99.8% (630 of 631 strings) Translated using Weblate (French) Currently translated at 99.0% (625 of 631 strings) Translated using Weblate (Spanish) Currently translated at 100.0% (631 of 631 strings) Translated using Weblate (German) Currently translated at 100.0% (631 of 631 strings) Translated using Weblate (English) Currently translated at 100.0% (631 of 631 strings) Translated using Weblate (English) Currently translated at 100.0% (631 of 631 strings) Co-authored-by: Agnieszka C Co-authored-by: Alex25820 Co-authored-by: Allan Nordhøy Co-authored-by: Balázs Meskó Co-authored-by: GnuPGを使うべきだ Co-authored-by: Hosted Weblate Co-authored-by: Human Beeing Co-authored-by: Ihor Hordiichuk Co-authored-by: JY3 Co-authored-by: Linerly Co-authored-by: Naveen Co-authored-by: Ricardo Co-authored-by: Terry Louwers Co-authored-by: Vasilis K Co-authored-by: Yaron Shahrabani Co-authored-by: chr56 Co-authored-by: nautilusx Co-authored-by: nzgha Co-authored-by: rickeesingh Co-authored-by: ssantos Co-authored-by: subba raidu Co-authored-by: translator Co-authored-by: Даниил Морозюк Co-authored-by: Саша Петровић Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/de/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/he/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/hu/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pa/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pl/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ta/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/te/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/uk/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/zh_Hans/ Translation: NewPipe/Metadata --- .../main/res/values-b+zh+HANS+CN/strings.xml | 8 +- app/src/main/res/values-de/strings.xml | 4 +- app/src/main/res/values-el/strings.xml | 6 +- app/src/main/res/values-es/strings.xml | 6 +- app/src/main/res/values-fr/strings.xml | 5 + app/src/main/res/values-in/strings.xml | 5 + app/src/main/res/values-ja/strings.xml | 4 + app/src/main/res/values-nl/strings.xml | 12 +- app/src/main/res/values-pa/strings.xml | 2 +- app/src/main/res/values-pl/strings.xml | 10 +- app/src/main/res/values-pt-rBR/strings.xml | 6 + app/src/main/res/values-pt-rPT/strings.xml | 11 +- app/src/main/res/values-pt/strings.xml | 11 +- app/src/main/res/values-ru/strings.xml | 3 + app/src/main/res/values-sr/strings.xml | 17 +- app/src/main/res/values-sv/strings.xml | 7 +- app/src/main/res/values-te/strings.xml | 159 ++++++++++++++---- app/src/main/res/values-uk/strings.xml | 8 +- app/src/main/res/values/strings.xml | 6 +- .../metadata/android/de/changelogs/958.txt | 25 +-- .../metadata/android/he/changelogs/980.txt | 13 ++ .../metadata/android/hu/changelogs/63.txt | 8 + .../metadata/android/hu/full_description.txt | 2 +- .../metadata/android/pa/changelogs/63.txt | 8 + .../metadata/android/pa/changelogs/64.txt | 8 + .../metadata/android/pl/changelogs/980.txt | 13 ++ .../metadata/android/ta/changelogs/63.txt | 8 + .../metadata/android/ta/changelogs/64.txt | 8 + .../metadata/android/ta/full_description.txt | 1 + .../metadata/android/te/changelogs/63.txt | 8 + .../metadata/android/te/changelogs/64.txt | 8 + .../metadata/android/te/full_description.txt | 1 + .../metadata/android/te/short_description.txt | 1 + .../metadata/android/uk/changelogs/980.txt | 13 ++ .../android/zh-Hans/changelogs/980.txt | 13 ++ 35 files changed, 344 insertions(+), 84 deletions(-) create mode 100644 fastlane/metadata/android/he/changelogs/980.txt create mode 100644 fastlane/metadata/android/hu/changelogs/63.txt create mode 100644 fastlane/metadata/android/pa/changelogs/63.txt create mode 100644 fastlane/metadata/android/pa/changelogs/64.txt create mode 100644 fastlane/metadata/android/pl/changelogs/980.txt create mode 100644 fastlane/metadata/android/ta/changelogs/63.txt create mode 100644 fastlane/metadata/android/ta/changelogs/64.txt create mode 100644 fastlane/metadata/android/ta/full_description.txt create mode 100644 fastlane/metadata/android/te/changelogs/63.txt create mode 100644 fastlane/metadata/android/te/changelogs/64.txt create mode 100644 fastlane/metadata/android/te/full_description.txt create mode 100644 fastlane/metadata/android/te/short_description.txt create mode 100644 fastlane/metadata/android/uk/changelogs/980.txt create mode 100644 fastlane/metadata/android/zh-Hans/changelogs/980.txt 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 038512f3a..4e9511d8c 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 @@ -62,7 +62,7 @@ 网格 NewPipe 可更新! 服务器不接受多线程下载, 使用 @string/msg_threads = 1 重试 - 自动恢复上次播放 + 自动播放 清空数据 播放历史已删除 喜欢 @@ -211,7 +211,7 @@ 时下流行 前 50 最新与热门 - 显示“长按添加”说明 + 显示“长按加入播放队列”提示 在视频详情页中,长按后台播放或悬浮窗播放按钮时显示提示 无法播放此串流 发生无法处理的播放器错误 @@ -534,7 +534,7 @@ 显示结果:%s 从不 仅在 Wi-Fi 下 - 视频开始播放后,自动定位到上次播放时的位置 — %s + 自动开始播放 — %s 播放队列 无法识别此 URL。是否用其他应用打开\? 自动加入播放队列 @@ -611,7 +611,7 @@ 语言 年龄限制 私有性 - 发行许可 + 许可 标签 类别 启用简介中的文本选择功能 diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 30300c192..feb7e85c3 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -184,7 +184,7 @@ Tipp anzeigen, wenn der Hintergrundwiedergabe- oder Pop-up-Knopf „Details:“ im Video gedrückt wird Neu und Heiß Halten, um zur Wiedergabeliste hinzuzufügen - „Zum Anhängen gedrückt halten“ Tipp anzeigen + „Halten zum Einreihen“ Tipp anzeigen [Unbekannt] Wiedergabe im Hintergrund starten Wiedergabe in einem Pop-up starten @@ -566,7 +566,7 @@ Wiederholen Nichts Warteschlange abspielen - Automatische Warteschlange + Auto-Einreihung Der Wechsel von einem Player zu einem anderen kann deine Warteschlange überschreiben Überschreiben der Warteschlange bestätigen Die aktive Player-Warteschlange wird ersetzt diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index dff16cd05..bff4dea91 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -106,7 +106,7 @@ Κρατήστε ιστορικό των αναπαραχθέντων βίντεο Ανάκτηση αναπαραγωγής Συνέχιση της αναπαραγωγής έπειτα από διακοπές (π.χ. κλήσεις) - Εμφάνιση επεξήγησης του «Πιέστε παρατεταμένα για προσθήκη» + Εμφάνιση επεξήγησης του «Πιέστε παρατεταμένα για προσθήκη στην ουρά» Εμφάνιση υπόδειξης όταν πατηθεί το κουμπί παρασκηνίου ή αναδυόμενου παραθύρου στη σελίδα λεπτομερειών του βίντεο Προεπιλεγμένη χώρα περιεχομένου Αναπαραγωγός @@ -252,7 +252,7 @@ Αφαίρεση Λεπτομέρειες Ρυθμίσεις ήχου - Πιέστε παρατεταμένα για να προστεθεί στην ουρά + Πιέστε παρατεταμένα για προσθήκη στην ουρά Εκκίνηση αναπαραγωγής στο παρασκήνιο Εκκίνηση αναπαραγωγής σε ένα αναδυόμενο παράθυρο Άνοιγμα συρταριού @@ -487,7 +487,7 @@ Λειτουργία περιορισμένης πρόσβασης του YouTube Ειδοποίηση Δεν ήταν δυνατή η αναγνώριση της διεύθυνσης URL. Άνοιγμα με άλλη εφαρμογή; - Αυτόματη ουρά + Αυτόματη προσθήκη στην ουρά Η ουρά του ενεργού αναπαραγωγού θα αντικατασταθεί Η εναλλαγή από έναν αναπαραγωγό σε άλλον, μπορεί να αντικαταστήσει την ουρά σας Ζητήστε επιβεβαίωση πριν από την εκκαθάριση μιας ουράς diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 3cf061e06..ffdf60d7e 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -183,7 +183,7 @@ [Desconocido] Comenzar a reproducir en segundo plano Reproducir en modo emergente - Mostrar la sugerencia \"Mantener pulsado para añadir a la cola\" + Mostrar sugerencia de \"Mantener pulsado para añadir a la cola\" Nuevo y lo mejor Mantener pulsado para añadir a la cola Donar @@ -250,7 +250,7 @@ Forzar informe de excepciones no entregables de RX fuera del fragmento o del ciclo de actividad después del descarte Usar búsqueda rápida e inexacta La búsqueda inexacta permite al reproductor buscar posiciones más rápido con menor precisión. Buscar de a 5, 15 o 25 segundos no funciona - Poner en cola vídeo relacionado siguiente + Poner en cola automáticamente la siguiente transmisión Continuar reproducción sin repetir al añadir de forma automática un vídeo relacionado con el último visto Archivo Archivo movido o borrado @@ -553,7 +553,7 @@ Reproducir cola Notificación No se pudo reconocer la URL. ¿Abrir con otra aplicación\? - Poner en cola + Poner en cola automáticamente Cambiar de un reproductor a otro puede reemplazar la cola de reproducción La cola de reproducción activa será reemplazada Pedir confirmación antes de vaciar una cola diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 93f31f59a..44d43ce83 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -676,4 +676,9 @@ Vérification des mises à jour… Vérifier les mises à jours Nouveaux éléments du flux + Reporter les erreurs du lecteur en détail au lieu de montrer un bref message éphémère (utile pour diagnostiquer les problèmes) + Reporter des erreurs du lecteur + Couper le lecteur + Montrer \"Couper le lecteur\" + Montrer une option couper lors de l\'utilisation du lecteur \ No newline at end of file diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 7e32445a2..b420c56d1 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -661,4 +661,9 @@ Periksa manual untuk versi baru Memeriksa pembaruan… Item feed baru + Tampilkan \"hentikan pemain video\" + Menampilkan opsi penghentian ketika menggunakan pemain video + Melaporkan kesalahan pemain video dalam detail yang penuh daripada menampilkan pesan toast yang muncul sebentar (berguna untuk memeriksa masalah) + Laporkan kesalahan pemain video + Hentikan pemain video \ No newline at end of file diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 095fb7bea..6cedc2566 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -661,4 +661,8 @@ 次をキューに追加 次をキューに追加しました クリエイターの心をこめて + プレーヤーのエラーを、短時間のトーストメッセージではなく、詳細に報告する(問題の診断に役立ちます) + プレイヤーのエラーを報告 + \"プレイヤーがクラッシュ\"を表示 + プレイヤーがクラッシュ \ No newline at end of file diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index b835c68dc..9fef6b795 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -564,7 +564,7 @@ Eerste actieknop Schaal de miniatuurafbeelding van de video die getoond wordt in de notificatie van verhouding 16:9 naar 1:1 (dit kan vervorming creëren) Schaal de miniatuurafbeelding tot verhouding 1:1 - Auto-wachtrij + Automatisch in de wachtrij plaatsen Toon memory leaks In de wachtrij geplaatst In de wachtrij plaatsen @@ -669,4 +669,14 @@ Veeg items om ze te verwijderen Start geen video\'s in de minispeler, maar ga direct naar de volledige schermmodus, als automatisch draaien is vergrendeld. Je hebt nog steeds toegang tot de minispeler door de volledige schermmodus af te sluiten Start hoofdspeler als volledig scherm + Rapporteer fouten van de speler in volledig detail in plaats van een kortstondige toastmelding te tonen (handig voor het diagnosticeren van problemen) + Verwerken... Dit kan even duren + Crash de speler + Rapporteer fouten van de speler + Toon \"crash de speler\" + Toon een crash overzicht bij gebruik van de speler + Controleer handmatig op nieuwe versies + Controleer op updates + Bezig met controleren op updates… + Nieuwe feed items \ No newline at end of file diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml index 8fad329f3..219440faa 100644 --- a/app/src/main/res/values-pa/strings.xml +++ b/app/src/main/res/values-pa/strings.xml @@ -1,6 +1,6 @@ - ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਸਰਚ ਦਬਾਓ + ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਵੱਡਦਰਸ਼ੀ ਕੱਚ ਨੂੰ ਦਬਾਓ %1$s ਨੂੰ ਜਾਰੀ ਕੀਤੀ ਗਈ ਕੋਈ ਸਟ੍ਰੀਮ ਪਲੇਅਰ ਨਹੀਂ ਮਿਲਿਆ। ਤੁਸੀਂ ਵੀਐੱਲਸੀ ਸਥਾਪਤ ਕਰਨਾ ਚਾਹੋਗੇ\? ਸਟ੍ਰੀਮ ਪਲੇਅਰ ਨਹੀਂ ਮਿਲਿਆ (ਤੁਸੀਂ ਵੀਐੱਲਸੀ ਸਥਾਪਤ ਕਰਕੇ ਇਸਨੂੰ ਚਲਾ ਸਕਦੇ ਹੋ)। diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 1a623b7d1..7a776d862 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -252,8 +252,8 @@ Powiększ Wygenerowane automatycznie Monitorowanie wycieków pamięci może powodować niestabilność aplikacji podczas zrzutu pamięci - Zgłoś błędy spoza cyklu życia - Wymuś raportowanie niedostarczonych wyjątków Rx poza cyklem życia fragmentu lub aktywności + Zgłaszaj błędy spoza cyklu życia + Wymuś raportowanie niedostarczonych wyjątków Rx poza cyklem życia fragmentu lub aktywności po usunięciu Używaj szybkiego, niedokładnego przewijania Niedokładne przewijanie umożliwia szybsze przewijanie ze zmniejszoną dokładnością. Przewijanie o 5, 15 lub 25 sekund nie działa w tym przypadku Wczytuj miniatury @@ -544,7 +544,7 @@ Usunąć obejrzane wideo\? Usuń obejrzane Oryginalne teksty z usług będą widoczne w strumieniowanych pozycjach - Pokaż oryginalny czas + Pokazuj oryginalny czas na pozycjach Włącz tryb ograniczonego dostępu YouTube\'a Przez %s Utworzony przez %s @@ -667,8 +667,8 @@ Oznacz jako obejrzane Ładowanie szczegółów kanału… Błąd podczas wyświetlania szczegółów kanału - Pokaż kolorowe wstążki Picasso nad obrazami wskazujące ich źródło: czerwone dla sieci, niebieskie dla dysku i zielone dla pamięci - Pokaż wskaźniki obrazu + Pokazuj kolorowe wstążki Picasso nad obrazami wskazujące ich źródło: czerwone dla sieci, niebieskie dla dysku i zielone dla pamięci + Pokazuj wskaźniki obrazu Zdalne podpowiedzi wyszukiwania Lokalne podpowiedzi wyszukiwania diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index dcdb1d4f9..434993d2b 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -673,4 +673,10 @@ Procurar por atualizações Procurar manualmente por novas versões Procurando por atualizações… + Travar o player + Reporta os erros do player em detalhes completos, em vez de mostrar uma mensagem de notificação de curta duração (útil para diagnosticar problemas) + Mostrar \"travar o player\" + Reportar erros do player + Mostra uma opção de travamento ao usar o player + Novos itens do feed \ No newline at end of file diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index b8f6b4f22..446c79486 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -351,7 +351,7 @@ %d hora %d horas - Colocar vídeo seguinte na fila + Enfileirar o próximo stream automaticamente Defina as suas instâncias favoritas PeerTube Exportar histórico, subscrições, listas de reprodução e definições Melhor resolução @@ -468,7 +468,7 @@ Selecionar subscrições Adicionado à lista de reprodução Formato padrão de vídeo - Mostrar dica \"Toque longo para colocar na fila\" + Mostrar dica \"Toque longo para enfileirar\" Escolha uma instância Limpar todos os dados da página web Fechar menu @@ -547,7 +547,7 @@ Reproduzir fila Notificação URL não reconhecido. Abrir com outra aplicação\? - Colocar na fila automaticamente + Enfileiramento automático A fila do reprodutor ativo será substituída Mudar de um reprodutor para outro pode substituir a sua fila Pedir confirmação antes de limpar uma fila @@ -674,4 +674,9 @@ Verificar manualmente se existe uma nova versão A procurar atualizações… Novos itens + Travar o reprodutor + Relata os erros do reprodutor com todos os detalhes em vez de mostrar uma mensagem de notificação por pouco tempo (útil para diagnosticar problemas) + Relatar erros do reprodutor + Mostrar \"travar o reprodutor\" + Mostra uma opção de travamento ao usar o reprodutor \ No newline at end of file diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 43c2fd01f..9e36e1928 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -282,7 +282,7 @@ Ritmo Limpar histórico de visualizações Continuar (sem repetição) a fila de reprodução anexando um vídeo relacionado - Mostrar dica \"Toque longo para colocar na fila\" + Mostrar dica \"Toque longo para enfileirar\" Mostrar dica ao premir em segundo plano ou no botão \"Detalhes:\" da janela popup Canais Listas de reprodução @@ -303,7 +303,7 @@ O projeto NewPipe leva a sua privacidade muito a sério. Por isso, não recolhe nenhum dado sem o seu consentimento. \nA polícia de privacidade do NewPipe explica, em detalhe, os tipos de dados enviados sempre que submete um relatório de erro. Ver política de privacidade - Colocar vídeo seguinte na fila + Enfileirar o próximo stream automaticamente NewPipe é um software livre \"copyleft\": pode utilizar, estudar, partilhar e melhorar a aplicação. Especificamente, pode redistribuir e/ou modificar a aplicação nos termos da GNU General Public License, conforme publicada pela Free Software Foundation, tanto a versão 3 da licença ou (por opção) qualquer versão posterior. Também deseja importar as definições\? Toque longo para colocar na fila @@ -554,7 +554,7 @@ A carregar A fila do reprodutor ativo será substituída URL não reconhecido. Abrir com outra aplicação\? - Colocar na fila automaticamente + Enfileiramento automático Baralhar Notificação Apenas em Wi-Fi @@ -674,4 +674,9 @@ Verificar manualmente se existe uma nova versão A procurar atualizações… Novos itens + Travar o reprodutor + Relata os erros do reprodutor com todos os detalhes em vez de mostrar uma mensagem de notificação por pouco tempo (útil para diagnosticar problemas) + Relatar erros do reprodutor + Mostrar \"travar o reprodutor\" + Mostra uma opção de travamento ao usar o reprodutor \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 427a1987e..4710777f9 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -692,4 +692,7 @@ Новое на канале Отчёт об ошибках плеера Подробные отчёты об ошибках плеера вместо коротких всплывающих сообщений (полезно при диагностике проблем) + Показать \"Вызвать сбой плеера\" + Показать функцию вызова сбоя при работе плеера + Вызвать сбой плеера \ No newline at end of file diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index e27d9e8a8..66258db25 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -194,7 +194,7 @@ Увек Само једном [непознато] - Прикажи поруку „задржи ради стављања у ред” + Прикажи поруку „задржи ради заказивања” Донација ЊуПајп развијају волонтери у своје слободно време како би вам пружили најбоље искуство. Узвратите им како би наставили са побољшавањем ЊуПајпа док уживају уз шољицу кафе. Узврати @@ -507,9 +507,9 @@ Контрола осветљености потезом Користите потезе за контролу јачине звука плејера Контрола јачине звука потезом - Аутоматски ред + Самостално заказивање Наставите да завршавате (не понављајући) ред репродукције додавањем повезаног стрима - Аутоматски стави у ред следећи ток + Самостално закажи следећи ток Кеш метаподатака обрисан Искључите за сакривање поља мета-података са додатним информацијама о творцу тока, садржају или захтеву за претрагу Прикажи мета-податке @@ -652,4 +652,15 @@ укљ Режим таблета Прикажи пуштано + Закажи следеће + Заказано је следеће + Местни предлози претраге + Удаљени предлози претраге + Означи као одгледано + Разговори су онемогућени + Обрађујем… Може потрајати пар тренутака + Приказуј указиваче слике + Не покрећи видео у малом прозору, већ пређи одмах у пун приказ заслона, уколико је обртање приказа закључано. И даље можете приступити малом приказу извођача изласком из пуног приказа + Пријави грешке програма извођача видеа + Покрени пуни главни приказ извођача \ No newline at end of file diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index dadf7d047..d36248f55 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -91,7 +91,7 @@ Håll koll på videor som du tittat på Återuppta uppspelning Fortsätt uppspelning efter avbrott (t.ex. telefonsamtal) - Visa \"Håll för att lägga till\"-tips + Visa \"Håll för att placera i kön\"-tips Visa tips när bakgrunds- eller popup-knappen trycks på sidan för videodetaljer Spelare Beteende @@ -674,4 +674,9 @@ Kolla manuellt efter nya versioner Söker efter uppdateringar… Nya flödes objekt + Visa \"krascha spelaren\" + Rapportera spelarfel + Krascha spelaren + Visar ett kraschalternativ vid användning av spelaren + Rapporterar spelarfel i detalj i stället för att visa ett kortvarigt popup-meddelande (användbart för att diagnostisera problem) \ No newline at end of file diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml index f86ca288c..5c93dec4b 100644 --- a/app/src/main/res/values-te/strings.xml +++ b/app/src/main/res/values-te/strings.xml @@ -1,25 +1,25 @@ - ప్రారంభించడానికి శోధనను క్లిక్ - %1$s ప్రచురించబడింది + మొదలుపెట్టుటకు బూతద్దము గురుతుని తట్టండి. + %1$sన ప్రచురించబడింది ఇన్స్టాల్ రద్దు చేయి బ్రౌజర్ లో తెరవండి - షేర్ చేయండి + షేర్ డౌన్లోడ్ వెతుకు - సెట్టింగ్‌లు - అంటే నువ్వు అనేది: %1$s\? - తో పంచు - బాహ్యట ఆడియో ప్లేయర్ని ఉపయోగించండి + అమరికలు + మీ ఉద్దేశ్యం \"%1$s\"\? + పంచుకో + బాహ్య ఆడియో ప్లేయర్ని ఉపయోగించండి సభ్యత్వం సబ్ స్క్రైబ్ - అన్ సబ్స్క్రైబ్ చెసిరు + ఛానెల్ సభ్యత్వం తీసివేయబడినది సబ్ స్క్రైబ్ సాధ్యం కాలేదు సబ్ స్క్రైబ్ నవీకరించలేరు సభ్యత్వం కొత్తది ఏమిటి - వెనకవైపు + వెనుకగా పాపప్ వీడియో డౌన్లోడ్ మార్గం డౌన్లోడ్ చేసిన వీడియోలను నిల్వ చేయడానికి మార్గం @@ -28,26 +28,26 @@ ఆడియో కోసం డౌన్లోడ్ మార్గాన్ని నమోదు చేయండి ఆడియో ఫైల్లకు డౌన్లోడ్ మార్గాన్ని ఇవ్వండి కోడితో ప్లే చేయండి - కోరే అనువర్తనం కనుగొనబడలేదు. దీన్ని ఇన్స్టాల్ చేయండి + కోరే ఆప్ కనుగొనబడలేదు. దీన్ని ఇన్స్టాల్ చెయ్యాలా\? కోరే అనువర్తనం కనుగొనబడలేదు. దీన్ని ఇన్స్టాల్ చేయండి ఆడియో డిఫాల్ట్ ఆడియో ఫార్మాట్ థీమ్ ప్రకాశం - చరిత్ర - డౌన్లోడ్ - తదుపరి వీడియో మరియు ఇలాంటి వీడియో + చరిత్రను చూడండి + డౌన్‌లోడ్ + \'తదుపరి\' మరియు \'ఇలాంటి\' వీడియోలను చూపించు చిట్కాను అనుబంధించడానికి హోల్డ్ను చూపు Url మద్దతు లేదు డిఫాల్ట్ భాష ప్లేయర్ ప్రవర్తన వీడియో & ఆడియో - చరిత్ర + చరిత్ర మరియు కాష్ స్వరూపం వెనకవైపులో ఆడుతున్నారు పాపప్ రీతిలో ప్లే చేస్తోంది - కంటెంట్ + విషయము డౌన్ లోడ్ల డౌన్ లోడ్ లోపం నివేదిక @@ -62,17 +62,17 @@ కంటెంట్ అందుబాటులో లేదు డౌన్లోడ్ మెనుని సెటప్ చేయడం సాధ్యపడలేదు ఈ స్ట్రీమ్ని ప్లే చేయడం విఫలమైంది - ఆటగాడు లోపం నుండి పునరుద్ధరించడం + ప్లేయర్ లోపం నుండి పునరుద్ధరించబడుతున్నది క్షమించాలి, అది జరగకూడదు - ఇ-మెయిల్ ద్వారా నివేదన లోపం - క్షమించండి, కొన్ని లోపాలు సంభవించాయి + ఇ-మెయిల్ ద్వారా లోపాన్ని నివేదించుము + క్షమించండి, ఏదో తప్పు జరిగింది. నివేదిక - సమాచారం - ఏం జరిగింది - మీ వ్యాఖ్య(ఆంగ్లం లో) - వివరాలు + సమాచారం: + ఏం జరిగింది: + మీ వ్యాఖ్య(ఆంగ్లం లో): + వివరములు: వీడియో ప్రివ్యూ సూక్ష్మచిత్రం - Video preview thumbnail + వీడియోని ప్లే చేయండి, వ్యవధి: ఇష్టాలు మంది ఇష్టపడలేదు ఫలితాలు లేవు @@ -82,10 +82,10 @@ కె ఎం బి - చందాదారులు లేరు + సభ్యులు లేరు - %s సబ్స్క్రయిబ్ - %s సబ్స్క్రయిబలు + %s సభ్యుడు + %s సభ్యులు వీక్షణలు లేవు @@ -98,7 +98,7 @@ %s వీడియోలు ప్రారంభం - ఆపు + విరామం తొలగించు అలాగే ఫైలుపేరు @@ -112,7 +112,7 @@ డౌన్లోడ్ ఫైల్ పేర్లలో అనుమతించిన అక్షరాలు చెల్లని అక్షరాలు ఈ విలువతో భర్తీ చేయబడతాయి - ప్రత్యామ్నాయం పాత్ర + ప్రత్యామ్నాయ అక్షరం లెటర్స్ మరియు అంకెలు న్యూపిప్ గురించి మూడవ పార్టీ లైసెన్స్ @@ -120,9 +120,9 @@ లైసెన్సుల GitHub పై చూడండి న్యూపెయిప్స్ లైసెన్స్ - మీరు ఆలోచనలు ఉన్నాయా లేదో; అనువాదం, డిజైన్ మార్పులు, కోడ్ క్లీనింగ్ లేదా రియల్ భారీ కోడ్ మార్పులు-సహాయం ఎల్లప్పుడూ స్వాగతం. మరింత అది గెట్స్ మంచి జరుగుతుంది + మీకు ఆలోచనలు ఉన్నాయా; అనువాదం, డిజైన్ మార్పులు, కోడ్ శుభ్రపరచడం లేదా నిజమైన భారీ కోడ్ మార్పులు-సహాయం ఎల్లప్పుడూ స్వాగతం. ఎంత ఎక్కువ చేస్తే అంత మంచిది! లైసెన్స్ చదువు - కాంట్రిబ్యూషన్ + సహకరించటానికి చరిత్ర చరిత్ర మీరు ఈ అంశాన్ని శోధన చరిత్ర నుండి తొలగించాలనుకుంటున్నారా? @@ -138,11 +138,100 @@ వివరాలు ఆడియో సెట్టింగ్లు ఎన్క్యూలో పట్టుకోండి - మీదగార వీడియో కి కావాల్సిన ప్లేయర్ లేదు. VLC ప్లేయర్ ఇన్స్టాల్ చేసుకుంటారా\? - మీదగార వీడియో కి కావాల్సిన ప్లేయర్ లేదు (మీరు VLC ఇసన్తాల్ చేసుకోండి ) - "పాపప్ మోడ్ లో తెరవండి" + మీదగ్గర వీడియోకి కావాల్సిన ప్లేయర్ లేదు. VLC ప్లేయర్ని ఇన్స్టాల్ చేసుకుంటారా\? + మీదగ్గర వీడియోకి కావాల్సిన ప్లేయర్ లేదు (మీరు VLCని ఇన్స్టాల్ చేసుకోండి ). + పాపప్ మోడ్లో తెరవండి డిఫాల్ట్ పాపప్ స్పష్టత - ప్రసార ఫైల్ను డౌన్లోడ్ చేయండి + ప్రసార ఫైలుని డౌన్లోడ్ చేయండి బాహ్య వీడియో ప్లేయర్ని ఉపయోగించండి - కొన్ని రెసొల్యూషన్స్ లో ఆడియో తీసేస్తుంది + కొన్ని స్పష్టతల్లో ఆడియోను తొలగిస్తుంది + పూర్తి స్క్రీన్‌లో ప్రధాన ప్లేయర్‌ని ప్రారంభించండి + డీబగ్ చేయండి + ఏమిలేదు + నోటిఫికేషన్‌లో చూపబడిన వీడియో థంబ్‌నెయిల్‌ను 16:9 నుండి 1:1 కారక నిష్పత్తికి స్కేల్ చేయండి (వక్రీకరణలను ప్రవేశపెట్టవచ్చు) + పునరావృతం చేయండి + వీడియో \"వివరాలు:\"లో బ్యాక్‌గ్రౌండ్ లేదా పాప్‌అప్ బటన్‌ను నొక్కినప్పుడు చిట్కాను చూపు + URLని గుర్తించడం సాధ్యపడలేదు. మరొక యాప్‌తో తెరవాలా\? + నోటిఫికేషన్‌ను రంగులమయం చేయండి + స్థానిక శోధన సూచనలు + రిమోట్ శోధన సూచనలు + ఆటోప్లే + అంతరాయాలు (ఉదా. ఫోన్‌కాల్స్) తర్వాత ప్లే చేయడం కొనసాగించండి + మెటా సమాచారాన్ని చూపు + కోడి మీడియా సెంటర్ ద్వారా వీడియోను ప్లే చేయడానికి ఎంపికను ప్రదర్శించండి + కొన్ని పరికరాలు మాత్రమే 2K/4K వీడియోలను ప్లే చేయగలవు + వీక్షించినట్లు గుర్తుపెట్టుము + దీనితో తెరువుము + దీని కోసం ఫలితాలను చూపుతోంది: %s + డిఫాల్ట్ స్పష్టత + అధిక స్పష్టతను చూపుము + నలుపు + పాప్అప్ లక్షణాలను గుర్తుంచుకో + సూక్ష్మచిత్రాలను లోడ్ చేయండి + వ్యాఖ్యలను చూపించు + వ్యాఖ్యలను దాచడాన్ని ఆఫ్ చేయండి + %sలో మీకు నచ్చిన సందర్భాలను కనుగొనండి + పీర్‌ట్యూబ్ ఉదాహరణలు + మూడవ చర్య బటన్ + థంబ్‌నెయిల్‌లను లోడ్ చేయడం, డేటాను సేవ్ చేయడం మరియు మెమరీ వినియోగాన్ని నిరోధించడానికి ఆఫ్ చేయండి. మార్పులు ఇన్-మెమరీ మరియు ఆన్-డిస్క్ ఇమేజ్ కాష్ రెండింటినీ క్లియర్ చేస్తాయి + ఖచ్చితమైన శోధన తగ్గిన ఖచ్చితత్వంతో వేగంగా స్థానాలను పొందేందుకు ఆటగాడిని అనుమతిస్తుంది. 5, 15 లేదా 25 సెకన్ల పాటు కోరడం దీనితో పని చేయదు + వేగవంతమైన ఖచ్చితమైన శోధనను ఉపయోగించండి + జోడించండి + బుక్‌మార్క్ చేయబడిన వినోదజాబితాలు + ట్యాబ్‌ని ఎంచుకోండి + సభ్యత్వాన్ని తొలగించుము + సమాచారాన్ని చూపుము + సూక్ష్మచిత్రాన్ని 1:1 కారక నిష్పత్తికి స్కేల్ చేయండి + ఒక ప్లేయర్ నుండి మరొక ప్లేయర్‌కు మారడం వలన మీ క్యూను భర్తీ చేయవచ్చు + సంబంధిత స్ట్రీమ్‌ను జోడించడం ద్వారా (పునరావృతం కాని) ప్లేబ్యాక్ క్యూను ముగించడాన్ని కొనసాగించండి + దిగువన ఉన్న ప్రతి నోటిఫికేషన్ చర్యను దానిపై నొక్కడం ద్వారా సవరించండి. కుడివైపు ఉన్న చెక్‌బాక్స్‌లను ఉపయోగించడం ద్వారా కాంపాక్ట్ నోటిఫికేషన్‌లో చూపబడే వాటిలో మూడు వరకు ఎంచుకోండి + పాప్అప్ చివరి పరిమాణం మరియు స్థానాన్ని గుర్తుంచుకోండి + వీడియో వివరణ మరియు అదనపు సమాచారాన్ని దాచడాన్ని ఆఫ్ చేయండి + స్ట్రీమ్ సృష్టికర్త, స్ట్రీమ్ కంటెంట్ లేదా శోధన అభ్యర్థన గురించి అదనపు సమాచారంతో మెటా సమాచార పెట్టెలను దాచడానికి ఆఫ్ చేయండి + ప్లేయర్ ప్రకాశాన్ని నియంత్రించడానికి సంజ్ఞలను ఉపయోగించండి + శోధిస్తున్నప్పుడు చూపాల్సిన సూచనలను ఎంచుకోండి + చివరి ప్లేబ్యాక్ స్థానాన్ని పునరుద్ధరించండి + మీకు ఇష్టమైన పీర్‌ట్యూబ్ సందర్భాలను ఎంచుకోండి + వీక్షించిన వీడియోలను ట్రాక్ చేయండి + మినీ ప్లేయర్‌లో వీడియోలను ప్రారంభించవద్దు, ఆటో రొటేషన్ లాక్ చేయబడితే, నేరుగా పూర్తి స్క్రీన్ మోడ్‌కి మారండి. మీరు పూర్తి స్క్రీన్ నుండి నిష్క్రమించడం ద్వారా ఇప్పటికీ మినీ ప్లేయర్‌ని యాక్సెస్ చేయవచ్చు + సందర్భాన్ని జోడించండి + నవీకరణలు + HTTPS URLలకు మాత్రమే మద్దతు ఉంది + రెండవ చర్య బటన్ + నాల్గవ చర్య బటన్ + స్వల్పకాలిక టోస్ట్ సందేశాన్ని చూపించే బదులు పూర్తి వివరాలతో ప్లేయర్ లోపాలను నివేదిస్తుంది (సమస్యలను నిర్ధారించడానికి ఉపయోగపడుతుంది) + ప్లేయర్ క్రాష్ చేయండి + ప్లేయర్ లోపాలను నివేదించండి + మొదటి చర్య బటన్ + ఐదవ చర్య బటన్ + మీరు కాంపాక్ట్ నోటిఫికేషన్‌లో చూపడానికి గరిష్టంగా మూడు చర్యలను ఎంచుకోవచ్చు! + షఫుల్ చేయండి + బఫరింగ్ + డిఫాల్ట్ వీడియో ఫార్మాట్ + రాత్రి థీమ్ + చీకటి + ఫాస్ట్-ఫార్వర్డ్/-రివైండ్ సీక్ వ్యవధి + క్యూను క్లియర్ చేయడానికి ముందు నిర్ధారణ కోసం అడగండి + క్రియాశీల ప్లేయర్ క్యూ భర్తీ చేయబడుతుంది + వివరణను చూపు + చిత్రం కాష్ తుడిచివేయబడింది + కాష్ చేయబడిన మెటాడేటాను తుడిచివేయండి + కాష్ చేసిన వెబ్‌పేజీ డేటా మొత్తాన్ని తీసివేయండి + మెటాడేటా కాష్ తుడిచివేయబడింది + వాల్యూమ్ సంజ్ఞ నియంత్రణ + ప్లేయర్ వాల్యూమ్‌ను నియంత్రించడానికి సంజ్ఞలను ఉపయోగించండి + ప్రకాశం సంజ్ఞ నియంత్రణ + సూచనలను శోధించండి + శోధన చరిత్ర + శోధన ప్రశ్నలను స్థానికంగా నిల్వ చేయండి + ప్లేబ్యాక్ పునఃప్రారంభించండి + జాబితాలలో స్థానాలు + జాబితాలలో ప్లేబ్యాక్ స్థాన సూచికలను చూపు + డేటాను క్లియర్ చేయండి + ప్లే చేయడం కొనసాగించండి + డిఫాల్ట్ కంటెంట్ దేశం + ఉదాహరణ URLని నమోదు చేయండి + ఉదాహరణను ధృవీకరించడం సాధ్యపడలేదు + ఉదాహరణ ఇప్పటికే ఉంది + నోటిఫికేషన్ \ No newline at end of file diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index e0b3cd7d8..ebb0bccb1 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -115,7 +115,7 @@ Історія переглядів Відновлювати відтворення Продовжувати відтворення після переривань (напр. телефонних дзвінків) - Показати пораду «Утримуй, щоб додати» + Показувати підказку «Утримуйте, щоб додати в чергу» Типова країна вмісту Програвач Поведінка @@ -130,7 +130,7 @@ Сповіщення NewPipe Сповіщення для програвачів NewPipe на тлі й у вікні [Невідомо] - Перемкнути на тло + Перейти у фоновий режим Перемкнути у вікно Перемкнути на головну Імпортувати базу даних @@ -258,7 +258,7 @@ Примусове звітування про неможливість доставлення Rx-винятків, які відбуваються за межами фрагменту або діяльності життєвого циклу після усунення Викор. швидкий неточний пошук Неточний пошук дозволяє програвачеві рухатися позиціями швидше, проте з меншою точністю - Автододавання в чергу наступного запису + Автододавання в чергу наступної трансляції Продовжити при завершені (не повторюваної) черги, додавши повʼязаний запис Файл Такої теки не існує @@ -583,7 +583,7 @@ Коментарі Сповіщення Не розпізнано URL. Відкрити через іншу програму\? - Самододавання в чергу + Автоматична черга Показувати метадані Показувати описи Нічна тема diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 52ee9651c..eeb57dcf0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -99,9 +99,9 @@ Wipe cached metadata Remove all cached webpage data Metadata cache wiped - Auto-queue next stream + Auto-enqueue next stream Continue ending (non-repeating) playback queue by appending a related stream - Auto-queue + Auto-enqueuing Volume gesture control Use gestures to control player volume Brightness gesture control @@ -125,7 +125,7 @@ Start main player in fullscreen Do not start videos in the mini player, but turn to fullscreen mode directly, if auto rotation is locked. You can still access the mini player by exiting fullscreen Autoplay - Show \"Hold to append\" tip + Show \"Hold to enqueue\" tip Show tip when pressing the background or the popup button in video \"Details:\" Unsupported URL Could not recognize the URL. Open with another app? diff --git a/fastlane/metadata/android/de/changelogs/958.txt b/fastlane/metadata/android/de/changelogs/958.txt index 2fe07fd71..4b41f7d70 100644 --- a/fastlane/metadata/android/de/changelogs/958.txt +++ b/fastlane/metadata/android/de/changelogs/958.txt @@ -1,14 +1,15 @@ -Neu und verbessert: -• Einstellung, kein Vorschaubild auf dem Lockscreen anzuzeigen, wurde hinzugefügt -• Feeds durch Gesten aktualisieren -• Verbesserte Performance beim laden von lokalen Listen +Neu+verbessert +•Option Miniansicht Ausblenden auf Sperrbildschirm wieder hinzugefügt +•Ziehen zum Feed aktualisieren +•Verbesserte Leistung beim Abruf lokaler Listen -Behoben: -• Absturz beim Starten von NewPipe ohne Internetverbindung -• Absturz beim Wiederherstellen von NewPipe aus dem Arbeitsspeicher -• [YouTube] Lange Wiedergabelisten +Behoben +•Absturz, Start von NewPipe, nachdem es aus dem RAM entfernt wurde +•Absturz, Starten von NewPipe ohne Internetverbindung +•Einstellungen Helligkeits- und Lautstärkegesten +•[YT] Lange Wiedergabelisten -Anderes: -• Code Verbesserungen und mehrere interne Verbesserungen -• Bibliotheken wurden aktualisiert -• aktualisierte Übersetzungen +Sonstiges +•Codebereinigung, verschiedene interne Verbesserungen +•Aktualisierung Abhängigkeiten +•Aktualisierte Übersetzungen diff --git a/fastlane/metadata/android/he/changelogs/980.txt b/fastlane/metadata/android/he/changelogs/980.txt new file mode 100644 index 000000000..7b74d9af0 --- /dev/null +++ b/fastlane/metadata/android/he/changelogs/980.txt @@ -0,0 +1,13 @@ +חדש +• נוספה האפשרות „הוספה לרשימת נגינה” לתפריט השיתוף +• נוספה תמיכה ב־y2u.be וקישורים מקוצרים של PeerTube + +שיפורים +• פקדי מהירות הנגינה צומצמו +• ההזנה מדגישה מעתה פריטים חדשים +• האפשרות „הצגת פריטים שנצפו” בהזנה נשמרת מעתה + +תיקונים +• תוקן חילוץ הלייקים והלא לייקים ב־YouTube +• תוקנה נגינה חוזרת אוטומטית בחזרה מעבודה ברקע +קצרה היריעה מלהכיל diff --git a/fastlane/metadata/android/hu/changelogs/63.txt b/fastlane/metadata/android/hu/changelogs/63.txt new file mode 100644 index 000000000..e9b4b461c --- /dev/null +++ b/fastlane/metadata/android/hu/changelogs/63.txt @@ -0,0 +1,8 @@ +### Fejlesztések +- Beállítások importálása/exportálása #1333 +- Túlrajzolás csökkentése (teljesítménybeli javítás) #1371 +- Apró kódfejlesztések #1375 +- GDPR információk hozzáadása #1420 + +### Javítva +- Letöltés: A befejezetlen .giga fájlokból történő betöltés közbeni összeomlás javítása #1407 diff --git a/fastlane/metadata/android/hu/full_description.txt b/fastlane/metadata/android/hu/full_description.txt index c1cf87b83..df1f8cb77 100644 --- a/fastlane/metadata/android/hu/full_description.txt +++ b/fastlane/metadata/android/hu/full_description.txt @@ -1 +1 @@ -A NewPipe nem használ semmilyen Google vázkönyvtárat vagy a YouTube API-t. Csupán a weboldalt elemzi, hogy megszerezze a szükséges információt. Így ez az alkalmazás a Google Szolgáltatások nélkül futó ezközökön is használható. Emellett, a NewPipe használatához nincs szükséged YouTube fiókra, +A NewPipe nem használ semmilyen Google keretrendszer könyvtárat, sem a YouTube API-t. Csupán a weboldalt dolgozza fel, hogy kinyerje a szükséges információkat. Így ez az alkalmazás a Google Szolgáltatások nélkül futó eszközökön is használható. Továbbá a NewPipe használatához nincs szükség YouTube-fiókra sem. A NewPipe szabad és nyílt forráskódú szoftver. diff --git a/fastlane/metadata/android/pa/changelogs/63.txt b/fastlane/metadata/android/pa/changelogs/63.txt new file mode 100644 index 000000000..eacfe0cd7 --- /dev/null +++ b/fastlane/metadata/android/pa/changelogs/63.txt @@ -0,0 +1,8 @@ +### ਸੁਧਾਰ +- ਆਯਾਤ/ਨਿਰਯਾਤ ਸੈਟਿੰਗਾਂ #1333 +- ਓਵਰ ਡਰਾਅ ਘਟਾਇਆ ਗਿਆ (ਕਾਰਗੁਜ਼ਾਰੀ ਵਿੱਚ ਸੁਧਾਰ) #1371 +- ਨਿੱਕੇ ਕੋਡ ਸੁਧਾਰ #1375 +- ਜੀ.ਡੀ. ਪੀ.ਆਰ. ਬਾਰੇ ਸਾਰਾ ਕੁਝ ਜੋੜਿਆ #1420 + +### ਸਹੀ ਕੀਤਾ ਗਿਆ +- ਡਾਊਨਲੋਡਰ: .giga ਨਾਮਕ ਫਾਈਲਾਂ ਤੋਂ ਅਧੂਰੇ ਡਾਊਨਲੋਡ ਲੋਡ ਕਰਨ ਤੇ ਬੰਦ ਹੋਣਾ ਸਹੀ ਕੀਤਾ ਗਿਆ diff --git a/fastlane/metadata/android/pa/changelogs/64.txt b/fastlane/metadata/android/pa/changelogs/64.txt new file mode 100644 index 000000000..087c5886a --- /dev/null +++ b/fastlane/metadata/android/pa/changelogs/64.txt @@ -0,0 +1,8 @@ +### ਸੁਧਾਰ +- ਮੋਬਾਈਲ ਡਾਟਾ ਦੀ ਵਰਤੋਂ ਕਰਨ ਤੇ ਵੀਡੀਓ ਗੁਣਤਾ ਨੂੰ ਸੀਮਤ ਕਰਨ ਦੀ ਸਮਰੱਥਾ ਨੂੰ ਜੋੜਿਆ। #1339 +- ਸੈਸ਼ਨ ਲਈ ਚਮਕ ਯਾਦ ਰੱਖੋ #1442 +- ਕਮਜ਼ੋਰ ਸੀ ਪੀ ਯੂ #1431 ਲਈ ਡਾਊਨਲੋਡ ਪ੍ਰਦਰਸ਼ਨ ਵਿੱਚ ਸੁਧਾਰ ਕੀਤਾ +- ਮੀਡੀਆ ਸੈਸ਼ਨ #1433 ਲਈ (ਕੰਮ ਕਰਨਾ) ਸਮਰਥਨ ਸ਼ਾਮਲ ਕਰੋ + +### ਸਹੀ ਕੀਤਾ ਗਿਆ +- ਸ਼ੁਰੂਆਤੀ ਡਾਊਨਲੋਡਾਂ 'ਤੇ ਕਰੈਸ਼ ਨੂੰ ਠੀਕ ਕੀਤਾ (ਰਿਲੀਜ਼ ਬਿਲਡਾਂ ਲਈ ਹੁਣ ਇਹ ਫਿਕਸ ਉਪਲਬਧ ਹੈ) #1441 diff --git a/fastlane/metadata/android/pl/changelogs/980.txt b/fastlane/metadata/android/pl/changelogs/980.txt new file mode 100644 index 000000000..29e051247 --- /dev/null +++ b/fastlane/metadata/android/pl/changelogs/980.txt @@ -0,0 +1,13 @@ +Nowe +• Dodano opcję „Dodaj do playlisty” do menu kontekstowego +• Dodano obsługę krótkich linków dla y2u.be and PeerTube + +Poprawione +• Bardziej kompaktowe sterowanie prędkością odtwarzania +• Kanał wyróżnia teraz nowe pozycje +• Opcja „Pokaż obejrzane pozycje” w kanale jest teraz zapisywana + +Naprawione +• Naprawiono wyciąganie polubień i łapek w dół z YouTube'a +• Naprawiono automatyczne odtwarzanie po powracaniu z tła +I wiele więcej diff --git a/fastlane/metadata/android/ta/changelogs/63.txt b/fastlane/metadata/android/ta/changelogs/63.txt new file mode 100644 index 000000000..6a90173ef --- /dev/null +++ b/fastlane/metadata/android/ta/changelogs/63.txt @@ -0,0 +1,8 @@ +### மேம்பாடுகள் +- இறக்குமதி/ஏற்றுமதி அமைப்புகள் #1333 +- ஓவர் டிராவைக் குறைக்கவும் (செயல்திறன் மேம்பாடு) #1371 +- சிறிய குறியீடு மேம்பாடுகள் #1375 +- GDPR #1420 பற்றிய அனைத்தையும் சேர்க்கவும் + +### சரி செய்யப்பட்டது +- டவுன்லோடர்: .giga கோப்புகள் #1407 இலிருந்து முடிக்கப்படாத பதிவிறக்கங்களை ஏற்றுவதில் ஏற்படும் செயலிழப்பை சரிசெய்யவும் diff --git a/fastlane/metadata/android/ta/changelogs/64.txt b/fastlane/metadata/android/ta/changelogs/64.txt new file mode 100644 index 000000000..04336a3cd --- /dev/null +++ b/fastlane/metadata/android/ta/changelogs/64.txt @@ -0,0 +1,8 @@ +### மேம்பாடுகள் +- மொபைல் டேட்டாவைப் பயன்படுத்தினால் வீடியோ தரத்தைக் கட்டுப்படுத்தும் திறன் சேர்க்கப்பட்டது. #1339 +- அமர்வு #1442 க்கான பிரகாசத்தை நினைவில் கொள்க +- பலவீனமான CPUகளுக்கான பதிவிறக்க செயல்திறனை மேம்படுத்தவும் #1431 +- மீடியா அமர்வு #1433க்கு (வேலை செய்யும்) ஆதரவைச் சேர்க்கவும் + +### சரி +- பதிவிறக்கங்களைத் திறப்பதில் ஏற்படும் செயலிழப்பைச் சரிசெய்தல் (வெளியீட்டு உருவாக்கங்களுக்கு இப்போது சரிசெய்தல் கிடைக்கிறது) #1441 diff --git a/fastlane/metadata/android/ta/full_description.txt b/fastlane/metadata/android/ta/full_description.txt new file mode 100644 index 000000000..12e0e08ef --- /dev/null +++ b/fastlane/metadata/android/ta/full_description.txt @@ -0,0 +1 @@ +NewPipe எந்த Google கட்டமைப்பு நூலகங்களையும் அல்லது YouTube API ஐயும் பயன்படுத்துவதில்லை. இணையத்தளத்திற்குத் தேவையான தகவல்களைப் பெறுவதற்காக மட்டுமே இது அலசுகிறது. எனவே Google சேவைகள் நிறுவப்படாத சாதனங்களில் இந்தப் பயன்பாட்டைப் பயன்படுத்தலாம். மேலும், NewPipe ஐப் பயன்படுத்த உங்களுக்கு YouTube கணக்கு தேவையில்லை, அது FLOSS ஆகும். diff --git a/fastlane/metadata/android/te/changelogs/63.txt b/fastlane/metadata/android/te/changelogs/63.txt new file mode 100644 index 000000000..d78af57ac --- /dev/null +++ b/fastlane/metadata/android/te/changelogs/63.txt @@ -0,0 +1,8 @@ +### మెరుగుదలలు +- దిగుమతి/ఎగుమతి సెట్టింగ్‌లు #1333 +- ఓవర్‌డ్రాను తగ్గించండి (పనితీరు మెరుగుదల) #1371 +- చిన్న కోడ్ మెరుగుదలలు #1375 +- GDPR #1420 గురించి అన్నింటినీ జోడించండి + +### పరిష్కరించబడినవి +- డౌన్‌లోడర్: .giga ఫైల్స్ #1407 నుండి అసంపూర్తి డౌన్‌లోడ్‌లను లోడ్ చేయడంలో క్రాష్‌ని పరిష్కరించండి diff --git a/fastlane/metadata/android/te/changelogs/64.txt b/fastlane/metadata/android/te/changelogs/64.txt new file mode 100644 index 000000000..b704b531a --- /dev/null +++ b/fastlane/metadata/android/te/changelogs/64.txt @@ -0,0 +1,8 @@ +### మెరుగులు +- మొబైల్ డేటాను ఉపయోగిస్తుంటే వీడియో నాణ్యతను పరిమితం చేసే సామర్థ్యం జోడించబడింది. #1339 +- సెషన్ #1442 కోసం ప్రకాశాన్ని గుర్తుంచుకోండి +- బలహీనమైన CPUల కోసం డౌన్‌లోడ్ పనితీరును మెరుగుపరచండి #1431 +- మీడియా సెషన్ #1433 కోసం (పని) మద్దతును జోడించండి + +### పరిష్కరించండి +- డౌన్‌లోడ్‌లను తెరవడంపై క్రాష్‌ని పరిష్కరించండి (విడుదల బిల్డ్‌ల కోసం ఇప్పుడు అందుబాటులో ఉంది) #1441 diff --git a/fastlane/metadata/android/te/full_description.txt b/fastlane/metadata/android/te/full_description.txt new file mode 100644 index 000000000..64a04af4b --- /dev/null +++ b/fastlane/metadata/android/te/full_description.txt @@ -0,0 +1 @@ +NewPipe ఏ Google ఫ్రేమ్‌వర్క్ లైబ్రరీలను లేదా YouTube APIని ఉపయోగించదు. ఇది వెబ్‌సైట్‌కు అవసరమైన సమాచారాన్ని పొందడం కోసం మాత్రమే అన్వయిస్తుంది. అందువల్ల ఈ యాప్‌ను Google సేవలు ఇన్‌స్టాల్ చేయని పరికరాలలో ఉపయోగించవచ్చు. అలాగే, NewPipeని ఉపయోగించడానికి మీకు YouTube ఖాతా అవసరం లేదు మరియు ఇది FLOSS. diff --git a/fastlane/metadata/android/te/short_description.txt b/fastlane/metadata/android/te/short_description.txt new file mode 100644 index 000000000..62c769a30 --- /dev/null +++ b/fastlane/metadata/android/te/short_description.txt @@ -0,0 +1 @@ +ఆండ్రాయిడ్ కోసం ఉచిత తేలికపాటి యూట్యూబ్ ఫ్రంటెండ్. diff --git a/fastlane/metadata/android/uk/changelogs/980.txt b/fastlane/metadata/android/uk/changelogs/980.txt new file mode 100644 index 000000000..8cd6d0bb2 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/980.txt @@ -0,0 +1,13 @@ +Новий +• Додано опцію «Додати в добірку» до меню спільного доступу +• Додано підтримку коротких посилань y2u.be та PeerTube + +Удосконалено +• Елементи керування швидкістю відтворення стали компактнішими +• У стрічці відтепер виділяються нові елементи +• Опція «Показати переглянуті елементи» у стрічці тепер збережена + +Виправлено +• Виправлено підтягування вподобайок YouTube +• Виправлено автовідтворення після повернення з фонового режиму +І багато іншого diff --git a/fastlane/metadata/android/zh-Hans/changelogs/980.txt b/fastlane/metadata/android/zh-Hans/changelogs/980.txt new file mode 100644 index 000000000..7215efe42 --- /dev/null +++ b/fastlane/metadata/android/zh-Hans/changelogs/980.txt @@ -0,0 +1,13 @@ +新增 +- 增加 在共享菜单中新增 "添加到播放列表 "选项 +- 增加 对y2u.be和PeerTube短链接的支持 + +改进 +- 播放速度控制更加紧凑 +- Feed突出显示新项目 +- 保存feed中的 "显示观看过的项目 "选项 + +修复 +- 修复 YouTube 顶与踩 计数 的解析 +- 修复 从后台返回后的自动重放 +以及更多 From 7d6688f4976d1c998938843f5c29d5db8c0ea7fc Mon Sep 17 00:00:00 2001 From: Stypox Date: Wed, 8 Dec 2021 14:02:16 +0100 Subject: [PATCH 26/49] Add DatabaseMocker to mock NewPipeDatabase --- .../playlist/LocalPlaylistManagerTest.kt | 13 ++------ .../schabi/newpipe/testUtil/TestDatabase.kt | 32 +++++++++++++++++++ 2 files changed, 35 insertions(+), 10 deletions(-) create mode 100644 app/src/androidTest/java/org/schabi/newpipe/testUtil/TestDatabase.kt diff --git a/app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt b/app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt index 0a00b0443..249492d8f 100644 --- a/app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt +++ b/app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt @@ -1,7 +1,5 @@ package org.schabi.newpipe.local.playlist -import androidx.room.Room -import androidx.test.core.app.ApplicationProvider import org.junit.After import org.junit.Before import org.junit.Rule @@ -10,6 +8,7 @@ import org.junit.rules.Timeout import org.schabi.newpipe.database.AppDatabase import org.schabi.newpipe.database.stream.model.StreamEntity import org.schabi.newpipe.extractor.stream.StreamType +import org.schabi.newpipe.testUtil.TestDatabase import org.schabi.newpipe.testUtil.TrampolineSchedulerRule import java.util.concurrent.TimeUnit @@ -22,17 +21,11 @@ class LocalPlaylistManagerTest { val trampolineScheduler = TrampolineSchedulerRule() @get:Rule - val timeout = Timeout(10, TimeUnit.SECONDS) + val timeout = Timeout(1, TimeUnit.SECONDS) @Before fun setup() { - database = Room.inMemoryDatabaseBuilder( - ApplicationProvider.getApplicationContext(), - AppDatabase::class.java - ) - .allowMainThreadQueries() - .build() - + database = TestDatabase.createReplacingNewPipeDatabase() manager = LocalPlaylistManager(database) } diff --git a/app/src/androidTest/java/org/schabi/newpipe/testUtil/TestDatabase.kt b/app/src/androidTest/java/org/schabi/newpipe/testUtil/TestDatabase.kt new file mode 100644 index 000000000..8b1a261be --- /dev/null +++ b/app/src/androidTest/java/org/schabi/newpipe/testUtil/TestDatabase.kt @@ -0,0 +1,32 @@ +package org.schabi.newpipe.testUtil + +import androidx.room.Room +import androidx.test.core.app.ApplicationProvider +import org.junit.Assert.assertSame +import org.schabi.newpipe.NewPipeDatabase +import org.schabi.newpipe.database.AppDatabase + +class TestDatabase { + companion object { + fun createReplacingNewPipeDatabase(): AppDatabase { + val database = Room.inMemoryDatabaseBuilder( + ApplicationProvider.getApplicationContext(), + AppDatabase::class.java + ) + .allowMainThreadQueries() + .build() + + val databaseField = NewPipeDatabase::class.java.getDeclaredField("databaseInstance") + databaseField.isAccessible = true + databaseField.set(NewPipeDatabase::class, database) + + assertSame( + "Mocking database failed!", + database, + NewPipeDatabase.getInstance(ApplicationProvider.getApplicationContext()) + ) + + return database + } + } +} From 2963cd5c6e167640f790ceafafee9f4312fa0773 Mon Sep 17 00:00:00 2001 From: Stypox Date: Wed, 8 Dec 2021 14:12:09 +0100 Subject: [PATCH 27/49] Add HistoryRecordManagerTest --- .../local/history/HistoryRecordManagerTest.kt | 153 ++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 app/src/androidTest/java/org/schabi/newpipe/local/history/HistoryRecordManagerTest.kt diff --git a/app/src/androidTest/java/org/schabi/newpipe/local/history/HistoryRecordManagerTest.kt b/app/src/androidTest/java/org/schabi/newpipe/local/history/HistoryRecordManagerTest.kt new file mode 100644 index 000000000..3f3a038d8 --- /dev/null +++ b/app/src/androidTest/java/org/schabi/newpipe/local/history/HistoryRecordManagerTest.kt @@ -0,0 +1,153 @@ +package org.schabi.newpipe.local.history + +import androidx.test.core.app.ApplicationProvider +import org.junit.After +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.rules.Timeout +import org.schabi.newpipe.database.AppDatabase +import org.schabi.newpipe.database.history.model.SearchHistoryEntry +import org.schabi.newpipe.testUtil.TestDatabase +import org.schabi.newpipe.testUtil.TrampolineSchedulerRule +import java.time.OffsetDateTime +import java.util.concurrent.TimeUnit + +class HistoryRecordManagerTest { + + private lateinit var manager: HistoryRecordManager + private lateinit var database: AppDatabase + + @get:Rule + val trampolineScheduler = TrampolineSchedulerRule() + + @get:Rule + val timeout = Timeout(1, TimeUnit.SECONDS) + + @Before + fun setup() { + database = TestDatabase.createReplacingNewPipeDatabase() + manager = HistoryRecordManager(ApplicationProvider.getApplicationContext()) + } + + @After + fun cleanUp() { + database.close() + } + + @Test + fun onSearched() { + manager.onSearched(0, "Hello").test().await().assertValue(1) + + // For some reason the Flowable returned by getAll() never completes, so we can't assert + // that the number of Lists it returns is exactly 1, we can only check if the first List is + // correct. Why on earth has a Flowable been used instead of a Single for getAll()?!? + val entities = database.searchHistoryDAO().all.blockingFirst() + assertEquals(1, entities.size) + assertEquals(1, entities[0].id) + assertEquals(0, entities[0].serviceId) + assertEquals("Hello", entities[0].search) + } + + @Test + fun deleteSearchHistory() { + val entries = listOf( + SearchHistoryEntry(OffsetDateTime.now(), 0, "A"), + SearchHistoryEntry(OffsetDateTime.now(), 2, "A"), + SearchHistoryEntry(OffsetDateTime.now(), 1, "B"), + SearchHistoryEntry(OffsetDateTime.now(), 0, "B"), + ) + + // make sure all 4 were inserted + database.searchHistoryDAO().insertAll(entries) + assertEquals(entries.size, database.searchHistoryDAO().all.blockingFirst().size) + + // try to delete only "A" entries, "B" entries should be untouched + manager.deleteSearchHistory("A").test().await().assertValue(2) + val entities = database.searchHistoryDAO().all.blockingFirst() + assertEquals(2, entities.size) + assertTrue(entries[2].hasEqualValues(entities[0])) + assertTrue(entries[3].hasEqualValues(entities[1])) + + // assert that nothing happens if we delete a search query that does exist in the db + manager.deleteSearchHistory("A").test().await().assertValue(0) + val entities2 = database.searchHistoryDAO().all.blockingFirst() + assertEquals(2, entities2.size) + assertTrue(entries[2].hasEqualValues(entities2[0])) + assertTrue(entries[3].hasEqualValues(entities2[1])) + + // delete all remaining entries + manager.deleteSearchHistory("B").test().await().assertValue(2) + assertEquals(0, database.searchHistoryDAO().all.blockingFirst().size) + } + + @Test + fun deleteCompleteSearchHistory() { + val entries = listOf( + SearchHistoryEntry(OffsetDateTime.now(), 1, "A"), + SearchHistoryEntry(OffsetDateTime.now(), 2, "B"), + SearchHistoryEntry(OffsetDateTime.now(), 0, "C"), + ) + + // make sure all 3 were inserted + database.searchHistoryDAO().insertAll(entries) + assertEquals(entries.size, database.searchHistoryDAO().all.blockingFirst().size) + + // should remove everything + manager.deleteCompleteSearchHistory().test().await().assertValue(entries.size) + assertEquals(0, database.searchHistoryDAO().all.blockingFirst().size) + } + + @Test + fun getRelatedSearches_emptyQuery() { + // make sure all entries were inserted + database.searchHistoryDAO().insertAll(RELATED_SEARCHES_ENTRIES) + assertEquals( + RELATED_SEARCHES_ENTRIES.size, + database.searchHistoryDAO().all.blockingFirst().size + ) + + // make sure correct number of searches is returned and in correct order + val searches = manager.getRelatedSearches("", 6, 4).blockingFirst() + assertEquals(4, searches.size) + assertEquals(RELATED_SEARCHES_ENTRIES[6].search, searches[0]) // A (even if in two places) + assertEquals(RELATED_SEARCHES_ENTRIES[4].search, searches[1]) // B + assertEquals(RELATED_SEARCHES_ENTRIES[5].search, searches[2]) // AA + assertEquals(RELATED_SEARCHES_ENTRIES[2].search, searches[3]) // BA + } + + @Test + fun getRelatedSearched_nonEmptyQuery() { + // make sure all entries were inserted + database.searchHistoryDAO().insertAll(RELATED_SEARCHES_ENTRIES) + assertEquals( + RELATED_SEARCHES_ENTRIES.size, + database.searchHistoryDAO().all.blockingFirst().size + ) + + // make sure correct number of searches is returned and in correct order + val searches = manager.getRelatedSearches("A", 3, 5).blockingFirst() + assertEquals(3, searches.size) + assertEquals(RELATED_SEARCHES_ENTRIES[6].search, searches[0]) // A (even if in two places) + assertEquals(RELATED_SEARCHES_ENTRIES[5].search, searches[1]) // AA + assertEquals(RELATED_SEARCHES_ENTRIES[1].search, searches[2]) // BA + + // also make sure that the string comparison is case insensitive + val searches2 = manager.getRelatedSearches("a", 3, 5).blockingFirst() + assertEquals(searches, searches2) + } + + companion object { + val RELATED_SEARCHES_ENTRIES = listOf( + SearchHistoryEntry(OffsetDateTime.now().minusSeconds(7), 2, "AC"), + SearchHistoryEntry(OffsetDateTime.now().minusSeconds(6), 0, "ABC"), + SearchHistoryEntry(OffsetDateTime.now().minusSeconds(5), 1, "BA"), + SearchHistoryEntry(OffsetDateTime.now().minusSeconds(4), 3, "A"), + SearchHistoryEntry(OffsetDateTime.now().minusSeconds(2), 0, "B"), + SearchHistoryEntry(OffsetDateTime.now().minusSeconds(3), 2, "AA"), + SearchHistoryEntry(OffsetDateTime.now().minusSeconds(1), 1, "A"), + ) + } +} From 156bbad5b5a2c263616f5d26d4db3b184c5356e2 Mon Sep 17 00:00:00 2001 From: TacoTheDank Date: Sun, 12 Dec 2021 20:03:42 -0500 Subject: [PATCH 28/49] Update Gradle --- gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 269 ++++++++++++++--------- 2 files changed, 161 insertions(+), 112 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a3bc6ec0f..0d8da6971 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-all.zip -distributionSha256Sum=9bb8bc05f562f2d42bdf1ba8db62f6b6fa1c3bf6c392228802cc7cb0578fe7e0 +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-all.zip +distributionSha256Sum=b75392c5625a88bccd58a574552a5a323edca82dab5942d2d41097f809c6bcce zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 744e882ed..c53aefaa5 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,101 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions $var, ${var}, ${var:-default}, ${var+SET}, +# ${var#prefix}, ${var%suffix}, and $( cmd ); +# * compound commands having a testable exit status, especially case; +# * various built-in commands including command, set, and ulimit. +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MSYS* | MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=`expr $i + 1` - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" From a924f819a930f6728fd4a8b93c9cdfa11ab57783 Mon Sep 17 00:00:00 2001 From: TacoTheDank Date: Sun, 12 Dec 2021 21:26:59 -0500 Subject: [PATCH 29/49] Update a bunch of libraries --- app/build.gradle | 20 +++++++++----------- build.gradle | 2 +- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 07c34281d..0c511a2b3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,13 +105,13 @@ ext { icepickVersion = '3.2.0' exoPlayerVersion = '2.14.2' - googleAutoServiceVersion = '1.0' + googleAutoServiceVersion = '1.0.1' groupieVersion = '2.10.0' markwonVersion = '4.6.2' leakCanaryVersion = '2.5' stethoVersion = '1.6.0' - mockitoVersion = '3.6.0' + mockitoVersion = '4.0.0' } configurations { @@ -200,7 +200,7 @@ dependencies { /** AndroidX **/ implementation 'androidx.appcompat:appcompat:1.3.1' implementation 'androidx.cardview:cardview:1.0.0' - implementation 'androidx.constraintlayout:constraintlayout:2.0.4' + implementation 'androidx.constraintlayout:constraintlayout:2.1.2' implementation 'androidx.core:core-ktx:1.6.0' implementation 'androidx.documentfile:documentfile:1.0.1' implementation 'androidx.fragment:fragment-ktx:1.3.6' @@ -219,7 +219,7 @@ dependencies { // 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' + implementation 'com.google.android.material:material:1.4.0' /** Third-party libraries **/ // Instance state boilerplate elimination @@ -227,7 +227,7 @@ dependencies { kapt "frankiesardo:icepick-processor:${icepickVersion}" // HTML parser - implementation "org.jsoup:jsoup:1.13.1" + implementation "org.jsoup:jsoup:1.14.3" // HTTP client //noinspection GradleDependency --> do not update okhttp to keep supporting Android 4.4 users @@ -265,13 +265,13 @@ dependencies { implementation 'com.jakewharton:process-phoenix:2.1.2' // Reactive extensions for Java VM - implementation "io.reactivex.rxjava3:rxjava:3.0.7" + implementation "io.reactivex.rxjava3:rxjava:3.0.13" implementation "io.reactivex.rxjava3:rxandroid:3.0.0" // RxJava binding APIs for Android UI widgets implementation "com.jakewharton.rxbinding4:rxbinding:4.0.0" // Date and time formatting - implementation "org.ocpsoft.prettytime:prettytime:5.0.1.Final" + implementation "org.ocpsoft.prettytime:prettytime:5.0.2.Final" /** Debugging **/ // Memory leak detection @@ -287,11 +287,9 @@ dependencies { testImplementation "org.mockito:mockito-core:${mockitoVersion}" testImplementation "org.mockito:mockito-inline:${mockitoVersion}" - androidTestImplementation "androidx.test.ext:junit:1.1.2" + androidTestImplementation "androidx.test.ext:junit:1.1.3" + androidTestImplementation "androidx.test:runner:1.4.0" androidTestImplementation "androidx.room:room-testing:${androidxRoomVersion}" - androidTestImplementation "androidx.test.espresso:espresso-core:3.3.0", { - exclude module: 'support-annotations' - } } static String getGitWorkingBranch() { diff --git a/build.gradle b/build.gradle index 145515c1e..f7717a4ff 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.0.3' + classpath 'com.android.tools.build:gradle:7.0.4' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong From e06342eacfe7816e6baf5e894401e42bca427131 Mon Sep 17 00:00:00 2001 From: XiangRongLin <41164160+XiangRongLin@users.noreply.github.com> Date: Sun, 19 Dec 2021 12:18:37 +0100 Subject: [PATCH 30/49] Readd sonar CI job --- .github/workflows/ci.yml | 46 ++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b87219f4f..c0ca24abb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -74,29 +74,29 @@ jobs: emulator-build: 7425822 script: ./gradlew connectedCheck -# sonar: -# runs-on: ubuntu-latest -# steps: -# - uses: actions/checkout@v2 -# with: -# fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + sonar: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis -# - name: Set up JDK 11 -# uses: actions/setup-java@v2 -# with: -# java-version: 11 # Sonar requires JDK 11 -# distribution: "temurin" -# cache: 'gradle' + - name: Set up JDK 11 + uses: actions/setup-java@v2 + with: + java-version: 11 # Sonar requires JDK 11 + distribution: "temurin" + cache: 'gradle' -# - name: Cache SonarCloud packages -# uses: actions/cache@v2 -# with: -# path: ~/.sonar/cache -# key: ${{ runner.os }}-sonar -# restore-keys: ${{ runner.os }}-sonar + - name: Cache SonarCloud packages + uses: actions/cache@v2 + with: + path: ~/.sonar/cache + key: ${{ runner.os }}-sonar + restore-keys: ${{ runner.os }}-sonar -# - name: Build and analyze -# env: -# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any -# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} -# run: ./gradlew build sonarqube --info + - name: Build and analyze + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: ./gradlew build sonarqube --info From eea2768633883074aaecac0d4b078d96cc47eeb2 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sun, 19 Dec 2021 20:16:10 +0100 Subject: [PATCH 31/49] Removed/Reverted MediaParser support (Android 11+) due to bugs --- .../player/helper/PlayerDataSource.java | 51 +++---------------- 1 file changed, 8 insertions(+), 43 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 b7584151d..708b72ff2 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,18 +1,14 @@ 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; @@ -46,17 +42,10 @@ public class PlayerDataSource { } 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) { - factory.setExtractorFactory(MediaParserHlsMediaChunkExtractor.FACTORY); - } - - return factory; + return new HlsMediaSource.Factory(cachelessDataSourceFactory) + .setAllowChunklessPreparation(true) + .setLoadErrorHandlingPolicy( + new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)); } public DashMediaSource.Factory getLiveDashMediaSourceFactory() { @@ -71,26 +60,11 @@ public class PlayerDataSource { 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() { - 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); + return new HlsMediaSource.Factory(cacheDataSourceFactory); } public DashMediaSource.Factory getDashMediaSourceFactory() { @@ -101,18 +75,9 @@ public class PlayerDataSource { } public ProgressiveMediaSource.Factory getExtractorMediaSourceFactory() { - final ProgressiveMediaSource.Factory factory; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - factory = new ProgressiveMediaSource.Factory( - cacheDataSourceFactory, - MediaParserExtractorAdapter.FACTORY - ); - } else { - factory = new ProgressiveMediaSource.Factory(cacheDataSourceFactory); - } - - return factory.setLoadErrorHandlingPolicy( - new DefaultLoadErrorHandlingPolicy(EXTRACTOR_MINIMUM_RETRY)); + return new ProgressiveMediaSource.Factory(cacheDataSourceFactory) + .setLoadErrorHandlingPolicy( + new DefaultLoadErrorHandlingPolicy(EXTRACTOR_MINIMUM_RETRY)); } public SingleSampleMediaSource.Factory getSampleMediaSourceFactory() { From 361760be0ac4304038457ca51aa135aa4bf6acaf Mon Sep 17 00:00:00 2001 From: Jaspann Date: Sun, 19 Dec 2021 20:33:55 -0500 Subject: [PATCH 32/49] Allows multilingual support in hashtags --- .../newpipe/util/external_communication/TextLinkifier.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/external_communication/TextLinkifier.java b/app/src/main/java/org/schabi/newpipe/util/external_communication/TextLinkifier.java index f435653b5..92bdf879d 100644 --- a/app/src/main/java/org/schabi/newpipe/util/external_communication/TextLinkifier.java +++ b/app/src/main/java/org/schabi/newpipe/util/external_communication/TextLinkifier.java @@ -33,7 +33,8 @@ import static org.schabi.newpipe.util.external_communication.InternalUrlsHandler public final class TextLinkifier { public static final String TAG = TextLinkifier.class.getSimpleName(); - private static final Pattern HASHTAGS_PATTERN = Pattern.compile("(#[A-Za-z0-9_]+)"); + private static final Pattern HASHTAGS_PATTERN = + Pattern.compile("(#[A-Za-z0-9_\\u0080-\\uFFFF]+)"); private TextLinkifier() { } From a274baf5cda538e03b9089752ba3dd936971ec64 Mon Sep 17 00:00:00 2001 From: Jaspann Date: Mon, 20 Dec 2021 14:13:40 -0500 Subject: [PATCH 33/49] Adds comment to HASHTAGS_PATTERN --- .../newpipe/util/external_communication/TextLinkifier.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/external_communication/TextLinkifier.java b/app/src/main/java/org/schabi/newpipe/util/external_communication/TextLinkifier.java index 92bdf879d..8b8eb265b 100644 --- a/app/src/main/java/org/schabi/newpipe/util/external_communication/TextLinkifier.java +++ b/app/src/main/java/org/schabi/newpipe/util/external_communication/TextLinkifier.java @@ -33,8 +33,9 @@ import static org.schabi.newpipe.util.external_communication.InternalUrlsHandler public final class TextLinkifier { public static final String TAG = TextLinkifier.class.getSimpleName(); + // Looks for hashtags with characters from any language (\p{L}), numbers, or underscores private static final Pattern HASHTAGS_PATTERN = - Pattern.compile("(#[A-Za-z0-9_\\u0080-\\uFFFF]+)"); + Pattern.compile("(#[\\p{L}0-9_]+)"); private TextLinkifier() { } From a163d5461d20f722cc21a9b47180bb74b10a012e Mon Sep 17 00:00:00 2001 From: TobiGr Date: Tue, 21 Dec 2021 00:18:58 +0100 Subject: [PATCH 34/49] Make PlayerHolder.bound private --- .../newpipe/fragments/detail/VideoDetailFragment.java | 4 ++-- .../java/org/schabi/newpipe/player/helper/PlayerHolder.java | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) 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 6a956c6dc..a5e590ba0 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 @@ -685,7 +685,7 @@ public final class VideoDetailFragment }); setupBottomPlayer(); - if (!playerHolder.bound) { + if (!playerHolder.isBound()) { setHeightThumbnail(); } else { playerHolder.startService(false, this); @@ -1434,7 +1434,7 @@ public final class VideoDetailFragment bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); } // Rebound to the service if it was closed via notification or mini player - if (!playerHolder.bound) { + if (!playerHolder.isBound()) { playerHolder.startService( false, VideoDetailFragment.this); } diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java index 46239cab1..3d960ae90 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java @@ -41,7 +41,7 @@ public final class PlayerHolder { private PlayerServiceExtendedEventListener listener; private final PlayerServiceConnection serviceConnection = new PlayerServiceConnection(); - public boolean bound; + private boolean bound; private MainPlayer playerService; private Player player; @@ -70,6 +70,10 @@ public final class PlayerHolder { return player != null; } + public boolean isBound() { + return bound; + } + public int getQueueSize() { return isPlayerOpen() ? player.getPlayQueue().size() : 0; } From d71af9a625db22a6e8edc8b9c78e01d5aa7d0ff0 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Tue, 21 Dec 2021 20:53:17 +0100 Subject: [PATCH 35/49] Introduce constants for some Strings that indicate no data in Tab class --- .../org/schabi/newpipe/settings/tabs/Tab.java | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/tabs/Tab.java b/app/src/main/java/org/schabi/newpipe/settings/tabs/Tab.java index eac5ce311..aa03bbfa6 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/tabs/Tab.java +++ b/app/src/main/java/org/schabi/newpipe/settings/tabs/Tab.java @@ -36,6 +36,10 @@ import java.util.Objects; public abstract class Tab { private static final String JSON_TAB_ID_KEY = "tab_id"; + private static final String NO_NAME = ""; + private static final String NO_ID = ""; + private static final String NO_URL = ""; + Tab() { } @@ -185,7 +189,9 @@ public abstract class Tab { @Override public String getTabName(final Context context) { - return "NewPipe"; //context.getString(R.string.blank_page_summary); + // TODO: find a better name for the blank tab (maybe "blank_tab") or replace it with + // context.getString(R.string.app_name); + return "NewPipe"; // context.getString(R.string.blank_page_summary); } @DrawableRes @@ -309,7 +315,7 @@ public abstract class Tab { private String kioskId; private KioskTab() { - this(-1, ""); + this(-1, NO_ID); } public KioskTab(final int kioskServiceId, final String kioskId) { @@ -357,7 +363,7 @@ public abstract class Tab { @Override protected void readDataFromJson(final JsonObject jsonObject) { kioskServiceId = jsonObject.getInt(JSON_KIOSK_SERVICE_ID_KEY, -1); - kioskId = jsonObject.getString(JSON_KIOSK_ID_KEY, ""); + kioskId = jsonObject.getString(JSON_KIOSK_ID_KEY, NO_ID); } @Override @@ -395,7 +401,7 @@ public abstract class Tab { private String channelName; private ChannelTab() { - this(-1, "", ""); + this(-1, NO_URL, NO_NAME); } public ChannelTab(final int channelServiceId, final String channelUrl, @@ -440,8 +446,8 @@ public abstract class Tab { @Override protected void readDataFromJson(final JsonObject jsonObject) { channelServiceId = jsonObject.getInt(JSON_CHANNEL_SERVICE_ID_KEY, -1); - channelUrl = jsonObject.getString(JSON_CHANNEL_URL_KEY, ""); - channelName = jsonObject.getString(JSON_CHANNEL_NAME_KEY, ""); + channelUrl = jsonObject.getString(JSON_CHANNEL_URL_KEY, NO_URL); + channelName = jsonObject.getString(JSON_CHANNEL_NAME_KEY, NO_NAME); } @Override @@ -527,7 +533,7 @@ public abstract class Tab { private LocalItemType playlistType; private PlaylistTab() { - this(-1, ""); + this(-1, NO_NAME); } public PlaylistTab(final long playlistId, final String playlistName) { @@ -535,7 +541,7 @@ public abstract class Tab { this.playlistId = playlistId; this.playlistType = LocalItemType.PLAYLIST_LOCAL_ITEM; this.playlistServiceId = -1; - this.playlistUrl = ""; + this.playlistUrl = NO_URL; } public PlaylistTab(final int playlistServiceId, final String playlistUrl, @@ -589,8 +595,8 @@ public abstract class Tab { @Override protected void readDataFromJson(final JsonObject jsonObject) { playlistServiceId = jsonObject.getInt(JSON_PLAYLIST_SERVICE_ID_KEY, -1); - playlistUrl = jsonObject.getString(JSON_PLAYLIST_URL_KEY, ""); - playlistName = jsonObject.getString(JSON_PLAYLIST_NAME_KEY, ""); + playlistUrl = jsonObject.getString(JSON_PLAYLIST_URL_KEY, NO_URL); + playlistName = jsonObject.getString(JSON_PLAYLIST_NAME_KEY, NO_NAME); playlistId = jsonObject.getInt(JSON_PLAYLIST_ID_KEY, -1); playlistType = LocalItemType.valueOf( jsonObject.getString(JSON_PLAYLIST_TYPE_KEY, From 37b8a9375f58770d59f9ce16d72eee476aa5ee49 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Tue, 21 Dec 2021 20:54:06 +0100 Subject: [PATCH 36/49] Small improvements to code quality and readability Add annotations to methods and parameters. Replace Jetbrains' @NotNull with Androidx' @NonNull annotatiation. Make class variables static if possible. Use constants for some Strings. Simplify if conditions. --- .../material/appbar/FlingBehavior.java | 1 + .../fragments/list/search/SearchFragment.java | 2 +- .../local/subscription/item/ChannelItem.kt | 8 ++--- .../org/schabi/newpipe/player/Player.java | 26 +++++++------- .../player/event/PlayerGestureListener.java | 34 +++++++++---------- .../newpipe/player/helper/PlayerHolder.java | 6 ++-- .../settings/BasePreferenceFragment.java | 2 +- .../us/shandian/giga/io/FileStreamSAF.java | 4 +++ 8 files changed, 44 insertions(+), 39 deletions(-) diff --git a/app/src/main/java/com/google/android/material/appbar/FlingBehavior.java b/app/src/main/java/com/google/android/material/appbar/FlingBehavior.java index ca1bd79d2..3e5f408f7 100644 --- a/app/src/main/java/com/google/android/material/appbar/FlingBehavior.java +++ b/app/src/main/java/com/google/android/material/appbar/FlingBehavior.java @@ -63,6 +63,7 @@ public final class FlingBehavior extends AppBarLayout.Behavior { return consumed == dy; } + @Override public boolean onInterceptTouchEvent(@NonNull final CoordinatorLayout parent, @NonNull final AppBarLayout child, @NonNull final MotionEvent ev) { 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 098df760d..15424334d 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 @@ -724,7 +724,7 @@ public class SearchFragment extends BaseListFragment 0 + && !infoListAdapter.getItemsList().isEmpty() && !isLoading.get()) { hideSuggestionsPanel(); hideKeyboardSearch(); diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/ChannelItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/ChannelItem.kt index 2b964779c..a8c05838f 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/ChannelItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/ChannelItem.kt @@ -54,11 +54,9 @@ class ChannelItem( context.getString(R.string.subscribers_count_not_available) } - if (itemVersion == ItemVersion.NORMAL) { - if (infoItem.streamCount >= 0) { - val formattedVideoAmount = Localization.localizeStreamCount(context, infoItem.streamCount) - details = Localization.concatenateStrings(details, formattedVideoAmount) - } + if (itemVersion == ItemVersion.NORMAL && infoItem.streamCount >= 0) { + val formattedVideoAmount = Localization.localizeStreamCount(context, infoItem.streamCount) + details = Localization.concatenateStrings(details, formattedVideoAmount) } return details } 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 ee09cb866..c038f5573 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -2348,7 +2348,8 @@ public final class Player implements NotificationUtil.getInstance().createNotificationIfNeededAndUpdate(this, false); } - private void setRepeatModeButton(final AppCompatImageButton imageButton, final int repeatMode) { + private void setRepeatModeButton(final AppCompatImageButton imageButton, + @RepeatMode final int repeatMode) { switch (repeatMode) { case REPEAT_MODE_OFF: imageButton.setImageResource(R.drawable.exo_controls_repeat_off); @@ -2362,7 +2363,7 @@ public final class Player implements } } - private void setShuffleButton(final ImageButton button, final boolean shuffled) { + private void setShuffleButton(@NonNull final ImageButton button, final boolean shuffled) { button.setImageAlpha(shuffled ? 255 : 77); } //endregion @@ -2387,7 +2388,7 @@ public final class Player implements return !exoPlayerIsNull() && simpleExoPlayer.getVolume() == 0; } - private void setMuteButton(final ImageButton button, final boolean isMuted) { + private void setMuteButton(@NonNull final ImageButton button, final boolean isMuted) { button.setImageDrawable(AppCompatResources.getDrawable(context, isMuted ? R.drawable.ic_volume_off : R.drawable.ic_volume_up)); } @@ -2876,7 +2877,7 @@ public final class Player implements databaseUpdateDisposable .add(recordManager.saveStreamState(currentMetadata.getMetadata(), progressMillis) .observeOn(AndroidSchedulers.mainThread()) - .doOnError((e) -> { + .doOnError(e -> { if (DEBUG) { e.printStackTrace(); } @@ -3386,7 +3387,7 @@ public final class Player implements playbackSpeedPopupMenu.setOnDismissListener(this); } - private void buildCaptionMenu(final List availableLanguages) { + private void buildCaptionMenu(@NonNull final List availableLanguages) { if (captionPopupMenu == null) { return; } @@ -3454,7 +3455,7 @@ public final class Player implements * Called when an item of the quality selector or the playback speed selector is selected. */ @Override - public boolean onMenuItemClick(final MenuItem menuItem) { + public boolean onMenuItemClick(@NonNull final MenuItem menuItem) { if (DEBUG) { Log.d(TAG, "onMenuItemClick() called with: " + "menuItem = [" + menuItem + "], " @@ -3491,7 +3492,7 @@ public final class Player implements * Called when some popup menu is dismissed. */ @Override - public void onDismiss(final PopupMenu menu) { + public void onDismiss(@Nullable final PopupMenu menu) { if (DEBUG) { Log.d(TAG, "onDismiss() called with: menu = [" + menu + "]"); } @@ -3544,7 +3545,7 @@ public final class Player implements isSomePopupMenuVisible = true; } - private void setPlaybackQuality(final String quality) { + private void setPlaybackQuality(@Nullable final String quality) { videoResolver.setPlaybackQuality(quality); } //endregion @@ -3568,7 +3569,7 @@ public final class Player implements final int minimumLength = Math.min(metrics.heightPixels, metrics.widthPixels); final float captionRatioInverse = 20f + 4f * (1.0f - captionScale); binding.subtitleView.setFixedTextSize( - TypedValue.COMPLEX_UNIT_PX, (float) minimumLength / captionRatioInverse); + TypedValue.COMPLEX_UNIT_PX, minimumLength / captionRatioInverse); } binding.subtitleView.setApplyEmbeddedStyles(captionStyle == CaptionStyleCompat.DEFAULT); binding.subtitleView.setStyle(captionStyle); @@ -3845,7 +3846,7 @@ public final class Player implements } @Override // exoplayer listener - public void onVideoSizeChanged(final VideoSize videoSize) { + public void onVideoSizeChanged(@NonNull final VideoSize videoSize) { if (DEBUG) { Log.d(TAG, "onVideoSizeChanged() called with: " + "width / height = [" + videoSize.width + " / " + videoSize.height @@ -3959,7 +3960,7 @@ public final class Player implements } } - private int distanceFromCloseButton(final MotionEvent popupMotionEvent) { + private int distanceFromCloseButton(@NonNull final MotionEvent popupMotionEvent) { final int closeOverlayButtonX = closeOverlayBinding.closeButton.getLeft() + closeOverlayBinding.closeButton.getWidth() / 2; final int closeOverlayButtonY = closeOverlayBinding.closeButton.getTop() @@ -3978,7 +3979,7 @@ public final class Player implements return buttonRadius * 1.2f; } - public boolean isInsideClosingRadius(final MotionEvent popupMotionEvent) { + public boolean isInsideClosingRadius(@NonNull final MotionEvent popupMotionEvent) { return distanceFromCloseButton(popupMotionEvent) <= getClosingRadius(); } //endregion @@ -4098,6 +4099,7 @@ public final class Player implements } } + @Nullable public AppCompatActivity getParentActivity() { // ! instanceof ViewGroup means that view was added via windowManager for Popup if (binding == null || !(binding.getRoot().getParent() instanceof ViewGroup)) { 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 e55c596b8..25ace1c05 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 @@ -1,5 +1,12 @@ package org.schabi.newpipe.player.event; +import static org.schabi.newpipe.ktx.AnimationType.ALPHA; +import static org.schabi.newpipe.ktx.AnimationType.SCALE_AND_ALPHA; +import static org.schabi.newpipe.ktx.ViewUtils.animate; +import static org.schabi.newpipe.player.Player.DEFAULT_CONTROLS_DURATION; +import static org.schabi.newpipe.player.Player.DEFAULT_CONTROLS_HIDE_TIME; +import static org.schabi.newpipe.player.Player.STATE_PLAYING; + import android.app.Activity; import android.util.Log; import android.view.MotionEvent; @@ -8,22 +15,15 @@ import android.view.Window; import android.view.WindowManager; import android.widget.ProgressBar; +import androidx.annotation.NonNull; import androidx.appcompat.content.res.AppCompatResources; -import org.jetbrains.annotations.NotNull; import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; import org.schabi.newpipe.player.MainPlayer; import org.schabi.newpipe.player.Player; import org.schabi.newpipe.player.helper.PlayerHelper; -import static org.schabi.newpipe.ktx.AnimationType.ALPHA; -import static org.schabi.newpipe.ktx.AnimationType.SCALE_AND_ALPHA; -import static org.schabi.newpipe.ktx.ViewUtils.animate; -import static org.schabi.newpipe.player.Player.DEFAULT_CONTROLS_DURATION; -import static org.schabi.newpipe.player.Player.DEFAULT_CONTROLS_HIDE_TIME; -import static org.schabi.newpipe.player.Player.STATE_PLAYING; - /** * GestureListener for the player * @@ -45,8 +45,8 @@ public class PlayerGestureListener } @Override - public void onDoubleTap(@NotNull final MotionEvent event, - @NotNull final DisplayPortion portion) { + public void onDoubleTap(@NonNull final MotionEvent event, + @NonNull final DisplayPortion portion) { if (DEBUG) { Log.d(TAG, "onDoubleTap called with playerType = [" + player.getPlayerType() + "], portion = [" + portion + "]"); @@ -65,7 +65,7 @@ public class PlayerGestureListener } @Override - public void onSingleTap(@NotNull final MainPlayer.PlayerType playerType) { + public void onSingleTap(@NonNull final MainPlayer.PlayerType playerType) { if (DEBUG) { Log.d(TAG, "onSingleTap called with playerType = [" + player.getPlayerType() + "]"); } @@ -85,10 +85,10 @@ public class PlayerGestureListener } @Override - public void onScroll(@NotNull final MainPlayer.PlayerType playerType, - @NotNull final DisplayPortion portion, - @NotNull final MotionEvent initialEvent, - @NotNull final MotionEvent movingEvent, + public void onScroll(@NonNull final MainPlayer.PlayerType playerType, + @NonNull final DisplayPortion portion, + @NonNull final MotionEvent initialEvent, + @NonNull final MotionEvent movingEvent, final float distanceX, final float distanceY) { if (DEBUG) { Log.d(TAG, "onScroll called with playerType = [" @@ -197,8 +197,8 @@ public class PlayerGestureListener } @Override - public void onScrollEnd(@NotNull final MainPlayer.PlayerType playerType, - @NotNull final MotionEvent event) { + public void onScrollEnd(@NonNull final MainPlayer.PlayerType playerType, + @NonNull final MotionEvent event) { if (DEBUG) { Log.d(TAG, "onScrollEnd called with playerType = [" + player.getPlayerType() + "]"); diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java index 3d960ae90..10e315667 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java @@ -35,8 +35,8 @@ public final class PlayerHolder { return PlayerHolder.instance; } - private final boolean DEBUG = MainActivity.DEBUG; - private final String TAG = PlayerHolder.class.getSimpleName(); + private static final boolean DEBUG = MainActivity.DEBUG; + private static final String TAG = PlayerHolder.class.getSimpleName(); private PlayerServiceExtendedEventListener listener; @@ -152,7 +152,7 @@ public final class PlayerHolder { } startPlayerListener(); } - }; + } private void bind(final Context context) { if (DEBUG) { diff --git a/app/src/main/java/org/schabi/newpipe/settings/BasePreferenceFragment.java b/app/src/main/java/org/schabi/newpipe/settings/BasePreferenceFragment.java index 8b2bd9c9a..a745861ad 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/BasePreferenceFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/BasePreferenceFragment.java @@ -18,7 +18,7 @@ import java.util.Objects; public abstract class BasePreferenceFragment extends PreferenceFragmentCompat { protected final String TAG = getClass().getSimpleName() + "@" + Integer.toHexString(hashCode()); - protected final boolean DEBUG = MainActivity.DEBUG; + protected static final boolean DEBUG = MainActivity.DEBUG; SharedPreferences defaultPreferences; diff --git a/app/src/main/java/us/shandian/giga/io/FileStreamSAF.java b/app/src/main/java/us/shandian/giga/io/FileStreamSAF.java index 000900918..b7dd0a103 100644 --- a/app/src/main/java/us/shandian/giga/io/FileStreamSAF.java +++ b/app/src/main/java/us/shandian/giga/io/FileStreamSAF.java @@ -108,10 +108,12 @@ public class FileStreamSAF extends SharpStream { return true; } + @Override public boolean canSetLength() { return true; } + @Override public boolean canSeek() { return true; } @@ -131,10 +133,12 @@ public class FileStreamSAF extends SharpStream { out.write(buffer, offset, count); } + @Override public void setLength(long length) throws IOException { channel.truncate(length); } + @Override public void seek(long offset) throws IOException { channel.position(offset); } From dc67628ba5d2e8676fa0514aa982bec7322a8b75 Mon Sep 17 00:00:00 2001 From: XiangRongLin <41164160+XiangRongLin@users.noreply.github.com> Date: Mon, 20 Dec 2021 16:29:20 +0100 Subject: [PATCH 37/49] Log test-android CI job in stacktrace mode --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c0ca24abb..4a707ff0a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,7 +39,7 @@ jobs: java-version: 11 distribution: "temurin" cache: 'gradle' - + - name: Build debug APK and run jvm tests run: ./gradlew assembleDebug lintDebug testDebugUnitTest --stacktrace -DskipFormatKtlint @@ -54,7 +54,7 @@ jobs: runs-on: macos-latest strategy: matrix: - # api-level 19 is min sdk, but throws errors related to desugaring + # api-level 19 is min sdk, but throws errors related to desugaring api-level: [ 21, 29 ] steps: - uses: actions/checkout@v2 @@ -72,7 +72,7 @@ jobs: api-level: ${{ matrix.api-level }} # workaround to emulator bug: https://github.com/ReactiveCircus/android-emulator-runner/issues/160 emulator-build: 7425822 - script: ./gradlew connectedCheck + script: ./gradlew connectedCheck --stacktrace sonar: runs-on: ubuntu-latest From f3edc698973f94af0887c06da7b974690a8ae659 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Thu, 5 Aug 2021 14:52:50 +0200 Subject: [PATCH 38/49] Fix incorrect link in Japanese README --- README.ja.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.ja.md b/README.ja.md index 5d9d46f75..2deab555c 100644 --- a/README.ja.md +++ b/README.ja.md @@ -17,7 +17,7 @@

ウェブサイトブログFAQニュース


-*他の言語で読む: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt.br.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md)。* +*他の言語で読む: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md)。* 注意: これはベータ版のため、バグが発生する可能性があります。もしバグが発生した場合、GitHub のリポジトリで Issue を開いてください。 From 989bcbf895c1879ca7cfd3e47f65d50bd0ce19d8 Mon Sep 17 00:00:00 2001 From: vhouriet Date: Wed, 22 Dec 2021 12:36:26 +0100 Subject: [PATCH 39/49] Add Already playing in background toast --- .../org/schabi/newpipe/util/NavigationHelper.java | 12 +++++++++--- app/src/main/res/values/strings.xml | 1 + 2 files changed, 10 insertions(+), 3 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 c01e051b0..d5be71f15 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -168,10 +168,16 @@ public final class NavigationHelper { public static void playOnBackgroundPlayer(final Context context, final PlayQueue queue, final boolean resumePlayback) { - if (PlayerHolder.getInstance().getType() != MainPlayer.PlayerType.AUDIO) { - Toast.makeText(context, R.string.background_player_playing_toast, Toast.LENGTH_SHORT) - .show(); + final int toastText; + if (PlayerHolder.getInstance().getType() == MainPlayer.PlayerType.AUDIO) { + toastText = R.string.background_player_already_playing_toast; + } else { + toastText = R.string.background_player_playing_toast; } + + Toast.makeText(context, toastText, 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); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b4d46a3e2..303e7bb3f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -147,6 +147,7 @@ Updates Notification Playing in background + Already playing in background Playing in popup mode Content Show age restricted content From c90237c14ceaffe16d27d9a9faec3156bef760f7 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sun, 19 Dec 2021 20:16:10 +0100 Subject: [PATCH 40/49] Removed/Reverted MediaParser support (Android 11+) due to bugs --- .../player/helper/PlayerDataSource.java | 51 +++---------------- 1 file changed, 8 insertions(+), 43 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 b7584151d..708b72ff2 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,18 +1,14 @@ 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; @@ -46,17 +42,10 @@ public class PlayerDataSource { } 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) { - factory.setExtractorFactory(MediaParserHlsMediaChunkExtractor.FACTORY); - } - - return factory; + return new HlsMediaSource.Factory(cachelessDataSourceFactory) + .setAllowChunklessPreparation(true) + .setLoadErrorHandlingPolicy( + new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)); } public DashMediaSource.Factory getLiveDashMediaSourceFactory() { @@ -71,26 +60,11 @@ public class PlayerDataSource { 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() { - 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); + return new HlsMediaSource.Factory(cacheDataSourceFactory); } public DashMediaSource.Factory getDashMediaSourceFactory() { @@ -101,18 +75,9 @@ public class PlayerDataSource { } public ProgressiveMediaSource.Factory getExtractorMediaSourceFactory() { - final ProgressiveMediaSource.Factory factory; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - factory = new ProgressiveMediaSource.Factory( - cacheDataSourceFactory, - MediaParserExtractorAdapter.FACTORY - ); - } else { - factory = new ProgressiveMediaSource.Factory(cacheDataSourceFactory); - } - - return factory.setLoadErrorHandlingPolicy( - new DefaultLoadErrorHandlingPolicy(EXTRACTOR_MINIMUM_RETRY)); + return new ProgressiveMediaSource.Factory(cacheDataSourceFactory) + .setLoadErrorHandlingPolicy( + new DefaultLoadErrorHandlingPolicy(EXTRACTOR_MINIMUM_RETRY)); } public SingleSampleMediaSource.Factory getSampleMediaSourceFactory() { From 8c6e37d1d13d94e377d4826aa2756d8897948c9e Mon Sep 17 00:00:00 2001 From: Robin Date: Sat, 4 Dec 2021 22:23:09 +0100 Subject: [PATCH 41/49] Disable media tunneling on Philips QM16XE --- app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java b/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java index bbe9a7edb..a4ff5ff19 100644 --- a/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java +++ b/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java @@ -37,6 +37,9 @@ public final class DeviceUtils { // Hilife TV private static final boolean REALTEKATV = Build.VERSION.SDK_INT == 25 && Build.DEVICE.equals("RealtekATV"); + // Philips QM16XE + private static final boolean QM16XE_U = Build.VERSION.SDK_INT == 23 + && Build.DEVICE.equals("QM16XE_U"); private DeviceUtils() { } @@ -134,7 +137,8 @@ public final class DeviceUtils { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !HI3798MV200 && !CVT_MT5886_EU_1G - && !REALTEKATV; + && !REALTEKATV + && !QM16XE_U; } public static boolean isLandscape(final Context context) { From ff8868f6a3de2f8885c0a02fb906c9f98c186144 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Thu, 23 Dec 2021 23:41:20 +0100 Subject: [PATCH 42/49] NewPipe version 0.21.15 (981) --- app/build.gradle | 4 ++-- fastlane/metadata/android/en-US/changelogs/981.txt | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/981.txt diff --git a/app/build.gradle b/app/build.gradle index 35bdd998e..0f7c28a43 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,8 +17,8 @@ android { resValue "string", "app_name", "NewPipe" minSdkVersion 19 targetSdkVersion 29 - versionCode 980 - versionName "0.21.14" + versionCode 981 + versionName "0.21.15" multiDexEnabled true diff --git a/fastlane/metadata/android/en-US/changelogs/981.txt b/fastlane/metadata/android/en-US/changelogs/981.txt new file mode 100644 index 000000000..9a2230ade --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/981.txt @@ -0,0 +1,2 @@ +Removed MediaParser support to fix failing playback resume after buffering on Android 11+. +Disabled media tunneling on Philips QM16XE to fix playback problems. From 07015973d27dd5191b6d7148cc0f04e5aa428fdc Mon Sep 17 00:00:00 2001 From: David Kramer Date: Fri, 24 Dec 2021 11:29:34 -0600 Subject: [PATCH 43/49] Added ability to see pinned comment --- .../holder/CommentsInfoItemHolder.java | 4 ++++ app/src/main/res/drawable-night/ic_pin.xml | 19 +++++++++++++++++++ app/src/main/res/drawable/ic_pin.xml | 18 ++++++++++++++++++ .../main/res/layout/list_comments_item.xml | 14 +++++++++++++- app/src/main/res/values-land/dimens.xml | 1 + app/src/main/res/values-sw600dp/dimens.xml | 1 + app/src/main/res/values/dimens.xml | 3 +++ app/src/main/res/values/strings.xml | 1 + 8 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 app/src/main/res/drawable-night/ic_pin.xml create mode 100644 app/src/main/res/drawable/ic_pin.xml diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsInfoItemHolder.java index fb144574a..4fc2d9f84 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsInfoItemHolder.java @@ -34,12 +34,14 @@ import org.schabi.newpipe.local.history.HistoryRecordManager; public class CommentsInfoItemHolder extends CommentsMiniInfoItemHolder { public final TextView itemTitleView; private final ImageView itemHeartView; + private final ImageView itemPinnedView; public CommentsInfoItemHolder(final InfoItemBuilder infoItemBuilder, final ViewGroup parent) { super(infoItemBuilder, R.layout.list_comments_item, parent); itemTitleView = itemView.findViewById(R.id.itemTitleView); itemHeartView = itemView.findViewById(R.id.detail_heart_image_view); + itemPinnedView = itemView.findViewById(R.id.detail_pinned_view); } @Override @@ -55,5 +57,7 @@ public class CommentsInfoItemHolder extends CommentsMiniInfoItemHolder { itemTitleView.setText(item.getUploaderName()); itemHeartView.setVisibility(item.isHeartedByUploader() ? View.VISIBLE : View.GONE); + + itemPinnedView.setVisibility(item.isPinned() ? View.VISIBLE : View.GONE); } } diff --git a/app/src/main/res/drawable-night/ic_pin.xml b/app/src/main/res/drawable-night/ic_pin.xml new file mode 100644 index 000000000..6fe406341 --- /dev/null +++ b/app/src/main/res/drawable-night/ic_pin.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_pin.xml b/app/src/main/res/drawable/ic_pin.xml new file mode 100644 index 000000000..70578fbeb --- /dev/null +++ b/app/src/main/res/drawable/ic_pin.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/app/src/main/res/layout/list_comments_item.xml b/app/src/main/res/layout/list_comments_item.xml index f6ddc3924..c76444212 100644 --- a/app/src/main/res/layout/list_comments_item.xml +++ b/app/src/main/res/layout/list_comments_item.xml @@ -23,13 +23,25 @@ android:src="@drawable/buddy" tools:ignore="RtlHardcoded" /> + + 90dp 45dp + 8dp 8dp 4dp diff --git a/app/src/main/res/values-sw600dp/dimens.xml b/app/src/main/res/values-sw600dp/dimens.xml index da00b0c22..85ed7b5a9 100644 --- a/app/src/main/res/values-sw600dp/dimens.xml +++ b/app/src/main/res/values-sw600dp/dimens.xml @@ -18,6 +18,7 @@ 18sp 18sp + 10dp 10dp 14sp diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 5c1d8aa70..f3d29b605 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -71,6 +71,8 @@ 12sp 32dp + 18sp + 18sp 16dp 18sp 18sp @@ -79,6 +81,7 @@ 35dp 60dp + 5dp 5dp 5dp 50dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b4d46a3e2..a16ef26ed 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -712,6 +712,7 @@ Unlisted Private Internal + Pinned comment Hearted by creator Open website Tablet mode From 53f5741317ad00d376fd5a514d9e3f134478b7bb Mon Sep 17 00:00:00 2001 From: Jaspann Date: Sat, 25 Dec 2021 18:10:05 -0500 Subject: [PATCH 44/49] Fixes view of sub-channel icon when not in use --- .../schabi/newpipe/fragments/detail/VideoDetailFragment.java | 5 +++++ 1 file changed, 5 insertions(+) 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 a5e590ba0..a393804df 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 @@ -1648,6 +1648,11 @@ public final class VideoDetailFragment binding.detailSubChannelTextView.setVisibility(View.VISIBLE); binding.detailSubChannelTextView.setSelected(true); binding.detailUploaderTextView.setVisibility(View.GONE); + + //No sub-channel name implies no sub-channel icon, but check just to make sure. + if(isEmpty(info.getSubChannelAvatarUrl())){ + binding.detailSubChannelThumbnailView.setVisibility(View.GONE); + } } private void displayBothUploaderAndSubChannel(final StreamInfo info) { From fb3be544ce9902fbd12fdf8fece2d23d7e06634f Mon Sep 17 00:00:00 2001 From: William Parker Date: Sun, 26 Dec 2021 00:12:48 -0500 Subject: [PATCH 45/49] Fixed code styling --- .../schabi/newpipe/fragments/detail/VideoDetailFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a393804df..20d01c415 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 @@ -1650,7 +1650,7 @@ public final class VideoDetailFragment binding.detailUploaderTextView.setVisibility(View.GONE); //No sub-channel name implies no sub-channel icon, but check just to make sure. - if(isEmpty(info.getSubChannelAvatarUrl())){ + if (isEmpty(info.getSubChannelAvatarUrl())) { binding.detailSubChannelThumbnailView.setVisibility(View.GONE); } } From b67bf16d4f3f0a238472021f58eb467b48560a2b Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sun, 26 Dec 2021 23:57:54 +0100 Subject: [PATCH 46/49] Minified code --- .../org/schabi/newpipe/util/NavigationHelper.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 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 d5be71f15..bb305aec7 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -168,14 +168,12 @@ public final class NavigationHelper { public static void playOnBackgroundPlayer(final Context context, final PlayQueue queue, final boolean resumePlayback) { - final int toastText; - if (PlayerHolder.getInstance().getType() == MainPlayer.PlayerType.AUDIO) { - toastText = R.string.background_player_already_playing_toast; - } else { - toastText = R.string.background_player_playing_toast; - } - - Toast.makeText(context, toastText, Toast.LENGTH_SHORT) + Toast.makeText( + context, + PlayerHolder.getInstance().getType() == PlayerType.AUDIO + ? R.string.background_player_playing_toast + : R.string.background_player_playing_toast, + Toast.LENGTH_SHORT) .show(); final Intent intent = getPlayerIntent(context, MainPlayer.class, queue, resumePlayback); From fc0e709817d8629d106dbfdd7078baf58500e707 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Mon, 27 Dec 2021 00:14:04 +0100 Subject: [PATCH 47/49] Fixed usage of wrong string --- app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java | 2 +- 1 file changed, 1 insertion(+), 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 bb305aec7..2a3f3c2dd 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -171,7 +171,7 @@ public final class NavigationHelper { Toast.makeText( context, PlayerHolder.getInstance().getType() == PlayerType.AUDIO - ? R.string.background_player_playing_toast + ? R.string.background_player_already_playing_toast : R.string.background_player_playing_toast, Toast.LENGTH_SHORT) .show(); From 4147c7c1d1da30e96c06e352a36da36989c8a9b3 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Mon, 27 Dec 2021 18:41:53 +0100 Subject: [PATCH 48/49] Updated NewPipeExtractor --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 689d7f08e..0386e7aa2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -188,7 +188,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.12' + implementation 'com.github.TeamNewPipe:NewPipeExtractor:10f6cc71' /** Checkstyle **/ checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}" From 558c9147a2204e53b43a61774a774a0492307a24 Mon Sep 17 00:00:00 2001 From: Jaspann Date: Tue, 28 Dec 2021 15:54:36 -0500 Subject: [PATCH 49/49] Move sub icon visibility line --- .../newpipe/fragments/detail/VideoDetailFragment.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) 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 20d01c415..5a74dc948 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 @@ -1521,6 +1521,8 @@ public final class VideoDetailFragment animate(binding.detailThumbnailPlayButton, true, 200); binding.detailVideoTitleView.setText(title); + binding.detailSubChannelThumbnailView.setVisibility(View.GONE); + if (!isEmpty(info.getSubChannelName())) { displayBothUploaderAndSubChannel(info); } else if (!isEmpty(info.getUploaderName())) { @@ -1648,11 +1650,6 @@ public final class VideoDetailFragment binding.detailSubChannelTextView.setVisibility(View.VISIBLE); binding.detailSubChannelTextView.setSelected(true); binding.detailUploaderTextView.setVisibility(View.GONE); - - //No sub-channel name implies no sub-channel icon, but check just to make sure. - if (isEmpty(info.getSubChannelAvatarUrl())) { - binding.detailSubChannelThumbnailView.setVisibility(View.GONE); - } } private void displayBothUploaderAndSubChannel(final StreamInfo info) {