From 6ddd4a7e636ed163b505e95d184b741931e6c226 Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Sun, 11 Jan 2026 18:04:26 +0200 Subject: [PATCH 01/56] VideoDetailFragment: hide relatedItemsLayout in tablet mode after fullscreen Fixes: #7617 --- .../newpipe/fragments/detail/VideoDetailFragment.java | 6 +++++- 1 file changed, 5 insertions(+), 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 9bffa149c..aa78bfa38 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 @@ -1899,7 +1899,11 @@ public final class VideoDetailFragment } if (binding.relatedItemsLayout != null) { - binding.relatedItemsLayout.setVisibility(fullscreen ? View.GONE : View.VISIBLE); + if (showRelatedItems) { + binding.relatedItemsLayout.setVisibility(fullscreen ? View.GONE : View.VISIBLE); + } else { + binding.relatedItemsLayout.setVisibility(View.GONE); + } } scrollToTop(); From 8a2c47bc12b01938e8ba5edddbf5568303ca340d Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Thu, 29 Jan 2026 15:01:40 +0200 Subject: [PATCH 02/56] Remove dead code from info_list/InfoItemBuilder It no longer really builds any view and used only for stroing click gesture callbacks. In the same way lik local/LocalItemBuilder does Last usage of build functions: 2e9a860aaa138f9682d363eece897506b823e340 --- .../newpipe/info_list/InfoItemBuilder.java | 131 ------------------ .../newpipe/info_list/InfoItemBuilder.kt | 20 +++ 2 files changed, 20 insertions(+), 131 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/info_list/InfoItemBuilder.java create mode 100644 app/src/main/java/org/schabi/newpipe/info_list/InfoItemBuilder.kt diff --git a/app/src/main/java/org/schabi/newpipe/info_list/InfoItemBuilder.java b/app/src/main/java/org/schabi/newpipe/info_list/InfoItemBuilder.java deleted file mode 100644 index d959c6327..000000000 --- a/app/src/main/java/org/schabi/newpipe/info_list/InfoItemBuilder.java +++ /dev/null @@ -1,131 +0,0 @@ -package org.schabi.newpipe.info_list; - -import android.content.Context; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; - -import org.schabi.newpipe.extractor.InfoItem; -import org.schabi.newpipe.extractor.channel.ChannelInfoItem; -import org.schabi.newpipe.extractor.comments.CommentsInfoItem; -import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem; -import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.info_list.holder.ChannelInfoItemHolder; -import org.schabi.newpipe.info_list.holder.ChannelMiniInfoItemHolder; -import org.schabi.newpipe.info_list.holder.CommentInfoItemHolder; -import org.schabi.newpipe.info_list.holder.InfoItemHolder; -import org.schabi.newpipe.info_list.holder.PlaylistInfoItemHolder; -import org.schabi.newpipe.info_list.holder.PlaylistMiniInfoItemHolder; -import org.schabi.newpipe.info_list.holder.StreamInfoItemHolder; -import org.schabi.newpipe.info_list.holder.StreamMiniInfoItemHolder; -import org.schabi.newpipe.local.history.HistoryRecordManager; -import org.schabi.newpipe.util.OnClickGesture; - -/* - * Created by Christian Schabesberger on 26.09.16. - *

- * Copyright (C) Christian Schabesberger 2016 - * InfoItemBuilder.java is part of NewPipe. - *

- *

- * NewPipe is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - *

- *

- * NewPipe is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - *

- *

- * You should have received a copy of the GNU General Public License - * along with NewPipe. If not, see . - *

- */ - -public class InfoItemBuilder { - private final Context context; - - private OnClickGesture onStreamSelectedListener; - private OnClickGesture onChannelSelectedListener; - private OnClickGesture onPlaylistSelectedListener; - private OnClickGesture onCommentsSelectedListener; - - public InfoItemBuilder(final Context context) { - this.context = context; - } - - public View buildView(@NonNull final ViewGroup parent, @NonNull final InfoItem infoItem, - final HistoryRecordManager historyRecordManager) { - return buildView(parent, infoItem, historyRecordManager, false); - } - - public View buildView(@NonNull final ViewGroup parent, @NonNull final InfoItem infoItem, - final HistoryRecordManager historyRecordManager, - final boolean useMiniVariant) { - final InfoItemHolder holder = - holderFromInfoType(parent, infoItem.getInfoType(), useMiniVariant); - holder.updateFromItem(infoItem, historyRecordManager); - return holder.itemView; - } - - private InfoItemHolder holderFromInfoType(@NonNull final ViewGroup parent, - @NonNull final InfoItem.InfoType infoType, - final boolean useMiniVariant) { - switch (infoType) { - case STREAM: - return useMiniVariant ? new StreamMiniInfoItemHolder(this, parent) - : new StreamInfoItemHolder(this, parent); - case CHANNEL: - return useMiniVariant ? new ChannelMiniInfoItemHolder(this, parent) - : new ChannelInfoItemHolder(this, parent); - case PLAYLIST: - return useMiniVariant ? new PlaylistMiniInfoItemHolder(this, parent) - : new PlaylistInfoItemHolder(this, parent); - case COMMENT: - return new CommentInfoItemHolder(this, parent); - default: - throw new RuntimeException("InfoType not expected = " + infoType.name()); - } - } - - public Context getContext() { - return context; - } - - public OnClickGesture getOnStreamSelectedListener() { - return onStreamSelectedListener; - } - - public void setOnStreamSelectedListener(final OnClickGesture listener) { - this.onStreamSelectedListener = listener; - } - - public OnClickGesture getOnChannelSelectedListener() { - return onChannelSelectedListener; - } - - public void setOnChannelSelectedListener(final OnClickGesture listener) { - this.onChannelSelectedListener = listener; - } - - public OnClickGesture getOnPlaylistSelectedListener() { - return onPlaylistSelectedListener; - } - - public void setOnPlaylistSelectedListener(final OnClickGesture listener) { - this.onPlaylistSelectedListener = listener; - } - - public OnClickGesture getOnCommentsSelectedListener() { - return onCommentsSelectedListener; - } - - public void setOnCommentsSelectedListener( - final OnClickGesture onCommentsSelectedListener) { - this.onCommentsSelectedListener = onCommentsSelectedListener; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/info_list/InfoItemBuilder.kt b/app/src/main/java/org/schabi/newpipe/info_list/InfoItemBuilder.kt new file mode 100644 index 000000000..cf674180e --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/info_list/InfoItemBuilder.kt @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2016-2026 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.info_list + +import android.content.Context +import org.schabi.newpipe.extractor.channel.ChannelInfoItem +import org.schabi.newpipe.extractor.comments.CommentsInfoItem +import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem +import org.schabi.newpipe.extractor.stream.StreamInfoItem +import org.schabi.newpipe.util.OnClickGesture + +class InfoItemBuilder(val context: Context) { + var onStreamSelectedListener: OnClickGesture? = null + var onChannelSelectedListener: OnClickGesture? = null + var onPlaylistSelectedListener: OnClickGesture? = null + var onCommentsSelectedListener: OnClickGesture? = null +} From 07fe1e758ab3dfc2fdb6a231a148bc86500094f3 Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Wed, 28 Jan 2026 00:07:31 +0200 Subject: [PATCH 03/56] Refactor settings/tabs/TabsJsonHelper.java to use java streams --- .../newpipe/settings/tabs/TabsJsonHelper.java | 31 ++++++------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/tabs/TabsJsonHelper.java b/app/src/main/java/org/schabi/newpipe/settings/tabs/TabsJsonHelper.java index 30676477c..c42348be0 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/tabs/TabsJsonHelper.java +++ b/app/src/main/java/org/schabi/newpipe/settings/tabs/TabsJsonHelper.java @@ -9,8 +9,9 @@ import com.grack.nanojson.JsonParserException; import com.grack.nanojson.JsonStringWriter; import com.grack.nanojson.JsonWriter; -import java.util.ArrayList; import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; /** * Class to get a JSON representation of a list of tabs, and the other way around. @@ -44,39 +45,25 @@ public final class TabsJsonHelper { return getDefaultTabs(); } - final List returnTabs = new ArrayList<>(); - - final JsonObject outerJsonObject; try { - outerJsonObject = JsonParser.object().from(tabsJson); + final JsonObject outerJsonObject = JsonParser.object().from(tabsJson); if (!outerJsonObject.has(JSON_TABS_ARRAY_KEY)) { throw new InvalidJsonException("JSON doesn't contain \"" + JSON_TABS_ARRAY_KEY + "\" array"); } - final JsonArray tabsArray = outerJsonObject.getArray(JSON_TABS_ARRAY_KEY); + final JsonArray tabsArray = outerJsonObject.getArray(JSON_TABS_ARRAY_KEY, null); - for (final Object o : tabsArray) { - if (!(o instanceof JsonObject)) { - continue; - } + final var returnTabs = tabsArray.streamAsJsonObjects() + .map(Tab::from) + .filter(Objects::nonNull) + .collect(Collectors.toUnmodifiableList()); - final Tab tab = Tab.from((JsonObject) o); - - if (tab != null) { - returnTabs.add(tab); - } - } + return returnTabs.isEmpty() ? getDefaultTabs() : returnTabs; } catch (final JsonParserException e) { throw new InvalidJsonException(e); } - - if (returnTabs.isEmpty()) { - return getDefaultTabs(); - } - - return returnTabs; } /** From 5e1a1989be6a89b70e8839b24b5a422a670de5fa Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Fri, 6 Feb 2026 19:03:01 +0200 Subject: [PATCH 04/56] VideoDetailFragment: Forcefully catch click events uncaught by children Because otherwise they will be caught by underlying view and "click through" will happen. Workaround for #5600 --- .../newpipe/fragments/detail/VideoDetailFragment.java | 6 ++++++ 1 file changed, 6 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 ef9fa1137..31a496711 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 @@ -646,6 +646,12 @@ public final class VideoDetailFragment protected void initListeners() { super.initListeners(); + // Workaround for #5600 + // Forcefully catch click events uncaught by children because otherwise + // they will be caught by underlying view and "click through" will happen + binding.getRoot().setOnClickListener(v -> { }); + binding.getRoot().setOnLongClickListener(v -> true); + setOnClickListeners(); setOnLongClickListeners(); From d6be966db36bca3d40611675e0d1a6693870f8d4 Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Fri, 9 Jan 2026 19:39:47 +0200 Subject: [PATCH 05/56] Replace Illegal{State,Argument} exceptions with more idiomatic kotlin code --- .../main/java/org/schabi/newpipe/about/AboutActivity.kt | 4 ++-- .../org/schabi/newpipe/database/stream/dao/StreamDAO.kt | 2 +- .../newpipe/database/subscription/SubscriptionDAO.kt | 2 +- .../newpipe/player/mediabrowser/MediaBrowserCommon.kt | 4 ++-- .../newpipe/player/mediabrowser/PackageValidator.kt | 8 ++++---- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt b/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt index cfb504200..94bde796b 100644 --- a/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt +++ b/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt @@ -92,7 +92,7 @@ class AboutActivity : AppCompatActivity() { return when (position) { posAbout -> AboutFragment() posLicense -> LicenseFragment.newInstance(SOFTWARE_COMPONENTS) - else -> throw IllegalArgumentException("Unknown position for ViewPager2") + else -> error("Unknown position for ViewPager2") } } @@ -105,7 +105,7 @@ class AboutActivity : AppCompatActivity() { return when (position) { posAbout -> R.string.tab_about posLicense -> R.string.tab_licenses - else -> throw IllegalArgumentException("Unknown position for ViewPager2") + else -> error("Unknown position for ViewPager2") } } } diff --git a/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamDAO.kt b/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamDAO.kt index a6ab2c6cc..86ba262f5 100644 --- a/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamDAO.kt +++ b/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamDAO.kt @@ -87,7 +87,7 @@ abstract class StreamDAO : BasicDAO { private fun compareAndUpdateStream(newerStream: StreamEntity) { val existentMinimalStream = getMinimalStreamForCompare(newerStream.serviceId, newerStream.url) - ?: throw IllegalStateException("Stream cannot be null just after insertion.") + ?: error("Stream cannot be null just after insertion.") newerStream.uid = existentMinimalStream.uid if (!StreamTypeUtil.isLiveStream(newerStream.streamType)) { diff --git a/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionDAO.kt b/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionDAO.kt index e6fdcbf70..72bdbcf5c 100644 --- a/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionDAO.kt +++ b/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionDAO.kt @@ -100,7 +100,7 @@ abstract class SubscriptionDAO : BasicDAO { entity.uid = uidFromInsert } else { val subscriptionIdFromDb = getSubscriptionIdInternal(entity.serviceId, entity.url!!) - ?: throw IllegalStateException("Subscription cannot be null just after insertion.") + ?: error("Subscription cannot be null just after insertion.") entity.uid = subscriptionIdFromDb update(entity) diff --git a/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserCommon.kt b/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserCommon.kt index 12d69a163..fb879bd7c 100644 --- a/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserCommon.kt +++ b/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserCommon.kt @@ -22,7 +22,7 @@ internal fun infoItemTypeToString(type: InfoType): String { InfoType.STREAM -> ID_STREAM InfoType.PLAYLIST -> ID_PLAYLIST InfoType.CHANNEL -> ID_CHANNEL - else -> throw IllegalStateException("Unexpected value: $type") + else -> error("Unexpected value: $type") } } @@ -31,7 +31,7 @@ internal fun infoItemTypeFromString(type: String): InfoType { ID_STREAM -> InfoType.STREAM ID_PLAYLIST -> InfoType.PLAYLIST ID_CHANNEL -> InfoType.CHANNEL - else -> throw IllegalStateException("Unexpected value: $type") + else -> error("Unexpected value: $type") } } diff --git a/app/src/main/java/org/schabi/newpipe/player/mediabrowser/PackageValidator.kt b/app/src/main/java/org/schabi/newpipe/player/mediabrowser/PackageValidator.kt index 05c94e990..ebc70c3b0 100644 --- a/app/src/main/java/org/schabi/newpipe/player/mediabrowser/PackageValidator.kt +++ b/app/src/main/java/org/schabi/newpipe/player/mediabrowser/PackageValidator.kt @@ -82,11 +82,11 @@ internal class PackageValidator(context: Context) { // Build the caller info for the rest of the checks here. val callerPackageInfo = buildCallerInfo(callingPackage) - ?: throw IllegalStateException("Caller wasn't found in the system?") + ?: error("Caller wasn't found in the system?") // Verify that things aren't ... broken. (This test should always pass.) - if (callerPackageInfo.uid != callingUid) { - throw IllegalStateException("Caller's package UID doesn't match caller's actual UID?") + check(callerPackageInfo.uid != callingUid) { + "Caller's package UID doesn't match caller's actual UID?" } val callerSignature = callerPackageInfo.signature @@ -202,7 +202,7 @@ internal class PackageValidator(context: Context) { */ private fun getSystemSignature(): String = getPackageInfo(ANDROID_PLATFORM)?.let { platformInfo -> getSignature(platformInfo) - } ?: throw IllegalStateException("Platform signature not found") + } ?: error("Platform signature not found") /** * Creates a SHA-256 signature given a certificate byte array. From 37cef825a25a38ae8bed042257b1dafed115e08e Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Mon, 9 Feb 2026 14:31:56 +0200 Subject: [PATCH 06/56] Correct inverted check If performs action when value is true but check when false Fix for d6be966db36bca3d40611675e0d1a6693870f8d4 --- .../org/schabi/newpipe/player/mediabrowser/PackageValidator.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/mediabrowser/PackageValidator.kt b/app/src/main/java/org/schabi/newpipe/player/mediabrowser/PackageValidator.kt index ebc70c3b0..619fa600a 100644 --- a/app/src/main/java/org/schabi/newpipe/player/mediabrowser/PackageValidator.kt +++ b/app/src/main/java/org/schabi/newpipe/player/mediabrowser/PackageValidator.kt @@ -85,7 +85,7 @@ internal class PackageValidator(context: Context) { ?: error("Caller wasn't found in the system?") // Verify that things aren't ... broken. (This test should always pass.) - check(callerPackageInfo.uid != callingUid) { + check(callerPackageInfo.uid == callingUid) { "Caller's package UID doesn't match caller's actual UID?" } From 21f446a78e749a9c8611e91d95efb4d86938bd62 Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Mon, 9 Feb 2026 17:04:55 +0200 Subject: [PATCH 07/56] Refactor settings/preferencesearch/PreferenceSearchItem#allRelevantSearchFields It doesn't need to return mutable list --- .../settings/preferencesearch/PreferenceSearchItem.kt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchItem.kt b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchItem.kt index 750e40eae..82bbe7b23 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchItem.kt +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchItem.kt @@ -26,14 +26,13 @@ data class PreferenceSearchItem( val breadcrumbs: String, @XmlRes val searchIndexItemResId: Int ) { + val allRelevantSearchFields: List + get() = listOf(title, summary, entries, breadcrumbs) + fun hasData(): Boolean { return !key.isEmpty() && !title.isEmpty() } - fun getAllRelevantSearchFields(): MutableList { - return mutableListOf(title, summary, entries, breadcrumbs) - } - override fun toString(): String { return "PreferenceItem: $title $summary $key" } From 289d22eed7798d39e5b0be2ef52a6863df93c3d8 Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Mon, 9 Feb 2026 17:10:59 +0200 Subject: [PATCH 08/56] Utilize kotlins ifEmpty --- .../newpipe/database/playlist/model/PlaylistRemoteEntity.kt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.kt b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.kt index 82162e1e4..254fa425a 100644 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.kt +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.kt @@ -62,11 +62,7 @@ data class PlaylistRemoteEntity( orderingName = playlistInfo.name, url = playlistInfo.url, thumbnailUrl = ImageStrategy.imageListToDbUrl( - if (playlistInfo.thumbnails.isEmpty()) { - playlistInfo.uploaderAvatars - } else { - playlistInfo.thumbnails - } + playlistInfo.thumbnails.ifEmpty { playlistInfo.uploaderAvatars } ), uploader = playlistInfo.uploaderName, streamCount = playlistInfo.streamCount From 451409fc3baefea8138dfff44e415cad64f784ee Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Mon, 9 Feb 2026 22:54:28 +0200 Subject: [PATCH 09/56] SharedPreferences.edit applies changes automatically --- .../java/org/schabi/newpipe/local/feed/FeedViewModel.kt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt index 7e781b30f..58ec818f3 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt @@ -129,8 +129,7 @@ class FeedViewModel( fun setSaveShowPlayedItems(showPlayedItems: Boolean) { this.showPlayedItems.onNext(showPlayedItems) PreferenceManager.getDefaultSharedPreferences(application).edit { - this.putBoolean(application.getString(R.string.feed_show_watched_items_key), showPlayedItems) - this.apply() + putBoolean(application.getString(R.string.feed_show_watched_items_key), showPlayedItems) } } @@ -139,8 +138,7 @@ class FeedViewModel( fun setSaveShowPartiallyPlayedItems(showPartiallyPlayedItems: Boolean) { this.showPartiallyPlayedItems.onNext(showPartiallyPlayedItems) PreferenceManager.getDefaultSharedPreferences(application).edit { - this.putBoolean(application.getString(R.string.feed_show_partially_watched_items_key), showPartiallyPlayedItems) - this.apply() + putBoolean(application.getString(R.string.feed_show_partially_watched_items_key), showPartiallyPlayedItems) } } @@ -149,8 +147,7 @@ class FeedViewModel( fun setSaveShowFutureItems(showFutureItems: Boolean) { this.showFutureItems.onNext(showFutureItems) PreferenceManager.getDefaultSharedPreferences(application).edit { - this.putBoolean(application.getString(R.string.feed_show_future_items_key), showFutureItems) - this.apply() + putBoolean(application.getString(R.string.feed_show_future_items_key), showFutureItems) } } From edfdbe805ff098e1b000020fbc98400dc71df57d Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Mon, 9 Feb 2026 23:19:32 +0200 Subject: [PATCH 10/56] Uitilize kotlin elvis operator --- .../schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt index ab856278f..7a256c166 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt @@ -327,7 +327,7 @@ class FeedGroupDialog : DialogFragment(), BackPressable { groupIcon = feedGroupEntity?.icon groupSortOrder = feedGroupEntity?.sortOrder ?: -1 - val feedGroupIcon = if (selectedIcon == null) icon else selectedIcon!! + val feedGroupIcon = selectedIcon ?: icon feedGroupCreateBinding.iconPreview.setImageResource(feedGroupIcon.getDrawableRes()) if (feedGroupCreateBinding.groupNameInput.text.isNullOrBlank()) { From 780e6a4848813108eb4d6b28acb18bb48001f4a3 Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Fri, 9 Jan 2026 06:39:07 +0200 Subject: [PATCH 11/56] Convert newpipe/util/PlayButtonHelper to kotlin --- .../schabi/newpipe/util/PlayButtonHelper.java | 94 ------------------ .../schabi/newpipe/util/PlayButtonHelper.kt | 96 +++++++++++++++++++ 2 files changed, 96 insertions(+), 94 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/util/PlayButtonHelper.java create mode 100644 app/src/main/java/org/schabi/newpipe/util/PlayButtonHelper.kt diff --git a/app/src/main/java/org/schabi/newpipe/util/PlayButtonHelper.java b/app/src/main/java/org/schabi/newpipe/util/PlayButtonHelper.java deleted file mode 100644 index 655ea7092..000000000 --- a/app/src/main/java/org/schabi/newpipe/util/PlayButtonHelper.java +++ /dev/null @@ -1,94 +0,0 @@ -package org.schabi.newpipe.util; - -import android.content.Context; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; -import androidx.preference.PreferenceManager; - -import org.schabi.newpipe.R; -import org.schabi.newpipe.databinding.PlaylistControlBinding; -import org.schabi.newpipe.fragments.list.playlist.PlaylistControlViewHolder; -import org.schabi.newpipe.player.PlayerType; - -/** - * Utility class for play buttons and their respective click listeners. - */ -public final class PlayButtonHelper { - - private PlayButtonHelper() { - // utility class - } - - /** - * Initialize {@link android.view.View.OnClickListener OnClickListener} - * and {@link android.view.View.OnLongClickListener OnLongClickListener} for playlist control - * buttons defined in {@link R.layout#playlist_control}. - * - * @param activity The activity to use for the {@link android.widget.Toast Toast}. - * @param playlistControlBinding The binding of the - * {@link R.layout#playlist_control playlist control layout}. - * @param fragment The fragment to get the play queue from. - */ - public static void initPlaylistControlClickListener( - @NonNull final AppCompatActivity activity, - @NonNull final PlaylistControlBinding playlistControlBinding, - @NonNull final PlaylistControlViewHolder fragment) { - // click listener - playlistControlBinding.playlistCtrlPlayAllButton.setOnClickListener(view -> { - NavigationHelper.playOnMainPlayer(activity, fragment.getPlayQueue()); - showHoldToAppendToastIfNeeded(activity); - }); - playlistControlBinding.playlistCtrlPlayPopupButton.setOnClickListener(view -> { - NavigationHelper.playOnPopupPlayer(activity, fragment.getPlayQueue(), false); - showHoldToAppendToastIfNeeded(activity); - }); - playlistControlBinding.playlistCtrlPlayBgButton.setOnClickListener(view -> { - NavigationHelper.playOnBackgroundPlayer(activity, fragment.getPlayQueue(), false); - showHoldToAppendToastIfNeeded(activity); - }); - - // long click listener - playlistControlBinding.playlistCtrlPlayAllButton.setOnLongClickListener(view -> { - NavigationHelper.enqueueOnPlayer(activity, fragment.getPlayQueue(), PlayerType.MAIN); - return true; - }); - playlistControlBinding.playlistCtrlPlayPopupButton.setOnLongClickListener(view -> { - NavigationHelper.enqueueOnPlayer(activity, fragment.getPlayQueue(), PlayerType.POPUP); - return true; - }); - playlistControlBinding.playlistCtrlPlayBgButton.setOnLongClickListener(view -> { - NavigationHelper.enqueueOnPlayer(activity, fragment.getPlayQueue(), PlayerType.AUDIO); - return true; - }); - } - - /** - * Show the "hold to append" toast if the corresponding preference is enabled. - * - * @param context The context to show the toast. - */ - private static void showHoldToAppendToastIfNeeded(@NonNull final Context context) { - if (shouldShowHoldToAppendTip(context)) { - Toast.makeText(context, R.string.hold_to_append, Toast.LENGTH_SHORT).show(); - } - - } - - /** - * Check if the "hold to append" toast should be shown. - * - *

- * The tip is shown if the corresponding preference is enabled. - * This is the default behaviour. - *

- * - * @param context The context to get the preference. - * @return {@code true} if the tip should be shown, {@code false} otherwise. - */ - public static boolean shouldShowHoldToAppendTip(@NonNull final Context context) { - return PreferenceManager.getDefaultSharedPreferences(context) - .getBoolean(context.getString(R.string.show_hold_to_append_key), true); - } -} diff --git a/app/src/main/java/org/schabi/newpipe/util/PlayButtonHelper.kt b/app/src/main/java/org/schabi/newpipe/util/PlayButtonHelper.kt new file mode 100644 index 000000000..40734ec58 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/PlayButtonHelper.kt @@ -0,0 +1,96 @@ +/* + * SPDX-FileCopyrightText: 2023-2026 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.util + +import android.content.Context +import android.view.View +import android.view.View.OnLongClickListener +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import androidx.preference.PreferenceManager +import org.schabi.newpipe.R +import org.schabi.newpipe.databinding.PlaylistControlBinding +import org.schabi.newpipe.fragments.list.playlist.PlaylistControlViewHolder +import org.schabi.newpipe.player.PlayerType + +/** + * Utility class for play buttons and their respective click listeners. + */ +object PlayButtonHelper { + /** + * Initialize [OnClickListener][View.OnClickListener] + * and [OnLongClickListener][OnLongClickListener] for playlist control + * buttons defined in [R.layout.playlist_control]. + * + * @param activity The activity to use for the [Toast][Toast]. + * @param playlistControlBinding The binding of the + * [playlist control layout][R.layout.playlist_control]. + * @param fragment The fragment to get the play queue from. + */ + @JvmStatic + fun initPlaylistControlClickListener( + activity: AppCompatActivity, + playlistControlBinding: PlaylistControlBinding, + fragment: PlaylistControlViewHolder + ) { + // click listener + playlistControlBinding.playlistCtrlPlayAllButton.setOnClickListener { + NavigationHelper.playOnMainPlayer(activity, fragment.getPlayQueue()) + showHoldToAppendToastIfNeeded(activity) + } + playlistControlBinding.playlistCtrlPlayPopupButton.setOnClickListener { + NavigationHelper.playOnPopupPlayer(activity, fragment.getPlayQueue(), false) + showHoldToAppendToastIfNeeded(activity) + } + playlistControlBinding.playlistCtrlPlayBgButton.setOnClickListener { + NavigationHelper.playOnBackgroundPlayer(activity, fragment.getPlayQueue(), false) + showHoldToAppendToastIfNeeded(activity) + } + + // long click listener + playlistControlBinding.playlistCtrlPlayAllButton.setOnLongClickListener { + NavigationHelper.enqueueOnPlayer(activity, fragment.getPlayQueue(), PlayerType.MAIN) + true + } + playlistControlBinding.playlistCtrlPlayPopupButton.setOnLongClickListener { + NavigationHelper.enqueueOnPlayer(activity, fragment.getPlayQueue(), PlayerType.POPUP) + true + } + playlistControlBinding.playlistCtrlPlayBgButton.setOnLongClickListener { + NavigationHelper.enqueueOnPlayer(activity, fragment.getPlayQueue(), PlayerType.AUDIO) + true + } + } + + /** + * Show the "hold to append" toast if the corresponding preference is enabled. + * + * @param context The context to show the toast. + */ + private fun showHoldToAppendToastIfNeeded(context: Context) { + if (shouldShowHoldToAppendTip(context)) { + Toast.makeText(context, R.string.hold_to_append, Toast.LENGTH_SHORT).show() + } + } + + /** + * Check if the "hold to append" toast should be shown. + * + * + * + * The tip is shown if the corresponding preference is enabled. + * This is the default behaviour. + * + * + * @param context The context to get the preference. + * @return `true` if the tip should be shown, `false` otherwise. + */ + @JvmStatic + fun shouldShowHoldToAppendTip(context: Context): Boolean { + return PreferenceManager.getDefaultSharedPreferences(context) + .getBoolean(context.getString(R.string.show_hold_to_append_key), true) + } +} From 48467669b6d73fced59cdd93cced3a7da7f8ddc2 Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Fri, 9 Jan 2026 07:00:26 +0200 Subject: [PATCH 12/56] Convert newpipe/util/PeertubeHelper to kotlin --- .../schabi/newpipe/util/PeertubeHelper.java | 69 ------------------- .../org/schabi/newpipe/util/PeertubeHelper.kt | 53 ++++++++++++++ 2 files changed, 53 insertions(+), 69 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/util/PeertubeHelper.java create mode 100644 app/src/main/java/org/schabi/newpipe/util/PeertubeHelper.kt diff --git a/app/src/main/java/org/schabi/newpipe/util/PeertubeHelper.java b/app/src/main/java/org/schabi/newpipe/util/PeertubeHelper.java deleted file mode 100644 index 34f99d262..000000000 --- a/app/src/main/java/org/schabi/newpipe/util/PeertubeHelper.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.schabi.newpipe.util; - -import android.content.Context; -import android.content.SharedPreferences; - -import androidx.preference.PreferenceManager; - -import com.grack.nanojson.JsonArray; -import com.grack.nanojson.JsonObject; -import com.grack.nanojson.JsonParser; -import com.grack.nanojson.JsonParserException; -import com.grack.nanojson.JsonStringWriter; -import com.grack.nanojson.JsonWriter; - -import org.schabi.newpipe.R; -import org.schabi.newpipe.extractor.ServiceList; -import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance; - -import java.util.ArrayList; -import java.util.List; - -public final class PeertubeHelper { - private PeertubeHelper() { } - - public static List getInstanceList(final Context context) { - final SharedPreferences sharedPreferences = PreferenceManager - .getDefaultSharedPreferences(context); - final String savedInstanceListKey = context.getString(R.string.peertube_instance_list_key); - final String savedJson = sharedPreferences.getString(savedInstanceListKey, null); - if (null == savedJson) { - return List.of(getCurrentInstance()); - } - - try { - final JsonArray array = JsonParser.object().from(savedJson).getArray("instances"); - final List result = new ArrayList<>(); - for (final Object o : array) { - if (o instanceof JsonObject) { - final JsonObject instance = (JsonObject) o; - final String name = instance.getString("name"); - final String url = instance.getString("url"); - result.add(new PeertubeInstance(url, name)); - } - } - return result; - } catch (final JsonParserException e) { - return List.of(getCurrentInstance()); - } - } - - public static PeertubeInstance selectInstance(final PeertubeInstance instance, - final Context context) { - final SharedPreferences sharedPreferences = PreferenceManager - .getDefaultSharedPreferences(context); - final String selectedInstanceKey = - context.getString(R.string.peertube_selected_instance_key); - final JsonStringWriter jsonWriter = JsonWriter.string().object(); - jsonWriter.value("name", instance.getName()); - jsonWriter.value("url", instance.getUrl()); - final String jsonToSave = jsonWriter.end().done(); - sharedPreferences.edit().putString(selectedInstanceKey, jsonToSave).apply(); - ServiceList.PeerTube.setInstance(instance); - return instance; - } - - public static PeertubeInstance getCurrentInstance() { - return ServiceList.PeerTube.getInstance(); - } -} diff --git a/app/src/main/java/org/schabi/newpipe/util/PeertubeHelper.kt b/app/src/main/java/org/schabi/newpipe/util/PeertubeHelper.kt new file mode 100644 index 000000000..3da7958d2 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/PeertubeHelper.kt @@ -0,0 +1,53 @@ +/* + * SPDX-FileCopyrightText: 2019-2026 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.util + +import android.content.Context +import androidx.core.content.edit +import androidx.preference.PreferenceManager +import com.grack.nanojson.JsonObject +import com.grack.nanojson.JsonParser +import com.grack.nanojson.JsonWriter +import org.schabi.newpipe.R +import org.schabi.newpipe.extractor.ServiceList +import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance + +object PeertubeHelper { + @JvmStatic + fun getInstanceList(context: Context): List { + val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) + val savedInstanceListKey = context.getString(R.string.peertube_instance_list_key) + val savedJson = sharedPreferences.getString(savedInstanceListKey, null) + if (savedJson == null) { + return listOf(currentInstance) + } + + return runCatching { + JsonParser.`object`().from(savedJson).getArray("instances") + .filterIsInstance() + .map { PeertubeInstance(it.getString("url"), it.getString("name")) } + }.getOrDefault(listOf(currentInstance)) + } + + @JvmStatic + fun selectInstance(instance: PeertubeInstance, context: Context): PeertubeInstance { + val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) + val selectedInstanceKey = context.getString(R.string.peertube_selected_instance_key) + + val jsonWriter = JsonWriter.string().`object`() + jsonWriter.value("name", instance.name) + jsonWriter.value("url", instance.url) + val jsonToSave = jsonWriter.end().done() + + sharedPreferences.edit { putString(selectedInstanceKey, jsonToSave) } + ServiceList.PeerTube.instance = instance + return instance + } + + @JvmStatic + val currentInstance: PeertubeInstance + get() = ServiceList.PeerTube.instance +} From 6cf932b2a714a1011849b3b2eb2fce8d0808f4aa Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Fri, 9 Jan 2026 11:51:41 +0200 Subject: [PATCH 13/56] Convert newpipe/ExitActivity to kotlin --- .../java/org/schabi/newpipe/ExitActivity.java | 50 ------------------- .../java/org/schabi/newpipe/ExitActivity.kt | 38 ++++++++++++++ 2 files changed, 38 insertions(+), 50 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/ExitActivity.java create mode 100644 app/src/main/java/org/schabi/newpipe/ExitActivity.kt diff --git a/app/src/main/java/org/schabi/newpipe/ExitActivity.java b/app/src/main/java/org/schabi/newpipe/ExitActivity.java deleted file mode 100644 index bd1351f0c..000000000 --- a/app/src/main/java/org/schabi/newpipe/ExitActivity.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.schabi.newpipe; - -import android.annotation.SuppressLint; -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; - -import org.schabi.newpipe.util.NavigationHelper; - -/* - * Copyright (C) Hans-Christoph Steiner 2016 - * ExitActivity.java is part of NewPipe. - * - * NewPipe is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * NewPipe is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with NewPipe. If not, see . - */ - -public class ExitActivity extends Activity { - - public static void exitAndRemoveFromRecentApps(final Activity activity) { - final Intent intent = new Intent(activity, ExitActivity.class); - - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS - | Intent.FLAG_ACTIVITY_CLEAR_TASK - | Intent.FLAG_ACTIVITY_NO_ANIMATION); - - activity.startActivity(intent); - } - - @SuppressLint("NewApi") - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - finishAndRemoveTask(); - - NavigationHelper.restartApp(this); - } -} diff --git a/app/src/main/java/org/schabi/newpipe/ExitActivity.kt b/app/src/main/java/org/schabi/newpipe/ExitActivity.kt new file mode 100644 index 000000000..854a07c43 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/ExitActivity.kt @@ -0,0 +1,38 @@ +/* + * SPDX-FileCopyrightText: 2016-2026 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe + +import android.annotation.SuppressLint +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import org.schabi.newpipe.util.NavigationHelper +class ExitActivity : Activity() { + @SuppressLint("NewApi") + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + finishAndRemoveTask() + + NavigationHelper.restartApp(this) + } + + companion object { + @JvmStatic + fun exitAndRemoveFromRecentApps(activity: Activity) { + val intent = Intent(activity, ExitActivity::class.java) + + intent.addFlags( + Intent.FLAG_ACTIVITY_NEW_TASK + or Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS + or Intent.FLAG_ACTIVITY_CLEAR_TASK + or Intent.FLAG_ACTIVITY_NO_ANIMATION + ) + + activity.startActivity(intent) + } + } +} From d665a4f01688e09eecacfc815bd58f2c57bd09f4 Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Fri, 9 Jan 2026 12:11:48 +0200 Subject: [PATCH 14/56] Convert newpipe/util/NewPipeTextViewHelper to kotlin --- .../newpipe/util/NewPipeTextViewHelper.java | 61 ------------------- .../newpipe/util/NewPipeTextViewHelper.kt | 60 ++++++++++++++++++ 2 files changed, 60 insertions(+), 61 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java create mode 100644 app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.kt diff --git a/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java b/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java deleted file mode 100644 index cf1a9a03a..000000000 --- a/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.schabi.newpipe.util; - -import android.content.Context; -import android.text.Selection; -import android.text.Spannable; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import org.schabi.newpipe.util.external_communication.ShareUtils; -import org.schabi.newpipe.views.NewPipeEditText; -import org.schabi.newpipe.views.NewPipeTextView; - -public final class NewPipeTextViewHelper { - private NewPipeTextViewHelper() { - } - - /** - * Share the selected text of {@link NewPipeTextView NewPipeTextViews} and - * {@link NewPipeEditText NewPipeEditTexts} with - * {@link ShareUtils#shareText(Context, String, String)}. - * - *

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

- * - * @param textView the {@link TextView} on which sharing the selected text. It should be a - * {@link NewPipeTextView} or a {@link NewPipeEditText} (even if - * {@link TextView standard TextViews} are supported). - */ - public static void shareSelectedTextWithShareUtils(@NonNull final TextView textView) { - final CharSequence textViewText = textView.getText(); - shareSelectedTextIfNotNullAndNotEmpty(textView, getSelectedText(textView, textViewText)); - if (textViewText instanceof Spannable) { - Selection.setSelection((Spannable) textViewText, textView.getSelectionEnd()); - } - } - - @Nullable - private static CharSequence getSelectedText(@NonNull final TextView textView, - @Nullable final CharSequence text) { - if (!textView.hasSelection() || text == null) { - return null; - } - - final int start = textView.getSelectionStart(); - final int end = textView.getSelectionEnd(); - return String.valueOf(start > end ? text.subSequence(end, start) - : text.subSequence(start, end)); - } - - private static void shareSelectedTextIfNotNullAndNotEmpty( - @NonNull final TextView textView, - @Nullable final CharSequence selectedText) { - if (selectedText != null && selectedText.length() != 0) { - ShareUtils.shareText(textView.getContext(), "", selectedText.toString()); - } - } -} diff --git a/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.kt b/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.kt new file mode 100644 index 000000000..33046c967 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.kt @@ -0,0 +1,60 @@ +/* + * SPDX-FileCopyrightText: 2021-2026 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.util + +import android.text.Selection +import android.text.Spannable +import android.widget.TextView +import org.schabi.newpipe.util.external_communication.ShareUtils + +object NewPipeTextViewHelper { + /** + * Share the selected text of [NewPipeTextViews][org.schabi.newpipe.views.NewPipeTextView] and + * [NewPipeEditTexts][org.schabi.newpipe.views.NewPipeEditText] with + * [ShareUtils.shareText]. + * + * + * + * This allows EMUI users to get the Android share sheet instead of the EMUI share sheet when + * using the `Share` command of the popup menu which appears when selecting text. + * + * + * @param textView the [TextView] on which sharing the selected text. It should be a + * [org.schabi.newpipe.views.NewPipeTextView] or a [org.schabi.newpipe.views.NewPipeEditText] + * (even if [standard TextViews][TextView] are supported). + */ + @JvmStatic + fun shareSelectedTextWithShareUtils(textView: TextView) { + val textViewText = textView.getText() + shareSelectedTextIfNotNullAndNotEmpty(textView, getSelectedText(textView, textViewText)) + if (textViewText is Spannable) { + Selection.setSelection(textViewText, textView.selectionEnd) + } + } + + private fun getSelectedText(textView: TextView, text: CharSequence?): CharSequence? { + if (!textView.hasSelection() || text == null) { + return null + } + + val start = textView.selectionStart + val end = textView.selectionEnd + return if (start > end) { + text.subSequence(end, start) + } else { + text.subSequence(start, end) + } + } + + private fun shareSelectedTextIfNotNullAndNotEmpty( + textView: TextView, + selectedText: CharSequence? + ) { + if (!selectedText.isNullOrEmpty()) { + ShareUtils.shareText(textView.getContext(), "", selectedText.toString()) + } + } +} From 09a746dd6a131bee665ed44e7cff1d554b85e9bb Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Fri, 9 Jan 2026 12:45:56 +0200 Subject: [PATCH 15/56] Convert newpipe/util/ServiceHelper to kotlin --- .../schabi/newpipe/util/ServiceHelper.java | 213 ------------------ .../org/schabi/newpipe/util/ServiceHelper.kt | 173 ++++++++++++++ 2 files changed, 173 insertions(+), 213 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/util/ServiceHelper.java create mode 100644 app/src/main/java/org/schabi/newpipe/util/ServiceHelper.kt diff --git a/app/src/main/java/org/schabi/newpipe/util/ServiceHelper.java b/app/src/main/java/org/schabi/newpipe/util/ServiceHelper.java deleted file mode 100644 index c712157b3..000000000 --- a/app/src/main/java/org/schabi/newpipe/util/ServiceHelper.java +++ /dev/null @@ -1,213 +0,0 @@ -package org.schabi.newpipe.util; - -import static org.schabi.newpipe.extractor.ServiceList.SoundCloud; - -import android.content.Context; -import android.content.SharedPreferences; - -import androidx.annotation.DrawableRes; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.StringRes; -import androidx.preference.PreferenceManager; - -import com.grack.nanojson.JsonObject; -import com.grack.nanojson.JsonParser; -import com.grack.nanojson.JsonParserException; - -import org.schabi.newpipe.R; -import org.schabi.newpipe.extractor.NewPipe; -import org.schabi.newpipe.extractor.ServiceList; -import org.schabi.newpipe.extractor.StreamingService; -import org.schabi.newpipe.extractor.exceptions.ExtractionException; -import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance; - -import java.util.Optional; -import java.util.concurrent.TimeUnit; - -public final class ServiceHelper { - private static final StreamingService DEFAULT_FALLBACK_SERVICE = ServiceList.YouTube; - - private ServiceHelper() { } - - @DrawableRes - public static int getIcon(final int serviceId) { - switch (serviceId) { - case 0: - return R.drawable.ic_smart_display; - case 1: - return R.drawable.ic_cloud; - case 2: - return R.drawable.ic_placeholder_media_ccc; - case 3: - return R.drawable.ic_placeholder_peertube; - case 4: - return R.drawable.ic_placeholder_bandcamp; - default: - return R.drawable.ic_circle; - } - } - - public static String getTranslatedFilterString(final String filter, final Context c) { - switch (filter) { - case "all": - return c.getString(R.string.all); - case "videos": - case "sepia_videos": - case "music_videos": - return c.getString(R.string.videos_string); - case "channels": - return c.getString(R.string.channels); - case "playlists": - case "music_playlists": - return c.getString(R.string.playlists); - case "tracks": - return c.getString(R.string.tracks); - case "users": - return c.getString(R.string.users); - case "conferences": - return c.getString(R.string.conferences); - case "events": - return c.getString(R.string.events); - case "music_songs": - return c.getString(R.string.songs); - case "music_albums": - return c.getString(R.string.albums); - case "music_artists": - return c.getString(R.string.artists); - default: - return filter; - } - } - - /** - * Get a resource string with instructions for importing subscriptions for each service. - * - * @param serviceId service to get the instructions for - * @return the string resource containing the instructions or -1 if the service don't support it - */ - @StringRes - public static int getImportInstructions(final int serviceId) { - switch (serviceId) { - case 0: - return R.string.import_youtube_instructions; - case 1: - return R.string.import_soundcloud_instructions; - default: - return -1; - } - } - - /** - * For services that support importing from a channel url, return a hint that will - * be used in the EditText that the user will type in his channel url. - * - * @param serviceId service to get the hint for - * @return the hint's string resource or -1 if the service don't support it - */ - @StringRes - public static int getImportInstructionsHint(final int serviceId) { - switch (serviceId) { - case 1: - return R.string.import_soundcloud_instructions_hint; - default: - return -1; - } - } - - public static int getSelectedServiceId(final Context context) { - return Optional.ofNullable(getSelectedService(context)) - .orElse(DEFAULT_FALLBACK_SERVICE) - .getServiceId(); - } - - @Nullable - public static StreamingService getSelectedService(final Context context) { - final String serviceName = PreferenceManager.getDefaultSharedPreferences(context) - .getString(context.getString(R.string.current_service_key), - context.getString(R.string.default_service_value)); - - try { - return NewPipe.getService(serviceName); - } catch (final ExtractionException e) { - return null; - } - } - - @NonNull - public static String getNameOfServiceById(final int serviceId) { - return ServiceList.all().stream() - .filter(s -> s.getServiceId() == serviceId) - .findFirst() - .map(StreamingService::getServiceInfo) - .map(StreamingService.ServiceInfo::getName) - .orElse(""); - } - - /** - * @param serviceId the id of the service - * @return the service corresponding to the provided id - * @throws java.util.NoSuchElementException if there is no service with the provided id - */ - @NonNull - public static StreamingService getServiceById(final int serviceId) { - return ServiceList.all().stream() - .filter(s -> s.getServiceId() == serviceId) - .findFirst() - .orElseThrow(); - } - - public static void setSelectedServiceId(final Context context, final int serviceId) { - String serviceName; - try { - serviceName = NewPipe.getService(serviceId).getServiceInfo().getName(); - } catch (final ExtractionException e) { - serviceName = DEFAULT_FALLBACK_SERVICE.getServiceInfo().getName(); - } - - setSelectedServicePreferences(context, serviceName); - } - - private static void setSelectedServicePreferences(final Context context, - final String serviceName) { - PreferenceManager.getDefaultSharedPreferences(context).edit(). - putString(context.getString(R.string.current_service_key), serviceName).apply(); - } - - public static long getCacheExpirationMillis(final int serviceId) { - if (serviceId == SoundCloud.getServiceId()) { - return TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES); - } else { - return TimeUnit.MILLISECONDS.convert(1, TimeUnit.HOURS); - } - } - - public static void initService(final Context context, final int serviceId) { - if (serviceId == ServiceList.PeerTube.getServiceId()) { - final SharedPreferences sharedPreferences = PreferenceManager - .getDefaultSharedPreferences(context); - final String json = sharedPreferences.getString(context.getString( - R.string.peertube_selected_instance_key), null); - if (null == json) { - return; - } - - final JsonObject jsonObject; - try { - jsonObject = JsonParser.object().from(json); - } catch (final JsonParserException e) { - return; - } - final String name = jsonObject.getString("name"); - final String url = jsonObject.getString("url"); - final PeertubeInstance instance = new PeertubeInstance(url, name); - ServiceList.PeerTube.setInstance(instance); - } - } - - public static void initServices(final Context context) { - for (final StreamingService s : ServiceList.all()) { - initService(context, s.getServiceId()); - } - } -} diff --git a/app/src/main/java/org/schabi/newpipe/util/ServiceHelper.kt b/app/src/main/java/org/schabi/newpipe/util/ServiceHelper.kt new file mode 100644 index 000000000..99cae0010 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/ServiceHelper.kt @@ -0,0 +1,173 @@ +/* + * SPDX-FileCopyrightText: 2018-2026 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.util + +import android.content.Context +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import androidx.core.content.edit +import androidx.preference.PreferenceManager +import com.grack.nanojson.JsonObject +import com.grack.nanojson.JsonParser +import com.grack.nanojson.JsonParserException +import java.util.concurrent.TimeUnit +import org.schabi.newpipe.R +import org.schabi.newpipe.extractor.NewPipe +import org.schabi.newpipe.extractor.ServiceList +import org.schabi.newpipe.extractor.StreamingService +import org.schabi.newpipe.extractor.exceptions.ExtractionException +import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance +import org.schabi.newpipe.ktx.getStringSafe + +object ServiceHelper { + private val DEFAULT_FALLBACK_SERVICE: StreamingService = ServiceList.YouTube + + @JvmStatic + @DrawableRes + fun getIcon(serviceId: Int): Int { + return when (serviceId) { + 0 -> R.drawable.ic_smart_display + 1 -> R.drawable.ic_cloud + 2 -> R.drawable.ic_placeholder_media_ccc + 3 -> R.drawable.ic_placeholder_peertube + 4 -> R.drawable.ic_placeholder_bandcamp + else -> R.drawable.ic_circle + } + } + + @JvmStatic + fun getTranslatedFilterString(filter: String, context: Context): String { + return when (filter) { + "all" -> context.getString(R.string.all) + "videos", "sepia_videos", "music_videos" -> context.getString(R.string.videos_string) + "channels" -> context.getString(R.string.channels) + "playlists", "music_playlists" -> context.getString(R.string.playlists) + "tracks" -> context.getString(R.string.tracks) + "users" -> context.getString(R.string.users) + "conferences" -> context.getString(R.string.conferences) + "events" -> context.getString(R.string.events) + "music_songs" -> context.getString(R.string.songs) + "music_albums" -> context.getString(R.string.albums) + "music_artists" -> context.getString(R.string.artists) + else -> filter + } + } + + /** + * Get a resource string with instructions for importing subscriptions for each service. + * + * @param serviceId service to get the instructions for + * @return the string resource containing the instructions or -1 if the service don't support it + */ + @JvmStatic + @StringRes + fun getImportInstructions(serviceId: Int): Int { + return when (serviceId) { + 0 -> R.string.import_youtube_instructions + 1 -> R.string.import_soundcloud_instructions + else -> -1 + } + } + + /** + * For services that support importing from a channel url, return a hint that will + * be used in the EditText that the user will type in his channel url. + * + * @param serviceId service to get the hint for + * @return the hint's string resource or -1 if the service don't support it + */ + @JvmStatic + @StringRes + fun getImportInstructionsHint(serviceId: Int): Int { + return when (serviceId) { + 1 -> R.string.import_soundcloud_instructions_hint + else -> -1 + } + } + + @JvmStatic + fun getSelectedServiceId(context: Context): Int { + return (getSelectedService(context) ?: DEFAULT_FALLBACK_SERVICE).serviceId + } + + @JvmStatic + fun getSelectedService(context: Context): StreamingService? { + val serviceName: String = PreferenceManager.getDefaultSharedPreferences(context) + .getStringSafe( + context.getString(R.string.current_service_key), + context.getString(R.string.default_service_value) + ) + + return runCatching { NewPipe.getService(serviceName) }.getOrNull() + } + + @JvmStatic + fun getNameOfServiceById(serviceId: Int): String { + return ServiceList.all().stream() + .filter { it.serviceId == serviceId } + .findFirst() + .map(StreamingService::getServiceInfo) + .map(StreamingService.ServiceInfo::getName) + .orElse("") + } + + /** + * @param serviceId the id of the service + * @return the service corresponding to the provided id + * @throws java.util.NoSuchElementException if there is no service with the provided id + */ + @JvmStatic + fun getServiceById(serviceId: Int): StreamingService { + return ServiceList.all().firstNotNullOf { it.takeIf { it.serviceId == serviceId } } + } + + @JvmStatic + fun setSelectedServiceId(context: Context, serviceId: Int) { + val serviceName = runCatching { NewPipe.getService(serviceId).serviceInfo.name } + .getOrDefault(DEFAULT_FALLBACK_SERVICE.serviceInfo.name) + + setSelectedServicePreferences(context, serviceName) + } + + private fun setSelectedServicePreferences(context: Context, serviceName: String?) { + val sp = PreferenceManager.getDefaultSharedPreferences(context) + sp.edit { putString(context.getString(R.string.current_service_key), serviceName) } + } + + @JvmStatic + fun getCacheExpirationMillis(serviceId: Int): Long { + return if (serviceId == ServiceList.SoundCloud.serviceId) { + TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES) + } else { + TimeUnit.MILLISECONDS.convert(1, TimeUnit.HOURS) + } + } + + fun initService(context: Context, serviceId: Int) { + if (serviceId == ServiceList.PeerTube.serviceId) { + val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) + val json = sharedPreferences.getString( + context.getString(R.string.peertube_selected_instance_key), + null + ) + if (null == json) { + return + } + + val jsonObject = runCatching { JsonParser.`object`().from(json) } + .getOrElse { return@initService } + + val name = jsonObject.getString("name") + val url = jsonObject.getString("url") + ServiceList.PeerTube.instance = PeertubeInstance(url, name) + } + } + + @JvmStatic + fun initServices(context: Context) { + ServiceList.all().forEach { initService(context, it.serviceId) } + } +} From 2c7654a579357f0a83edd5c1de26c8f73f149a04 Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Fri, 9 Jan 2026 12:54:36 +0200 Subject: [PATCH 16/56] Covert newpipe/util/DependentPreferenceHelper to kotlin --- .../util/DependentPreferenceHelper.java | 51 ------------------- .../newpipe/util/DependentPreferenceHelper.kt | 46 +++++++++++++++++ 2 files changed, 46 insertions(+), 51 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/util/DependentPreferenceHelper.java create mode 100644 app/src/main/java/org/schabi/newpipe/util/DependentPreferenceHelper.kt diff --git a/app/src/main/java/org/schabi/newpipe/util/DependentPreferenceHelper.java b/app/src/main/java/org/schabi/newpipe/util/DependentPreferenceHelper.java deleted file mode 100644 index 9591beddb..000000000 --- a/app/src/main/java/org/schabi/newpipe/util/DependentPreferenceHelper.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.schabi.newpipe.util; - -import android.content.Context; -import android.content.SharedPreferences; - -import androidx.preference.PreferenceManager; - -import org.schabi.newpipe.R; - -/** - * For preferences with dependencies and multiple use case, - * this class can be used to reduce the lines of code. - */ -public final class DependentPreferenceHelper { - - private DependentPreferenceHelper() { - // no instance - } - - /** - * Option `Resume playback` depends on `Watch history`, this method can be used to retrieve if - * `Resume playback` and its dependencies are all enabled. - * - * @param context the Android context - * @return returns true if `Resume playback` and `Watch history` are both enabled - */ - public static boolean getResumePlaybackEnabled(final Context context) { - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - - return prefs.getBoolean(context.getString( - R.string.enable_watch_history_key), true) - && prefs.getBoolean(context.getString( - R.string.enable_playback_resume_key), true); - } - - /** - * Option `Position in lists` depends on `Watch history`, this method can be used to retrieve if - * `Position in lists` and its dependencies are all enabled. - * - * @param context the Android context - * @return returns true if `Positions in lists` and `Watch history` are both enabled - */ - public static boolean getPositionsInListsEnabled(final Context context) { - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - - return prefs.getBoolean(context.getString( - R.string.enable_watch_history_key), true) - && prefs.getBoolean(context.getString( - R.string.enable_playback_state_lists_key), true); - } -} diff --git a/app/src/main/java/org/schabi/newpipe/util/DependentPreferenceHelper.kt b/app/src/main/java/org/schabi/newpipe/util/DependentPreferenceHelper.kt new file mode 100644 index 000000000..8e73a94f2 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/DependentPreferenceHelper.kt @@ -0,0 +1,46 @@ +/* + * SPDX-FileCopyrightText: 2023-2026 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.util + +import android.content.Context +import androidx.preference.PreferenceManager +import org.schabi.newpipe.R + +/** + * For preferences with dependencies and multiple use case, + * this class can be used to reduce the lines of code. + */ +object DependentPreferenceHelper { + /** + * Option `Resume playback` depends on `Watch history`, this method can be used to retrieve if + * `Resume playback` and its dependencies are all enabled. + * + * @param context the Android context + * @return returns true if `Resume playback` and `Watch history` are both enabled + */ + @JvmStatic + fun getResumePlaybackEnabled(context: Context): Boolean { + val prefs = PreferenceManager.getDefaultSharedPreferences(context) + + return prefs.getBoolean(context.getString(R.string.enable_watch_history_key), true) && + prefs.getBoolean(context.getString(R.string.enable_playback_resume_key), true) + } + + /** + * Option `Position in lists` depends on `Watch history`, this method can be used to retrieve if + * `Position in lists` and its dependencies are all enabled. + * + * @param context the Android context + * @return returns true if `Positions in lists` and `Watch history` are both enabled + */ + @JvmStatic + fun getPositionsInListsEnabled(context: Context): Boolean { + val prefs = PreferenceManager.getDefaultSharedPreferences(context) + + return prefs.getBoolean(context.getString(R.string.enable_watch_history_key), true) && + prefs.getBoolean(context.getString(R.string.enable_playback_state_lists_key), true) + } +} From 1eedfd7eee3d45640caa485b77df50d17ba57dd2 Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Fri, 9 Jan 2026 13:11:29 +0200 Subject: [PATCH 17/56] Convert /newpipe/util/StreamTypeUtil to kotlin --- .../schabi/newpipe/util/StreamTypeUtil.java | 50 ----------------- .../org/schabi/newpipe/util/StreamTypeUtil.kt | 54 +++++++++++++++++++ 2 files changed, 54 insertions(+), 50 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/util/StreamTypeUtil.java create mode 100644 app/src/main/java/org/schabi/newpipe/util/StreamTypeUtil.kt diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamTypeUtil.java b/app/src/main/java/org/schabi/newpipe/util/StreamTypeUtil.java deleted file mode 100644 index 0cc0ecf1f..000000000 --- a/app/src/main/java/org/schabi/newpipe/util/StreamTypeUtil.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.schabi.newpipe.util; - -import org.schabi.newpipe.extractor.stream.StreamType; - -/** - * Utility class for {@link StreamType}. - */ -public final class StreamTypeUtil { - private StreamTypeUtil() { - // No impl pls - } - - /** - * Check if the {@link StreamType} of a stream is a livestream. - * - * @param streamType the stream type of the stream - * @return whether the stream type is {@link StreamType#AUDIO_STREAM}, - * {@link StreamType#AUDIO_LIVE_STREAM} or {@link StreamType#POST_LIVE_AUDIO_STREAM} - */ - public static boolean isAudio(final StreamType streamType) { - return streamType == StreamType.AUDIO_STREAM - || streamType == StreamType.AUDIO_LIVE_STREAM - || streamType == StreamType.POST_LIVE_AUDIO_STREAM; - } - - /** - * Check if the {@link StreamType} of a stream is a livestream. - * - * @param streamType the stream type of the stream - * @return whether the stream type is {@link StreamType#VIDEO_STREAM}, - * {@link StreamType#LIVE_STREAM} or {@link StreamType#POST_LIVE_STREAM} - */ - public static boolean isVideo(final StreamType streamType) { - return streamType == StreamType.VIDEO_STREAM - || streamType == StreamType.LIVE_STREAM - || streamType == StreamType.POST_LIVE_STREAM; - } - - /** - * Check if the {@link StreamType} of a stream is a livestream. - * - * @param streamType the stream type of the stream - * @return whether the stream type is {@link StreamType#LIVE_STREAM} or - * {@link StreamType#AUDIO_LIVE_STREAM} - */ - public static boolean isLiveStream(final StreamType streamType) { - return streamType == StreamType.LIVE_STREAM - || streamType == StreamType.AUDIO_LIVE_STREAM; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamTypeUtil.kt b/app/src/main/java/org/schabi/newpipe/util/StreamTypeUtil.kt new file mode 100644 index 000000000..2401a4f49 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/StreamTypeUtil.kt @@ -0,0 +1,54 @@ +/* + * SPDX-FileCopyrightText: 2021-2026 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.util + +import org.schabi.newpipe.extractor.stream.StreamType + +/** + * Utility class for [StreamType]. + */ +object StreamTypeUtil { + /** + * Check if the [StreamType] of a stream is a livestream. + * + * @param streamType the stream type of the stream + * @return whether the stream type is [StreamType.AUDIO_STREAM], + * [StreamType.AUDIO_LIVE_STREAM] or [StreamType.POST_LIVE_AUDIO_STREAM] + */ + @JvmStatic + fun isAudio(streamType: StreamType): Boolean { + return streamType == StreamType.AUDIO_STREAM || + streamType == StreamType.AUDIO_LIVE_STREAM || + streamType == StreamType.POST_LIVE_AUDIO_STREAM + } + + /** + * Check if the [StreamType] of a stream is a livestream. + * + * @param streamType the stream type of the stream + * @return whether the stream type is [StreamType.VIDEO_STREAM], + * [StreamType.LIVE_STREAM] or [StreamType.POST_LIVE_STREAM] + */ + @JvmStatic + fun isVideo(streamType: StreamType): Boolean { + return streamType == StreamType.VIDEO_STREAM || + streamType == StreamType.LIVE_STREAM || + streamType == StreamType.POST_LIVE_STREAM + } + + /** + * Check if the [StreamType] of a stream is a livestream. + * + * @param streamType the stream type of the stream + * @return whether the stream type is [StreamType.LIVE_STREAM] or + * [StreamType.AUDIO_LIVE_STREAM] + */ + @JvmStatic + fun isLiveStream(streamType: StreamType): Boolean { + return streamType == StreamType.LIVE_STREAM || + streamType == StreamType.AUDIO_LIVE_STREAM + } +} From c6fc94e7bd65e15315e94a66f001c7c29d4cbc42 Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Fri, 9 Jan 2026 15:26:43 +0200 Subject: [PATCH 18/56] Convert newpipe/settings/export/PreferencesObjectInputStream to kotlin --- .../export/PreferencesObjectInputStream.java | 58 ------------------- .../export/PreferencesObjectInputStream.kt | 52 +++++++++++++++++ 2 files changed, 52 insertions(+), 58 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/settings/export/PreferencesObjectInputStream.java create mode 100644 app/src/main/java/org/schabi/newpipe/settings/export/PreferencesObjectInputStream.kt diff --git a/app/src/main/java/org/schabi/newpipe/settings/export/PreferencesObjectInputStream.java b/app/src/main/java/org/schabi/newpipe/settings/export/PreferencesObjectInputStream.java deleted file mode 100644 index 0d11b0b61..000000000 --- a/app/src/main/java/org/schabi/newpipe/settings/export/PreferencesObjectInputStream.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.schabi.newpipe.settings.export; - -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectStreamClass; -import java.util.Set; - -/** - * An {@link ObjectInputStream} that only allows preferences-related types to be deserialized, to - * prevent injections. The only allowed types are: all primitive types, all boxed primitive types, - * null, strings. HashMap, HashSet and arrays of previously defined types are also allowed. Sources: - * - * cmu.edu - * , - * - * OWASP cheatsheet - * , - * - * Apache's {@code ValidatingObjectInputStream} - * - */ -public class PreferencesObjectInputStream extends ObjectInputStream { - - /** - * Primitive types, strings and other built-in types do not pass through resolveClass() but - * instead have a custom encoding; see - * - * official docs. - */ - private static final Set CLASS_WHITELIST = Set.of( - "java.lang.Boolean", - "java.lang.Byte", - "java.lang.Character", - "java.lang.Short", - "java.lang.Integer", - "java.lang.Long", - "java.lang.Float", - "java.lang.Double", - "java.lang.Void", - "java.util.HashMap", - "java.util.HashSet" - ); - - public PreferencesObjectInputStream(final InputStream in) throws IOException { - super(in); - } - - @Override - protected Class resolveClass(final ObjectStreamClass desc) - throws ClassNotFoundException, IOException { - if (CLASS_WHITELIST.contains(desc.getName())) { - return super.resolveClass(desc); - } else { - throw new ClassNotFoundException("Class not allowed: " + desc.getName()); - } - } -} diff --git a/app/src/main/java/org/schabi/newpipe/settings/export/PreferencesObjectInputStream.kt b/app/src/main/java/org/schabi/newpipe/settings/export/PreferencesObjectInputStream.kt new file mode 100644 index 000000000..5f564a7a4 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/settings/export/PreferencesObjectInputStream.kt @@ -0,0 +1,52 @@ +/* + * SPDX-FileCopyrightText: 2024-2026 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.settings.export + +import java.io.IOException +import java.io.InputStream +import java.io.ObjectInputStream +import java.io.ObjectStreamClass + +/** + * An [ObjectInputStream] that only allows preferences-related types to be deserialized, to + * prevent injections. The only allowed types are: all primitive types, all boxed primitive types, + * null, strings. HashMap, HashSet and arrays of previously defined types are also allowed. Sources: + * [cmu.edu](https://wiki.sei.cmu.edu/confluence/display/java/SER00-J.+Enable+serialization+compatibility+during+class+evolution) * , + * [OWASP cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#harden-your-own-javaioobjectinputstream) * , + * [Apache's `ValidatingObjectInputStream`](https://commons.apache.org/proper/commons-io/apidocs/src-html/org/apache/commons/io/serialization/ValidatingObjectInputStream.html#line-118) * + */ +class PreferencesObjectInputStream(stream: InputStream) : ObjectInputStream(stream) { + @Throws(ClassNotFoundException::class, IOException::class) + override fun resolveClass(desc: ObjectStreamClass): Class<*> { + if (desc.name in CLASS_WHITELIST) { + return super.resolveClass(desc) + } else { + throw ClassNotFoundException("Class not allowed: $desc.name") + } + } + + companion object { + /** + * Primitive types, strings and other built-in types do not pass through resolveClass() but + * instead have a custom encoding; see + * [ + * official docs](https://docs.oracle.com/javase/6/docs/platform/serialization/spec/protocol.html#10152). + */ + private val CLASS_WHITELIST = setOf( + "java.lang.Boolean", + "java.lang.Byte", + "java.lang.Character", + "java.lang.Short", + "java.lang.Integer", + "java.lang.Long", + "java.lang.Float", + "java.lang.Double", + "java.lang.Void", + "java.util.HashMap", + "java.util.HashSet" + ) + } +} From 224a5d0cb9d4682986ba060b60bd7ff2bfc77482 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Tue, 10 Feb 2026 16:32:53 +0800 Subject: [PATCH 19/56] Minor improvements - Use early return in case of nulls - Use better variable names - Remove non-required newlines, imports and add missing ones Signed-off-by: Aayush Gupta --- .../java/org/schabi/newpipe/ExitActivity.kt | 4 +--- .../newpipe/util/NewPipeTextViewHelper.kt | 2 +- .../org/schabi/newpipe/util/PeertubeHelper.kt | 13 ++++++------- .../org/schabi/newpipe/util/ServiceHelper.kt | 19 +++++++------------ 4 files changed, 15 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/ExitActivity.kt b/app/src/main/java/org/schabi/newpipe/ExitActivity.kt index 854a07c43..cc9f448b7 100644 --- a/app/src/main/java/org/schabi/newpipe/ExitActivity.kt +++ b/app/src/main/java/org/schabi/newpipe/ExitActivity.kt @@ -10,13 +10,12 @@ import android.app.Activity import android.content.Intent import android.os.Bundle import org.schabi.newpipe.util.NavigationHelper + class ExitActivity : Activity() { @SuppressLint("NewApi") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - finishAndRemoveTask() - NavigationHelper.restartApp(this) } @@ -24,7 +23,6 @@ class ExitActivity : Activity() { @JvmStatic fun exitAndRemoveFromRecentApps(activity: Activity) { val intent = Intent(activity, ExitActivity::class.java) - intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS diff --git a/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.kt b/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.kt index 33046c967..159791813 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.kt +++ b/app/src/main/java/org/schabi/newpipe/util/NewPipeTextViewHelper.kt @@ -54,7 +54,7 @@ object NewPipeTextViewHelper { selectedText: CharSequence? ) { if (!selectedText.isNullOrEmpty()) { - ShareUtils.shareText(textView.getContext(), "", selectedText.toString()) + ShareUtils.shareText(textView.context, "", selectedText.toString()) } } } diff --git a/app/src/main/java/org/schabi/newpipe/util/PeertubeHelper.kt b/app/src/main/java/org/schabi/newpipe/util/PeertubeHelper.kt index 3da7958d2..9cf3c1e73 100644 --- a/app/src/main/java/org/schabi/newpipe/util/PeertubeHelper.kt +++ b/app/src/main/java/org/schabi/newpipe/util/PeertubeHelper.kt @@ -16,14 +16,17 @@ import org.schabi.newpipe.extractor.ServiceList import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance object PeertubeHelper { + + @JvmStatic + val currentInstance: PeertubeInstance + get() = ServiceList.PeerTube.instance + @JvmStatic fun getInstanceList(context: Context): List { val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) val savedInstanceListKey = context.getString(R.string.peertube_instance_list_key) val savedJson = sharedPreferences.getString(savedInstanceListKey, null) - if (savedJson == null) { - return listOf(currentInstance) - } + ?: return listOf(currentInstance) return runCatching { JsonParser.`object`().from(savedJson).getArray("instances") @@ -46,8 +49,4 @@ object PeertubeHelper { ServiceList.PeerTube.instance = instance return instance } - - @JvmStatic - val currentInstance: PeertubeInstance - get() = ServiceList.PeerTube.instance } diff --git a/app/src/main/java/org/schabi/newpipe/util/ServiceHelper.kt b/app/src/main/java/org/schabi/newpipe/util/ServiceHelper.kt index 99cae0010..4239f43e0 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ServiceHelper.kt +++ b/app/src/main/java/org/schabi/newpipe/util/ServiceHelper.kt @@ -10,15 +10,12 @@ import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.core.content.edit import androidx.preference.PreferenceManager -import com.grack.nanojson.JsonObject import com.grack.nanojson.JsonParser -import com.grack.nanojson.JsonParserException import java.util.concurrent.TimeUnit import org.schabi.newpipe.R import org.schabi.newpipe.extractor.NewPipe import org.schabi.newpipe.extractor.ServiceList import org.schabi.newpipe.extractor.StreamingService -import org.schabi.newpipe.extractor.exceptions.ExtractionException import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance import org.schabi.newpipe.ktx.getStringSafe @@ -133,8 +130,8 @@ object ServiceHelper { } private fun setSelectedServicePreferences(context: Context, serviceName: String?) { - val sp = PreferenceManager.getDefaultSharedPreferences(context) - sp.edit { putString(context.getString(R.string.current_service_key), serviceName) } + val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) + sharedPreferences.edit { putString(context.getString(R.string.current_service_key), serviceName) } } @JvmStatic @@ -152,17 +149,15 @@ object ServiceHelper { val json = sharedPreferences.getString( context.getString(R.string.peertube_selected_instance_key), null - ) - if (null == json) { - return - } + ) ?: return val jsonObject = runCatching { JsonParser.`object`().from(json) } .getOrElse { return@initService } - val name = jsonObject.getString("name") - val url = jsonObject.getString("url") - ServiceList.PeerTube.instance = PeertubeInstance(url, name) + ServiceList.PeerTube.instance = PeertubeInstance( + jsonObject.getString("url"), + jsonObject.getString("name") + ) } } From 59e5018c2d9b58de333f7bdab5c3f66f4c14f4dd Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Wed, 28 Jan 2026 20:25:47 +0200 Subject: [PATCH 20/56] player/helper/PlayerHelper#getTimeString replace ints with longs Duration data in the player code incosnistently typed. Half code uses ints and half uses longs. Recieve longs in this function to allow both halfs of player code just use the function without nasty long to int downcasting warnings/errors in code --- .../org/schabi/newpipe/player/helper/PlayerHelper.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java index 0f9579352..11d39a5c5 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java @@ -87,11 +87,11 @@ public final class PlayerHelper { } @NonNull - public static String getTimeString(final int milliSeconds) { - final int seconds = (milliSeconds % 60000) / 1000; - final int minutes = (milliSeconds % 3600000) / 60000; - final int hours = (milliSeconds % 86400000) / 3600000; - final int days = (milliSeconds % (86400000 * 7)) / 86400000; + public static String getTimeString(final long milliSeconds) { + final long seconds = (milliSeconds % 60000) / 1000; + final long minutes = (milliSeconds % 3600000) / 60000; + final long hours = (milliSeconds % 86400000) / 3600000; + final long days = (milliSeconds % (86400000 * 7)) / 86400000; final Formatters formatters = FORMATTERS_PROVIDER.formatters(); if (days > 0) { From 3a0a3a42afc91b31d0ee0184a85caaf658ebc0e2 Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Wed, 28 Jan 2026 20:14:36 +0200 Subject: [PATCH 21/56] Misc loop/stream based player refactors --- .../newpipe/player/helper/PlayerHelper.java | 9 ++++--- .../player/playqueue/SinglePlayQueue.java | 8 ++----- .../newpipe/player/ui/MainPlayerUi.java | 24 +++++++------------ 3 files changed, 14 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java index 11d39a5c5..25844f799 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java @@ -49,12 +49,12 @@ import java.text.DecimalFormatSymbols; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.Set; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; public final class PlayerHelper { private static final FormattersProvider FORMATTERS_PROVIDER = new FormattersProvider(); @@ -174,10 +174,9 @@ public final class PlayerHelper { @Nullable public static PlayQueue autoQueueOf(@NonNull final StreamInfo info, @NonNull final List existingItems) { - final Set urls = new HashSet<>(existingItems.size()); - for (final PlayQueueItem item : existingItems) { - urls.add(item.getUrl()); - } + final Set urls = existingItems.stream() + .map(PlayQueueItem::getUrl) + .collect(Collectors.toUnmodifiableSet()); final List relatedItems = info.getRelatedItems(); if (Utils.isNullOrEmpty(relatedItems)) { diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/SinglePlayQueue.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/SinglePlayQueue.java index f13d7924d..a072369d6 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/SinglePlayQueue.java +++ b/app/src/main/java/org/schabi/newpipe/player/playqueue/SinglePlayQueue.java @@ -5,8 +5,8 @@ import androidx.annotation.NonNull; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; public final class SinglePlayQueue extends PlayQueue { public SinglePlayQueue(final StreamInfoItem item) { @@ -29,11 +29,7 @@ public final class SinglePlayQueue extends PlayQueue { } private static List playQueueItemsOf(@NonNull final List items) { - final List playQueueItems = new ArrayList<>(items.size()); - for (final StreamInfoItem item : items) { - playQueueItems.add(new PlayQueueItem(item)); - } - return playQueueItems; + return items.stream().map(PlayQueueItem::new).collect(Collectors.toList()); } @Override diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java index 868881782..4d85dc950 100644 --- a/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java +++ b/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java @@ -77,6 +77,7 @@ import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.stream.Collectors; public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutChangeListener { private static final String TAG = MainPlayerUi.class.getSimpleName(); @@ -749,13 +750,13 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh } private int getNearestStreamSegmentPosition(final long playbackPosition) { - int nearestPosition = 0; final List segments = player.getCurrentStreamInfo() .map(StreamInfo::getStreamSegments) .orElse(Collections.emptyList()); - for (int i = 0; i < segments.size(); i++) { - if (segments.get(i).getStartTimeSeconds() * 1000L > playbackPosition) { + int nearestPosition = 0; + for (final var segment : segments) { + if (segment.getStartTimeSeconds() * 1000L > playbackPosition) { break; } nearestPosition++; @@ -816,22 +817,13 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh } final int currentStream = playQueue.getIndex(); - int before = 0; - int after = 0; - final List streams = playQueue.getStreams(); - final int nStreams = streams.size(); - for (int i = 0; i < nStreams; i++) { - if (i < currentStream) { - before += streams.get(i).getDuration(); - } else { - after += streams.get(i).getDuration(); - } - } + final long before = streams.subList(0, currentStream).stream() + .collect(Collectors.summingLong(PlayQueueItem::getDuration)) * 1000; - before *= 1000; - after *= 1000; + final long after = streams.subList(currentStream, streams.size()).stream() + .collect(Collectors.summingLong(PlayQueueItem::getDuration)) * 1000; binding.itemsListHeaderDuration.setText( String.format("%s/%s", From 869a3cea9b54f6af798873f7fab841fa3f16370a Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Tue, 10 Feb 2026 01:32:18 +0200 Subject: [PATCH 22/56] ErrorActivity small refactor --- .../schabi/newpipe/error/ErrorActivity.java | 31 ++++++------------- 1 file changed, 10 insertions(+), 21 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 160dcca4d..e183ebd71 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java @@ -85,8 +85,6 @@ public class ErrorActivity extends AppCompatActivity { activityErrorBinding = ActivityErrorBinding.inflate(getLayoutInflater()); setContentView(activityErrorBinding.getRoot()); - final Intent intent = getIntent(); - setSupportActionBar(activityErrorBinding.toolbarLayout.toolbar); final ActionBar actionBar = getSupportActionBar(); @@ -96,13 +94,12 @@ public class ErrorActivity extends AppCompatActivity { actionBar.setDisplayShowTitleEnabled(true); } - errorInfo = IntentCompat.getParcelableExtra(intent, ERROR_INFO, ErrorInfo.class); + errorInfo = IntentCompat.getParcelableExtra(getIntent(), ERROR_INFO, ErrorInfo.class); // important add guru meditation addGuruMeditation(); // print current time, as zoned ISO8601 timestamp - final ZonedDateTime now = ZonedDateTime.now(); - currentTimeStamp = now.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + currentTimeStamp = ZonedDateTime.now().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); activityErrorBinding.errorReportEmailButton.setOnClickListener(v -> openPrivacyPolicyDialog(this, "EMAIL")); @@ -160,9 +157,7 @@ public class ErrorActivity extends AppCompatActivity { final Intent i = new Intent(Intent.ACTION_SENDTO) .setData(Uri.parse("mailto:")) // only email apps should handle this .putExtra(Intent.EXTRA_EMAIL, new String[]{ERROR_EMAIL_ADDRESS}) - .putExtra(Intent.EXTRA_SUBJECT, ERROR_EMAIL_SUBJECT - + getString(R.string.app_name) + " " - + BuildConfig.VERSION_NAME) + .putExtra(Intent.EXTRA_SUBJECT, getErrorEmailSubject()) .putExtra(Intent.EXTRA_TEXT, buildJson()); ShareUtils.openIntentInApp(context, i); } else if (action.equals("GITHUB")) { // open the NewPipe issue page on GitHub @@ -180,12 +175,10 @@ public class ErrorActivity extends AppCompatActivity { } private void buildInfo(final ErrorInfo info) { - String text = ""; - activityErrorBinding.errorInfoLabelsView.setText(getString(R.string.info_labels) .replace("\\n", "\n")); - text += getUserActionString(info.getUserAction()) + "\n" + final String text = info.getUserAction().getMessage() + "\n" + info.getRequest() + "\n" + getContentLanguageString() + "\n" + getContentCountryString() + "\n" @@ -203,7 +196,7 @@ public class ErrorActivity extends AppCompatActivity { try { return JsonWriter.string() .object() - .value("user_action", getUserActionString(errorInfo.getUserAction())) + .value("user_action", errorInfo.getUserAction().getMessage()) .value("request", errorInfo.getRequest()) .value("content_language", getContentLanguageString()) .value("content_country", getContentCountryString()) @@ -239,7 +232,7 @@ public class ErrorActivity extends AppCompatActivity { htmlErrorReport .append("## Exception") .append("\n* __User Action:__ ") - .append(getUserActionString(errorInfo.getUserAction())) + .append(errorInfo.getUserAction().getMessage()) .append("\n* __Request:__ ").append(errorInfo.getRequest()) .append("\n* __Content Country:__ ").append(getContentCountryString()) .append("\n* __Content Language:__ ").append(getContentLanguageString()) @@ -286,14 +279,6 @@ public class ErrorActivity extends AppCompatActivity { } } - private String getUserActionString(final UserAction userAction) { - if (userAction == null) { - return "Your description is in another castle."; - } else { - return userAction.getMessage(); - } - } - private String getContentCountryString() { return Localization.getPreferredContentCountry(this).getCountryCode(); } @@ -306,6 +291,10 @@ public class ErrorActivity extends AppCompatActivity { return Localization.getAppLocale().toString(); } + private String getErrorEmailSubject() { + return ERROR_EMAIL_SUBJECT + getString(R.string.app_name) + " " + BuildConfig.VERSION_NAME; + } + private String getOsString() { final String osBase = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? Build.VERSION.BASE_OS : "Android"; From 4a7eaed3a70f0a5ec599253c59b39bde173ca404 Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Tue, 10 Feb 2026 09:32:43 +0200 Subject: [PATCH 23/56] ErrorActivity convert to kotlin Co-authored-by: Aayush Gupta --- .../schabi/newpipe/error/ErrorActivity.java | 313 ------------------ .../org/schabi/newpipe/error/ErrorActivity.kt | 281 ++++++++++++++++ 2 files changed, 281 insertions(+), 313 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java create mode 100644 app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java deleted file mode 100644 index e183ebd71..000000000 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java +++ /dev/null @@ -1,313 +0,0 @@ -package org.schabi.newpipe.error; - -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.util.Log; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; - -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.app.AppCompatActivity; -import androidx.core.content.IntentCompat; - -import com.grack.nanojson.JsonWriter; - -import org.schabi.newpipe.BuildConfig; -import org.schabi.newpipe.R; -import org.schabi.newpipe.databinding.ActivityErrorBinding; -import org.schabi.newpipe.util.Localization; -import org.schabi.newpipe.util.ThemeHelper; -import org.schabi.newpipe.util.external_communication.ShareUtils; - -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.Arrays; -import java.util.stream.Collectors; - -/* - * Created by Christian Schabesberger on 24.10.15. - * - * Copyright (C) Christian Schabesberger 2016 - * ErrorActivity.java is part of NewPipe. - * - * NewPipe is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * < - * NewPipe is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * < - * You should have received a copy of the GNU General Public License - * 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(); - // BUNDLE TAGS - public static final String ERROR_INFO = "error_info"; - - public static final String ERROR_EMAIL_ADDRESS = "crashreport@newpipe.schabi.org"; - public static final String ERROR_EMAIL_SUBJECT = "Exception in "; - - public static final String ERROR_GITHUB_ISSUE_URL = - "https://github.com/TeamNewPipe/NewPipe/issues"; - - private ErrorInfo errorInfo; - private String currentTimeStamp; - - private ActivityErrorBinding activityErrorBinding; - - - //////////////////////////////////////////////////////////////////////// - // Activity lifecycle - //////////////////////////////////////////////////////////////////////// - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ThemeHelper.setDayNightMode(this); - ThemeHelper.setTheme(this); - - activityErrorBinding = ActivityErrorBinding.inflate(getLayoutInflater()); - setContentView(activityErrorBinding.getRoot()); - - setSupportActionBar(activityErrorBinding.toolbarLayout.toolbar); - - final ActionBar actionBar = getSupportActionBar(); - if (actionBar != null) { - actionBar.setDisplayHomeAsUpEnabled(true); - actionBar.setTitle(R.string.error_report_title); - actionBar.setDisplayShowTitleEnabled(true); - } - - errorInfo = IntentCompat.getParcelableExtra(getIntent(), ERROR_INFO, ErrorInfo.class); - - // important add guru meditation - addGuruMeditation(); - // print current time, as zoned ISO8601 timestamp - currentTimeStamp = ZonedDateTime.now().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); - - activityErrorBinding.errorReportEmailButton.setOnClickListener(v -> - openPrivacyPolicyDialog(this, "EMAIL")); - - activityErrorBinding.errorReportCopyButton.setOnClickListener(v -> - ShareUtils.copyToClipboard(this, buildMarkdown())); - - activityErrorBinding.errorReportGitHubButton.setOnClickListener(v -> - openPrivacyPolicyDialog(this, "GITHUB")); - - // normal bugreport - buildInfo(errorInfo); - activityErrorBinding.errorMessageView.setText(errorInfo.getMessage(this)); - activityErrorBinding.errorView.setText(formErrorText(errorInfo.getStackTraces())); - - // print stack trace once again for debugging: - for (final String e : errorInfo.getStackTraces()) { - Log.e(TAG, e); - } - } - - @Override - public boolean onCreateOptionsMenu(final Menu menu) { - final MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.error_menu, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(final MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - onBackPressed(); - return true; - case R.id.menu_item_share_error: - ShareUtils.shareText(getApplicationContext(), - getString(R.string.error_report_title), buildJson()); - return true; - default: - return false; - } - } - - private void openPrivacyPolicyDialog(final Context context, final String action) { - new AlertDialog.Builder(context) - .setIcon(android.R.drawable.ic_dialog_alert) - .setTitle(R.string.privacy_policy_title) - .setMessage(R.string.start_accept_privacy_policy) - .setCancelable(false) - .setNeutralButton(R.string.read_privacy_policy, (dialog, which) -> - ShareUtils.openUrlInApp(context, - context.getString(R.string.privacy_policy_url))) - .setPositiveButton(R.string.accept, (dialog, which) -> { - if (action.equals("EMAIL")) { // send on email - final Intent i = new Intent(Intent.ACTION_SENDTO) - .setData(Uri.parse("mailto:")) // only email apps should handle this - .putExtra(Intent.EXTRA_EMAIL, new String[]{ERROR_EMAIL_ADDRESS}) - .putExtra(Intent.EXTRA_SUBJECT, getErrorEmailSubject()) - .putExtra(Intent.EXTRA_TEXT, buildJson()); - ShareUtils.openIntentInApp(context, i); - } else if (action.equals("GITHUB")) { // open the NewPipe issue page on GitHub - ShareUtils.openUrlInApp(this, ERROR_GITHUB_ISSUE_URL); - } - }) - .setNegativeButton(R.string.decline, null) - .show(); - } - - private String formErrorText(final String[] el) { - final String separator = "-------------------------------------"; - return Arrays.stream(el) - .collect(Collectors.joining(separator + "\n", separator + "\n", separator)); - } - - private void buildInfo(final ErrorInfo info) { - activityErrorBinding.errorInfoLabelsView.setText(getString(R.string.info_labels) - .replace("\\n", "\n")); - - final String text = info.getUserAction().getMessage() + "\n" - + info.getRequest() + "\n" - + getContentLanguageString() + "\n" - + getContentCountryString() + "\n" - + getAppLanguage() + "\n" - + info.getServiceName() + "\n" - + currentTimeStamp + "\n" - + getPackageName() + "\n" - + BuildConfig.VERSION_NAME + "\n" - + getOsString(); - - activityErrorBinding.errorInfosView.setText(text); - } - - private String buildJson() { - try { - return JsonWriter.string() - .object() - .value("user_action", errorInfo.getUserAction().getMessage()) - .value("request", errorInfo.getRequest()) - .value("content_language", getContentLanguageString()) - .value("content_country", getContentCountryString()) - .value("app_language", getAppLanguage()) - .value("service", errorInfo.getServiceName()) - .value("package", getPackageName()) - .value("version", BuildConfig.VERSION_NAME) - .value("os", getOsString()) - .value("time", currentTimeStamp) - .array("exceptions", Arrays.asList(errorInfo.getStackTraces())) - .value("user_comment", activityErrorBinding.errorCommentBox.getText() - .toString()) - .end() - .done(); - } catch (final Throwable e) { - Log.e(TAG, "Error while erroring: Could not build json"); - e.printStackTrace(); - } - - return ""; - } - - private String buildMarkdown() { - try { - final StringBuilder htmlErrorReport = new StringBuilder(); - - final String userComment = activityErrorBinding.errorCommentBox.getText().toString(); - if (!userComment.isEmpty()) { - htmlErrorReport.append(userComment).append("\n"); - } - - // basic error info - htmlErrorReport - .append("## Exception") - .append("\n* __User Action:__ ") - .append(errorInfo.getUserAction().getMessage()) - .append("\n* __Request:__ ").append(errorInfo.getRequest()) - .append("\n* __Content Country:__ ").append(getContentCountryString()) - .append("\n* __Content Language:__ ").append(getContentLanguageString()) - .append("\n* __App Language:__ ").append(getAppLanguage()) - .append("\n* __Service:__ ").append(errorInfo.getServiceName()) - .append("\n* __Timestamp:__ ").append(currentTimeStamp) - .append("\n* __Package:__ ").append(getPackageName()) - .append("\n* __Service:__ ").append(errorInfo.getServiceName()) - .append("\n* __Version:__ ").append(BuildConfig.VERSION_NAME) - .append("\n* __OS:__ ").append(getOsString()).append("\n"); - - - // Collapse all logs to a single paragraph when there are more than one - // to keep the GitHub issue clean. - if (errorInfo.getStackTraces().length > 1) { - htmlErrorReport - .append("
Exceptions (") - .append(errorInfo.getStackTraces().length) - .append(")

\n"); - } - - // add the logs - for (int i = 0; i < errorInfo.getStackTraces().length; i++) { - htmlErrorReport.append("

Crash log "); - if (errorInfo.getStackTraces().length > 1) { - htmlErrorReport.append(i + 1); - } - htmlErrorReport.append("") - .append("

\n") - .append("\n```\n").append(errorInfo.getStackTraces()[i]).append("\n```\n") - .append("

\n"); - } - - // make sure to close everything - if (errorInfo.getStackTraces().length > 1) { - htmlErrorReport.append("

\n"); - } - htmlErrorReport.append("
\n"); - return htmlErrorReport.toString(); - } catch (final Throwable e) { - Log.e(TAG, "Error while erroring: Could not build markdown"); - e.printStackTrace(); - return ""; - } - } - - private String getContentCountryString() { - return Localization.getPreferredContentCountry(this).getCountryCode(); - } - - private String getContentLanguageString() { - return Localization.getPreferredLocalization(this).getLocalizationCode(); - } - - private String getAppLanguage() { - return Localization.getAppLocale().toString(); - } - - private String getErrorEmailSubject() { - return ERROR_EMAIL_SUBJECT + getString(R.string.app_name) + " " + BuildConfig.VERSION_NAME; - } - - private String getOsString() { - final String osBase = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M - ? Build.VERSION.BASE_OS : "Android"; - return System.getProperty("os.name") - + " " + (osBase.isEmpty() ? "Android" : osBase) - + " " + Build.VERSION.RELEASE - + " - " + Build.VERSION.SDK_INT; - } - - private void addGuruMeditation() { - //just an easter egg - String text = activityErrorBinding.errorSorryView.getText().toString(); - text += "\n" + getString(R.string.guru_meditation); - activityErrorBinding.errorSorryView.setText(text); - } -} diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt new file mode 100644 index 000000000..b48dd29be --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt @@ -0,0 +1,281 @@ +/* + * SPDX-FileCopyrightText: 2015-2026 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.error + +import android.content.Context +import android.content.Intent +import android.os.Build +import android.os.Bundle +import android.util.Log +import android.view.Menu +import android.view.MenuItem +import androidx.appcompat.app.AlertDialog +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.IntentCompat +import androidx.core.net.toUri +import com.grack.nanojson.JsonWriter +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter +import org.schabi.newpipe.BuildConfig +import org.schabi.newpipe.R +import org.schabi.newpipe.databinding.ActivityErrorBinding +import org.schabi.newpipe.util.Localization +import org.schabi.newpipe.util.ThemeHelper +import org.schabi.newpipe.util.external_communication.ShareUtils + +/** + * This activity is used to show error details and allow reporting them in various ways. + * Use [ErrorUtil.openActivity] to correctly open this activity. + */ +class ErrorActivity : AppCompatActivity() { + private lateinit var errorInfo: ErrorInfo + private lateinit var currentTimeStamp: String + + private lateinit var activityErrorBinding: ActivityErrorBinding + + private val contentCountryString: String + get() = Localization.getPreferredContentCountry(this).countryCode + + private val contentLanguageString: String + get() = Localization.getPreferredLocalization(this).localizationCode + + private val appLanguage: String + get() = Localization.getAppLocale().toString() + + private val osString: String + get() { + val name = System.getProperty("os.name")!! + val osBase = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + Build.VERSION.BASE_OS.ifEmpty { "Android" } + } else { + "Android" + } + return "$name $osBase ${Build.VERSION.RELEASE} - ${Build.VERSION.SDK_INT}" + } + + private val errorEmailSubject: String + get() = "$ERROR_EMAIL_SUBJECT ${getString(R.string.app_name)} ${BuildConfig.VERSION_NAME}" + + // ///////////////////////////////////////////////////////////////////// + // Activity lifecycle + // ///////////////////////////////////////////////////////////////////// + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + ThemeHelper.setDayNightMode(this) + ThemeHelper.setTheme(this) + + activityErrorBinding = ActivityErrorBinding.inflate(layoutInflater) + setContentView(activityErrorBinding.getRoot()) + + setSupportActionBar(activityErrorBinding.toolbarLayout.toolbar) + supportActionBar?.apply { + setDisplayHomeAsUpEnabled(true) + setTitle(R.string.error_report_title) + setDisplayShowTitleEnabled(true) + } + + errorInfo = IntentCompat.getParcelableExtra(intent, ERROR_INFO, ErrorInfo::class.java)!! + + // important add guru meditation + addGuruMeditation() + // print current time, as zoned ISO8601 timestamp + currentTimeStamp = ZonedDateTime.now().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME) + + activityErrorBinding.errorReportEmailButton.setOnClickListener { _ -> + openPrivacyPolicyDialog(this, "EMAIL") + } + + activityErrorBinding.errorReportCopyButton.setOnClickListener { _ -> + ShareUtils.copyToClipboard(this, buildMarkdown()) + } + + activityErrorBinding.errorReportGitHubButton.setOnClickListener { _ -> + openPrivacyPolicyDialog(this, "GITHUB") + } + + // normal bugreport + buildInfo(errorInfo) + activityErrorBinding.errorMessageView.text = errorInfo.getMessage(this) + activityErrorBinding.errorView.text = formErrorText(errorInfo.stackTraces) + + // print stack trace once again for debugging: + errorInfo.stackTraces.forEach { Log.e(TAG, it) } + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + menuInflater.inflate(R.menu.error_menu, menu) + return true + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + android.R.id.home -> { + onBackPressed() + true + } + + R.id.menu_item_share_error -> { + ShareUtils.shareText( + applicationContext, + getString(R.string.error_report_title), + buildJson() + ) + true + } + + else -> false + } + } + + private fun openPrivacyPolicyDialog(context: Context, action: String) { + AlertDialog.Builder(context) + .setIcon(android.R.drawable.ic_dialog_alert) + .setTitle(R.string.privacy_policy_title) + .setMessage(R.string.start_accept_privacy_policy) + .setCancelable(false) + .setNeutralButton(R.string.read_privacy_policy) { _, _ -> + ShareUtils.openUrlInApp(context, context.getString(R.string.privacy_policy_url)) + } + .setPositiveButton(R.string.accept) { _, _ -> + if (action == "EMAIL") { // send on email + val i = Intent(Intent.ACTION_SENDTO) + .setData("mailto:".toUri()) // only email apps should handle this + .putExtra(Intent.EXTRA_EMAIL, arrayOf(ERROR_EMAIL_ADDRESS)) + .putExtra(Intent.EXTRA_SUBJECT, errorEmailSubject) + .putExtra(Intent.EXTRA_TEXT, buildJson()) + ShareUtils.openIntentInApp(context, i) + } else if (action == "GITHUB") { // open the NewPipe issue page on GitHub + ShareUtils.openUrlInApp(this, ERROR_GITHUB_ISSUE_URL) + } + } + .setNegativeButton(R.string.decline, null) + .show() + } + + private fun formErrorText(el: Array): String { + val separator = "-------------------------------------" + return el.joinToString(separator + "\n", separator + "\n", separator) + } + + private fun buildInfo(info: ErrorInfo) { + activityErrorBinding.errorInfoLabelsView.text = getString(R.string.info_labels) + .replace("\\n", "\n") + + val text = info.userAction.message + "\n" + + info.request + "\n" + + contentLanguageString + "\n" + + contentCountryString + "\n" + + appLanguage + "\n" + + info.getServiceName() + "\n" + + currentTimeStamp + "\n" + + packageName + "\n" + + BuildConfig.VERSION_NAME + "\n" + + osString + + activityErrorBinding.errorInfosView.text = text + } + + private fun buildJson(): String { + try { + return JsonWriter.string() + .`object`() + .value("user_action", errorInfo.userAction.message) + .value("request", errorInfo.request) + .value("content_language", contentLanguageString) + .value("content_country", contentCountryString) + .value("app_language", appLanguage) + .value("service", errorInfo.getServiceName()) + .value("package", packageName) + .value("version", BuildConfig.VERSION_NAME) + .value("os", osString) + .value("time", currentTimeStamp) + .array("exceptions", errorInfo.stackTraces.toList()) + .value("user_comment", activityErrorBinding.errorCommentBox.getText().toString()) + .end() + .done() + } catch (error: Throwable) { + Log.e(TAG, "Error while erroring: Could not build json", error) + } + + return "" + } + + private fun buildMarkdown(): String { + try { + return buildString(1024) { + val userComment = activityErrorBinding.errorCommentBox.getText().toString() + if (!userComment.isEmpty()) { + appendLine(userComment) + } + + // basic error info + appendLine("## Exception") + appendLine("* __User Action:__ ${errorInfo.userAction.message}") + appendLine("* __Request:__ ${errorInfo.request}") + appendLine("* __Content Country:__ $contentCountryString") + appendLine("* __Content Language:__ $contentLanguageString") + appendLine("* __App Language:__ $appLanguage") + appendLine("* __Service:__ ${errorInfo.getServiceName()}") + appendLine("* __Timestamp:__ $currentTimeStamp") + appendLine("* __Package:__ $packageName") + appendLine("* __Service:__ ${errorInfo.getServiceName()}") + appendLine("* __Version:__ ${BuildConfig.VERSION_NAME}") + appendLine("* __OS:__ $osString") + + // Collapse all logs to a single paragraph when there are more than one + // to keep the GitHub issue clean. + if (errorInfo.stackTraces.size > 1) { + append("
Exceptions (") + append(errorInfo.stackTraces.size) + append(")

\n") + } + + // add the logs + for (i in errorInfo.stackTraces.indices) { + append("

Crash log ") + if (errorInfo.stackTraces.size > 1) { + append(i + 1) + } + append("") + append("

\n") + append("\n```\n${errorInfo.stackTraces[i]}\n```\n") + append("

\n") + } + + // make sure to close everything + if (errorInfo.stackTraces.size > 1) { + append("

\n") + } + append("
\n") + } + } catch (error: Throwable) { + Log.e(TAG, "Error while erroring: Could not build markdown", error) + return "" + } + } + + private fun addGuruMeditation() { + // just an easter egg + var text = activityErrorBinding.errorSorryView.getText().toString() + text += "\n" + getString(R.string.guru_meditation) + activityErrorBinding.errorSorryView.text = text + } + + companion object { + // LOG TAGS + val TAG: String = ErrorActivity::class.java.toString() + + // BUNDLE TAGS + const val ERROR_INFO: String = "error_info" + + const val ERROR_EMAIL_ADDRESS: String = "crashreport@newpipe.schabi.org" + const val ERROR_EMAIL_SUBJECT: String = "Exception in " + + const val ERROR_GITHUB_ISSUE_URL: String = "https://github.com/TeamNewPipe/NewPipe/issues" + } +} From d7a4435e943fc59687cfb161c087c1492d0e09ed Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Wed, 11 Feb 2026 18:39:34 +0800 Subject: [PATCH 24/56] ErrorActivity: Use better variable names and encapsulation Signed-off-by: Aayush Gupta --- .../org/schabi/newpipe/error/ErrorActivity.kt | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt index b48dd29be..32f9769a1 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt @@ -34,7 +34,7 @@ class ErrorActivity : AppCompatActivity() { private lateinit var errorInfo: ErrorInfo private lateinit var currentTimeStamp: String - private lateinit var activityErrorBinding: ActivityErrorBinding + private lateinit var binding: ActivityErrorBinding private val contentCountryString: String get() = Localization.getPreferredContentCountry(this).countryCode @@ -69,10 +69,10 @@ class ErrorActivity : AppCompatActivity() { ThemeHelper.setDayNightMode(this) ThemeHelper.setTheme(this) - activityErrorBinding = ActivityErrorBinding.inflate(layoutInflater) - setContentView(activityErrorBinding.getRoot()) + binding = ActivityErrorBinding.inflate(layoutInflater) + setContentView(binding.getRoot()) - setSupportActionBar(activityErrorBinding.toolbarLayout.toolbar) + setSupportActionBar(binding.toolbarLayout.toolbar) supportActionBar?.apply { setDisplayHomeAsUpEnabled(true) setTitle(R.string.error_report_title) @@ -86,22 +86,22 @@ class ErrorActivity : AppCompatActivity() { // print current time, as zoned ISO8601 timestamp currentTimeStamp = ZonedDateTime.now().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME) - activityErrorBinding.errorReportEmailButton.setOnClickListener { _ -> + binding.errorReportEmailButton.setOnClickListener { _ -> openPrivacyPolicyDialog(this, "EMAIL") } - activityErrorBinding.errorReportCopyButton.setOnClickListener { _ -> + binding.errorReportCopyButton.setOnClickListener { _ -> ShareUtils.copyToClipboard(this, buildMarkdown()) } - activityErrorBinding.errorReportGitHubButton.setOnClickListener { _ -> + binding.errorReportGitHubButton.setOnClickListener { _ -> openPrivacyPolicyDialog(this, "GITHUB") } // normal bugreport buildInfo(errorInfo) - activityErrorBinding.errorMessageView.text = errorInfo.getMessage(this) - activityErrorBinding.errorView.text = formErrorText(errorInfo.stackTraces) + binding.errorMessageView.text = errorInfo.getMessage(this) + binding.errorView.text = formErrorText(errorInfo.stackTraces) // print stack trace once again for debugging: errorInfo.stackTraces.forEach { Log.e(TAG, it) } @@ -143,12 +143,12 @@ class ErrorActivity : AppCompatActivity() { } .setPositiveButton(R.string.accept) { _, _ -> if (action == "EMAIL") { // send on email - val i = Intent(Intent.ACTION_SENDTO) + val intent = Intent(Intent.ACTION_SENDTO) .setData("mailto:".toUri()) // only email apps should handle this .putExtra(Intent.EXTRA_EMAIL, arrayOf(ERROR_EMAIL_ADDRESS)) .putExtra(Intent.EXTRA_SUBJECT, errorEmailSubject) .putExtra(Intent.EXTRA_TEXT, buildJson()) - ShareUtils.openIntentInApp(context, i) + ShareUtils.openIntentInApp(context, intent) } else if (action == "GITHUB") { // open the NewPipe issue page on GitHub ShareUtils.openUrlInApp(this, ERROR_GITHUB_ISSUE_URL) } @@ -157,13 +157,13 @@ class ErrorActivity : AppCompatActivity() { .show() } - private fun formErrorText(el: Array): String { + private fun formErrorText(stacktrace: Array): String { val separator = "-------------------------------------" - return el.joinToString(separator + "\n", separator + "\n", separator) + return stacktrace.joinToString(separator + "\n", separator + "\n", separator) } private fun buildInfo(info: ErrorInfo) { - activityErrorBinding.errorInfoLabelsView.text = getString(R.string.info_labels) + binding.errorInfoLabelsView.text = getString(R.string.info_labels) .replace("\\n", "\n") val text = info.userAction.message + "\n" + @@ -177,7 +177,7 @@ class ErrorActivity : AppCompatActivity() { BuildConfig.VERSION_NAME + "\n" + osString - activityErrorBinding.errorInfosView.text = text + binding.errorInfosView.text = text } private fun buildJson(): String { @@ -195,7 +195,7 @@ class ErrorActivity : AppCompatActivity() { .value("os", osString) .value("time", currentTimeStamp) .array("exceptions", errorInfo.stackTraces.toList()) - .value("user_comment", activityErrorBinding.errorCommentBox.getText().toString()) + .value("user_comment", binding.errorCommentBox.getText().toString()) .end() .done() } catch (error: Throwable) { @@ -208,7 +208,7 @@ class ErrorActivity : AppCompatActivity() { private fun buildMarkdown(): String { try { return buildString(1024) { - val userComment = activityErrorBinding.errorCommentBox.getText().toString() + val userComment = binding.errorCommentBox.getText().toString() if (!userComment.isEmpty()) { appendLine(userComment) } @@ -261,21 +261,21 @@ class ErrorActivity : AppCompatActivity() { private fun addGuruMeditation() { // just an easter egg - var text = activityErrorBinding.errorSorryView.getText().toString() + var text = binding.errorSorryView.text.toString() text += "\n" + getString(R.string.guru_meditation) - activityErrorBinding.errorSorryView.text = text + binding.errorSorryView.text = text } companion object { // LOG TAGS - val TAG: String = ErrorActivity::class.java.toString() + private val TAG = ErrorActivity::class.java.toString() // BUNDLE TAGS - const val ERROR_INFO: String = "error_info" + const val ERROR_INFO = "error_info" - const val ERROR_EMAIL_ADDRESS: String = "crashreport@newpipe.schabi.org" - const val ERROR_EMAIL_SUBJECT: String = "Exception in " + private const val ERROR_EMAIL_ADDRESS = "crashreport@newpipe.schabi.org" + private const val ERROR_EMAIL_SUBJECT = "Exception in " - const val ERROR_GITHUB_ISSUE_URL: String = "https://github.com/TeamNewPipe/NewPipe/issues" + private const val ERROR_GITHUB_ISSUE_URL = "https://github.com/TeamNewPipe/NewPipe/issues" } } From 8968aab5785b326b4aebcb5f7ea91c4f54629e1f Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Wed, 11 Feb 2026 18:41:10 +0800 Subject: [PATCH 25/56] ErrorActivity: Catch exceptions not throwables Signed-off-by: Aayush Gupta --- .../main/java/org/schabi/newpipe/error/ErrorActivity.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt index 32f9769a1..7fbeb1716 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt @@ -198,8 +198,8 @@ class ErrorActivity : AppCompatActivity() { .value("user_comment", binding.errorCommentBox.getText().toString()) .end() .done() - } catch (error: Throwable) { - Log.e(TAG, "Error while erroring: Could not build json", error) + } catch (exception: Exception) { + Log.e(TAG, "Error while erroring: Could not build json", exception) } return "" @@ -253,8 +253,8 @@ class ErrorActivity : AppCompatActivity() { } append("
\n") } - } catch (error: Throwable) { - Log.e(TAG, "Error while erroring: Could not build markdown", error) + } catch (exception: Exception) { + Log.e(TAG, "Error while erroring: Could not build markdown", exception) return "" } } From c3dbed54e50430b585e9d7b88cf22c9f3a6cc54c Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Wed, 11 Feb 2026 21:39:01 +0800 Subject: [PATCH 26/56] ErrorActivity: Kotlin-fy buildMarkdown method Signed-off-by: Aayush Gupta --- .../org/schabi/newpipe/error/ErrorActivity.kt | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt index 7fbeb1716..b29190a55 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt @@ -208,8 +208,8 @@ class ErrorActivity : AppCompatActivity() { private fun buildMarkdown(): String { try { return buildString(1024) { - val userComment = binding.errorCommentBox.getText().toString() - if (!userComment.isEmpty()) { + val userComment = binding.errorCommentBox.text.toString() + if (userComment.isNotEmpty()) { appendLine(userComment) } @@ -229,28 +229,27 @@ class ErrorActivity : AppCompatActivity() { // Collapse all logs to a single paragraph when there are more than one // to keep the GitHub issue clean. - if (errorInfo.stackTraces.size > 1) { + if (errorInfo.stackTraces.isNotEmpty()) { append("
Exceptions (") append(errorInfo.stackTraces.size) append(")

\n") - } - // add the logs - for (i in errorInfo.stackTraces.indices) { - append("

Crash log ") - if (errorInfo.stackTraces.size > 1) { - append(i + 1) + // add the logs + errorInfo.stackTraces.forEachIndexed { index, stacktrace -> + append("
Crash log ") + if (errorInfo.stackTraces.isNotEmpty()) { + append(index + 1) + } + append("") + append("

\n") + append("\n```\n${stacktrace}\n```\n") + append("

\n") } - append("
") - append("

\n") - append("\n```\n${errorInfo.stackTraces[i]}\n```\n") - append("

\n") - } - // make sure to close everything - if (errorInfo.stackTraces.size > 1) { + // make sure to close everything append("

\n") } + append("
\n") } } catch (exception: Exception) { From 54090ca7b6f1c7f1f478514dc832c2961dfcdb7d Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Wed, 11 Feb 2026 16:54:00 +0200 Subject: [PATCH 27/56] ErrorActivity use normal `\n` instead of `\\n` in resource strings --- app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt | 1 - app/src/main/res/values-ar-rLY/strings.xml | 2 +- app/src/main/res/values-ar/strings.xml | 2 +- app/src/main/res/values-az/strings.xml | 2 +- app/src/main/res/values-b+ast/strings.xml | 2 +- app/src/main/res/values-b+uz+Latn/strings.xml | 2 +- app/src/main/res/values-be/strings.xml | 2 +- app/src/main/res/values-bg/strings.xml | 2 +- app/src/main/res/values-bn-rBD/strings.xml | 2 +- app/src/main/res/values-bn-rIN/strings.xml | 2 +- app/src/main/res/values-bn/strings.xml | 2 +- app/src/main/res/values-bs/strings.xml | 2 +- app/src/main/res/values-ca/strings.xml | 2 +- app/src/main/res/values-ckb/strings.xml | 2 +- app/src/main/res/values-cs/strings.xml | 2 +- app/src/main/res/values-da/strings.xml | 2 +- app/src/main/res/values-de/strings.xml | 2 +- app/src/main/res/values-el/strings.xml | 2 +- app/src/main/res/values-eo/strings.xml | 2 +- app/src/main/res/values-es/strings.xml | 2 +- app/src/main/res/values-et/strings.xml | 2 +- app/src/main/res/values-eu/strings.xml | 2 +- app/src/main/res/values-fa/strings.xml | 2 +- app/src/main/res/values-fi/strings.xml | 2 +- app/src/main/res/values-fr/strings.xml | 2 +- app/src/main/res/values-gl/strings.xml | 2 +- app/src/main/res/values-he/strings.xml | 2 +- app/src/main/res/values-hi/strings.xml | 2 +- app/src/main/res/values-hr/strings.xml | 2 +- app/src/main/res/values-hu/strings.xml | 2 +- app/src/main/res/values-in/strings.xml | 2 +- app/src/main/res/values-is/strings.xml | 2 +- app/src/main/res/values-it/strings.xml | 2 +- app/src/main/res/values-ja/strings.xml | 2 +- app/src/main/res/values-ka/strings.xml | 2 +- app/src/main/res/values-kmr/strings.xml | 2 +- app/src/main/res/values-ko/strings.xml | 2 +- app/src/main/res/values-ku/strings.xml | 2 +- app/src/main/res/values-lt/strings.xml | 2 +- app/src/main/res/values-lv/strings.xml | 2 +- app/src/main/res/values-mk/strings.xml | 2 +- app/src/main/res/values-ml/strings.xml | 2 +- app/src/main/res/values-ms/strings.xml | 2 +- app/src/main/res/values-nb-rNO/strings.xml | 2 +- app/src/main/res/values-ne/strings.xml | 2 +- app/src/main/res/values-nl-rBE/strings.xml | 2 +- app/src/main/res/values-nl/strings.xml | 2 +- app/src/main/res/values-nqo/strings.xml | 2 +- app/src/main/res/values-or/strings.xml | 2 +- app/src/main/res/values-pa/strings.xml | 2 +- app/src/main/res/values-pl/strings.xml | 2 +- app/src/main/res/values-pt-rBR/strings.xml | 2 +- app/src/main/res/values-pt-rPT/strings.xml | 2 +- app/src/main/res/values-pt/strings.xml | 2 +- app/src/main/res/values-ro/strings.xml | 2 +- app/src/main/res/values-ru/strings.xml | 2 +- app/src/main/res/values-ryu/strings.xml | 2 +- app/src/main/res/values-sat/strings.xml | 2 +- app/src/main/res/values-sc/strings.xml | 2 +- app/src/main/res/values-sk/strings.xml | 2 +- app/src/main/res/values-sl/strings.xml | 2 +- app/src/main/res/values-so/strings.xml | 2 +- app/src/main/res/values-sq/strings.xml | 2 +- app/src/main/res/values-sr/strings.xml | 2 +- app/src/main/res/values-sv/strings.xml | 2 +- app/src/main/res/values-ta/strings.xml | 2 +- app/src/main/res/values-tr/strings.xml | 2 +- app/src/main/res/values-uk/strings.xml | 2 +- app/src/main/res/values-ur/strings.xml | 2 +- app/src/main/res/values-vi/strings.xml | 2 +- app/src/main/res/values-zh-rCN/strings.xml | 2 +- app/src/main/res/values-zh-rHK/strings.xml | 2 +- app/src/main/res/values-zh-rTW/strings.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- 74 files changed, 73 insertions(+), 74 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt index b29190a55..a8555abae 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt @@ -164,7 +164,6 @@ class ErrorActivity : AppCompatActivity() { private fun buildInfo(info: ErrorInfo) { binding.errorInfoLabelsView.text = getString(R.string.info_labels) - .replace("\\n", "\n") val text = info.userAction.message + "\n" + info.request + "\n" + diff --git a/app/src/main/res/values-ar-rLY/strings.xml b/app/src/main/res/values-ar-rLY/strings.xml index ad411ab1e..e481d6bf7 100644 --- a/app/src/main/res/values-ar-rLY/strings.xml +++ b/app/src/main/res/values-ar-rLY/strings.xml @@ -381,7 +381,7 @@ القنوات لا تظهر أدخل عنوان للمثيل - ماذا:\\nطلب:\\nلغة المحتوى:\\nبلد المحتوى:\\nلغة التطبيق:\\nالخدمات:\\nتوقيت جرينتش:\\nالحزمة:\\nالإصدار:\\nOS نسخة: + ماذا:\nطلب:\nلغة المحتوى:\nبلد المحتوى:\nلغة التطبيق:\nالخدمات:\nتوقيت جرينتش:\nالحزمة:\nالإصدار:\nOS نسخة: يزيل الصوت في بعض الجودات جلب ألسنة القنوات جودة عالية (أكبر) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 51a1e47cb..d4e1847f3 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -109,7 +109,7 @@ أبلِغ معلومات: ماذا حدث: - ماذا:\\nطلب:\\nلغة المحتوى:\\nبلد المحتوى:\\nلغة التطبيق:\\nالخدمات:\\nتوقيت جرينتش:\\nالحزمة:\\nالإصدار:\\nOS نسخة: + ماذا:\nطلب:\nلغة المحتوى:\nبلد المحتوى:\nلغة التطبيق:\nالخدمات:\nتوقيت جرينتش:\nالحزمة:\nالإصدار:\nOS نسخة: تعليقك (باللغة الإنجليزية): التفاصيل: لم يتم العثور على نتائج diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index ee3396bc7..aec305e72 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -577,7 +577,7 @@ Səs Təfərrüatlar: - Nə:\\nSorğu:\\nMəzmun Dili:\\nMəzmun Ölkəsi:\\nTətbiq Dili:\\nXidmət:\\nGMT Saatı:\\nPaket:\\nVersiya:\\nƏS versiyası: + Nə:\nSorğu:\nMəzmun Dili:\nMəzmun Ölkəsi:\nTətbiq Dili:\nXidmət:\nGMT Saatı:\nPaket:\nVersiya:\nƏS versiyası: Bağışlayın, nəsə səhv oldu. Formatlanmış hesabatı köçür Server URL\'sini daxil et diff --git a/app/src/main/res/values-b+ast/strings.xml b/app/src/main/res/values-b+ast/strings.xml index c64972eb3..e5fb76ae1 100644 --- a/app/src/main/res/values-b+ast/strings.xml +++ b/app/src/main/res/values-b+ast/strings.xml @@ -267,7 +267,7 @@ Llimpiar los metadatos de la caché Llimpióse la caché d\'imáxenes ¿Instalar Kode\? - Qué asocedió:\\nSolicitú:\\nLlingua del conteníu:\\nPaís del conteníu:\\nLlingua de l\'aplicación:\\nServiciu:\\nHora en GMT:\\nPaquete:\\nVersión de l\'aplicación:\\nVersión del SO: + Qué asocedió:\nSolicitú:\nLlingua del conteníu:\nPaís del conteníu:\nLlingua de l\'aplicación:\nServiciu:\nHora en GMT:\nPaquete:\nVersión de l\'aplicación:\nVersión del SO: Nun s\'atopó nengún reproductor de fluxos (pues instalar VLC pa reproducilos). Amuesa una miniatura nel fondu de la pantalla de bloquéu y dientro de los avisos Amosar una miniatura diff --git a/app/src/main/res/values-b+uz+Latn/strings.xml b/app/src/main/res/values-b+uz+Latn/strings.xml index cc82ec69c..7e737235b 100644 --- a/app/src/main/res/values-b+uz+Latn/strings.xml +++ b/app/src/main/res/values-b+uz+Latn/strings.xml @@ -279,7 +279,7 @@ Videoni ijro etish muddati, davomiyligi: Detallar: Sizning sharhingiz (ingliz tilida): - Nima: \\n So\'rov: \\nTarkib tili: \\nTarkib mamlakati: \\nIlova tili: \\ nXizmat: \\ nGMT vaqti: \\ nPaket: \\ nVersion: \\ nOS versiyasi: + Nima: \n So\'rov: \nTarkib tili: \nTarkib mamlakati: \nIlova tili: \\ nXizmat: \\ nGMT vaqti: \\ nPaket: \\ nVersion: \\ nOS versiyasi: Nima sodir bo\'ldi: Info: Hisobot diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index e44d2ea5c..530d700a7 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -146,7 +146,7 @@ Справаздача Інфармацыя: Што адбылося: - Што:\\nЗапыт:\\nМова кантэнту:\\nКраіна кантэнту:\\nМова праграмы:\\nСэрвіс:\\nЧас GMT:\\nПакет:\\nВерсія:\\nВерсія АС: + Што:\nЗапыт:\nМова кантэнту:\nКраіна кантэнту:\nМова праграмы:\nСэрвіс:\nЧас GMT:\nПакет:\nВерсія:\nВерсія АС: Ваш каментарый (па-англійску): Падрабязнасці: Прайграць відэа, працягласць: diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index 5d0b07943..22f4b9685 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -204,7 +204,7 @@ Изтрива историята на възпроизвежданите стриймове и позицията на възпроизвеждането Не са намерени видео стриймове Не са намерени аудио стриймове - Какво:\\nЗаявка:\\nЕзик на съдържанието:\\nДържава на съдържанието:\\nЕзик на приложението:\\nУслуга:\\nGMT Време:\\nПакет:\\nВерсия:\\nВерсия на ОС: + Какво:\nЗаявка:\nЕзик на съдържанието:\nДържава на съдържанието:\nЕзик на приложението:\nУслуга:\nGMT Време:\nПакет:\nВерсия:\nВерсия на ОС: Пренареди чрез плъзгане Начало Преименувай diff --git a/app/src/main/res/values-bn-rBD/strings.xml b/app/src/main/res/values-bn-rBD/strings.xml index 2b0ffe918..0d82e434b 100644 --- a/app/src/main/res/values-bn-rBD/strings.xml +++ b/app/src/main/res/values-bn-rBD/strings.xml @@ -103,7 +103,7 @@ reCAPTCHA চ্যালেঞ্জ reCAPTCHA চ্যালেঞ্জ অনুরোধ করা হয়েছে - কি:\\nঅনুরোধ:\\nকন্টেন্ট ভাষা:\\nসার্ভিস:\\nসময়(GMT এ):\\nপ্যাকেজ:\\nসংস্করণ:\\nওএস সংস্করণ:\\nআইপি পরিসর: + কি:\nঅনুরোধ:\nকন্টেন্ট ভাষা:\nসার্ভিস:\nসময়(GMT এ):\nপ্যাকেজ:\nসংস্করণ:\nওএস সংস্করণ:\nআইপি পরিসর: স্ট্রিম ফাইল ডাউনলোড করুন তথ্য দেখাও নতুন যা কিছু diff --git a/app/src/main/res/values-bn-rIN/strings.xml b/app/src/main/res/values-bn-rIN/strings.xml index a79319ee3..bf226e28e 100644 --- a/app/src/main/res/values-bn-rIN/strings.xml +++ b/app/src/main/res/values-bn-rIN/strings.xml @@ -33,7 +33,7 @@ ভিডিও প্রাকদর্শন, সময়ঃ বর্ণনা: আপনার মন্তব্য (ইংরেজিতে): - কি:\\nঅনুরোধ:\\nকন্টেন্ট ভাষা:\\nকন্টেন্ট দেশ:\\nঅ্যাপ ভাষা:\\nসার্ভিস:\\nসময়(GMT এ):\\nপ্যাকেজ:\\nসংস্করণ:\\nওএস সংস্করণ: + কি:\nঅনুরোধ:\nকন্টেন্ট ভাষা:\nকন্টেন্ট দেশ:\nঅ্যাপ ভাষা:\nসার্ভিস:\nসময়(GMT এ):\nপ্যাকেজ:\nসংস্করণ:\nওএস সংস্করণ: কি হয়েছিল: তথ্য: প্রতিবেদন diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index 7a4c8b3b0..9059bd4f5 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -114,7 +114,7 @@ ভিডিও চালাও, সময়ঃ বর্ণনা: তোমার মন্তব্য (ইংরেজিতে): - কি:\\nঅনুরোধ:\\nকন্টেন্ট ভাষা:\\nসার্ভিস:\\nসময়(GMT এ):\\nপ্যাকেজ:\\nসংস্করণ:\\nওএস সংস্করণ:\\nআইপি পরিসর: + কি:\nঅনুরোধ:\nকন্টেন্ট ভাষা:\nসার্ভিস:\nসময়(GMT এ):\nপ্যাকেজ:\nসংস্করণ:\nওএস সংস্করণ:\nআইপি পরিসর: কি হয়েছিল: তথ্য: প্রতিবেদন diff --git a/app/src/main/res/values-bs/strings.xml b/app/src/main/res/values-bs/strings.xml index ee4fc3317..6c4b08a72 100644 --- a/app/src/main/res/values-bs/strings.xml +++ b/app/src/main/res/values-bs/strings.xml @@ -268,7 +268,7 @@ Prijavi Info: Šta se dogodilo: - Šta:\\nZahtjev:\\nJezik sadržaja:\\nZemlja sadržaja:\\nJezik aplikacije:\\nUsluga:\\nVremenska oznaka:\\nPaket:\\nVerzija:\\nVerzija OS-a: + Šta:\nZahtjev:\nJezik sadržaja:\nZemlja sadržaja:\nJezik aplikacije:\nUsluga:\nVremenska oznaka:\nPaket:\nVerzija:\nVerzija OS-a: Vaš komentar (na engleskom): Detalji: Reproduciraj video, trajanje: diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index ff12819f5..88d5b2e65 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -268,7 +268,7 @@ Acaba de reproduir la cua (sense repetició) quan s\'hi afegeixi un vídeo relacionat Mostra l\'indicador «Mantenir per posar a la cua» Mostra un missatge d\'ajuda quan el botó de mode en segon pla o emergent estigui premut a la pàgina de detalls d\'un vídeo - Què ha passat:\\nPetició:\\nIdioma del contingut:\\nPaís del contingut:\\nLlengua de l\'aplicació:\\nServei:\\nHora GMT:\\nPaquet:\\nVersió:\\nVersió del SO: + Què ha passat:\nPetició:\nIdioma del contingut:\nPaís del contingut:\nLlengua de l\'aplicació:\nServei:\nHora GMT:\nPaquet:\nVersió:\nVersió del SO: Acció d\'obertura preferida Acció per defecte en obrir continguts — %s La supervisió de fugues de memòria pot fer que l\'aplicació deixi de respondre mentre es bolca la memòria diff --git a/app/src/main/res/values-ckb/strings.xml b/app/src/main/res/values-ckb/strings.xml index d448c1118..d168bbb37 100644 --- a/app/src/main/res/values-ckb/strings.xml +++ b/app/src/main/res/values-ckb/strings.xml @@ -12,7 +12,7 @@ \n \nبۆیە هەڵژرادن بۆ خۆت دەگەڕێتەوە: زانیاری تەواو یان خێرا.
نیوپایپ نه‌رمه‌والایه‌كی سەرچاوە کراوەیە : دەتوانیت بەکاریبهێنیت، بیخوێنیتەوە، هاوبەشی پێبکەیت ،بەرەوپێشی ببەیت. بەتایبەتی دەتوانی دابەشیبکەیتەوە یاخوود بگۆڕیت بەپێی مەرجەکانی GNU مۆڵەتنامەی گشتی وەک نه‌رمه‌واڵایه‌كی بڵاوی خۆڕایی, بەهۆی وەشانی ٣ ی مۆڵەتنامە، یان هەر وەشانێکی دوواتر. - چی:\\nداواكاری:\\nزمانی بابەت:\\nوڵاتی بابەت:\\nزمانی به‌رنامه‌:\\nخزمه‌تگوزاری:\\nGMT كات:\\nپاكێج:\\nوه‌شان:\\nOS وه‌شان: + چی:\nداواكاری:\nزمانی بابەت:\nوڵاتی بابەت:\nزمانی به‌رنامه‌:\nخزمه‌تگوزاری:\nGMT كات:\nپاكێج:\nوه‌شان:\nOS وه‌شان: پڕۆژەی نیوپایپ زانیارییە تایبەتییەکانت بە وردی دەپارێزێت. هەروەها به‌رنامه‌كه‌ هیچ زانایارییەکت بەبێ ئاگاداری تۆ بەکارنابات. \n‫سیاسەتی تایبەتی نیوپایپ بە وردی ڕوونکردنەوەت دەداتێ لەسەر ئەو زانیاریانەی وەریاندەگرێت و بەکاریاندەبات. ناتوانرێت لە بیرگەی دەرەکیدا داببەزێنرێت . شوێنی فۆڵده‌ری دابه‌زاندنەکان ڕێکبخرێتەوە؟ diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 4c219d6d4..37e8d70e5 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -81,7 +81,7 @@ Černé Kontrolní součet Určete prosím složku pro stahování později v nastavení - Co:\\nŽádost:\\nJazyk obsahu:\\nZemě obsahu:\\nJazyk aplikace:\\nSlužba:\\nČas GMT:\\nBalíček:\\nVerze:\\nVerze OS: + Co:\nŽádost:\nJazyk obsahu:\nZemě obsahu:\nJazyk aplikace:\nSlužba:\nČas GMT:\nBalíček:\nVerze:\nVerze OS: Vše Otevřít ve vyskakovacím okně Toto oprávnění je vyžadováno diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index f3a25e3b7..2be7c8bb8 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -317,7 +317,7 @@ Start afspilning i et popup Åbn Skuffe Luk Skuffe - Hvad:\\nForespørgsel:\\nIndholdssprog:\\nIndholdsland:\\nApp-sprog:\\nTjeneste:\\nGMT-tid:\\nPakke:\\nVersion:\\nOS-version: + Hvad:\nForespørgsel:\nIndholdssprog:\nIndholdsland:\nApp-sprog:\nTjeneste:\nGMT-tid:\nPakke:\nVersion:\nOS-version: Standardhandling ved åbning af indhold — %s Anvend som playlistens miniaturebillede Bogmærk Playliste diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 1b4800a8f..6270c658a 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -54,7 +54,7 @@ Melden Info: Dies ist passiert: - Was:\\nAnfrage:\\nSprache des Inhalts:\\nLand des Inhalts:\\nSprache der App:\\nDienst:\\nZeit (GMT):\\nPaket:\\nVersion:\\nOS-Version: + Was:\nAnfrage:\nSprache des Inhalts:\nLand des Inhalts:\nSprache der App:\nDienst:\nZeit (GMT):\nPaket:\nVersion:\nOS-Version: Details: Video Audio diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index ac93470bc..b8166905e 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -163,7 +163,7 @@ Λυπούμαστε, αυτό δεν έπρεπε να έχει συμβεί. Αναφορά μέσω ηλεκτρονικού ταχυδρομείου Συγγνώμη, κάτι πήγε στραβά. - Τι:\\nΑίτημα:\\nΓλώσσα περιεχομένου:\\nΧώρα περιεχομένου:\\nΓλώσσα εφαρμογής:\\nΥπηρεσία:\\nΏρα GMT:\\nΠακέτο:\\nΈκδοση:\\nΈκδοση λειτουργικού συστήματος: + Τι:\nΑίτημα:\nΓλώσσα περιεχομένου:\nΧώρα περιεχομένου:\nΓλώσσα εφαρμογής:\nΥπηρεσία:\nΏρα GMT:\nΠακέτο:\nΈκδοση:\nΈκδοση λειτουργικού συστήματος: Κανένα αποτέλεσμα Δεν υπάρχει τίποτα εδώ Σύρετε για ταξινόμηση diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index cc42c0426..e1b1bede2 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -242,7 +242,7 @@ Pardonu, eraro okazis. Pardonon, io mizokasis. Kio okazis: - Kio:\\nPeto:\\nEnhavlingvo:\\nEnhavlando:\\nAplingvo:\\nServo:\\nGMT Horo:\\nPako:\\nVersio:\\nOperaciumo versio: + Kio:\nPeto:\nEnhavlingvo:\nEnhavlando:\nAplingvo:\nServo:\nGMT Horo:\nPako:\nVersio:\nOperaciumo versio: Aŭdio Komenci Paŭzigi diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index a2ab5ca52..9838eb3c1 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -78,7 +78,7 @@ Copiado al portapapeles Defina una carpeta de descargas más tarde en los ajustes La interfaz de la aplicación dejó de funcionar - Qué:\\nSolicitud:\\nIdioma del contenido:\\nPaís del contenido:\\nIdioma de la aplicación:\\nServicio:\\nMarca de tiempo:\\nPaquete:\\nVersión:\\nVersión del SO: + Qué:\nSolicitud:\nIdioma del contenido:\nPaís del contenido:\nIdioma de la aplicación:\nServicio:\nMarca de tiempo:\nPaquete:\nVersión:\nVersión del SO: Negro Todo Abrir en modo emergente diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index 6459c05a0..5d7e829f3 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -141,7 +141,7 @@ Teata Info: Mis juhtus: - Mis:\\nPäring:\\nSisu keel:\\nSisu maa:\\nRakenduse keel:\\nTeenus:\\nGMT aeg:\\nPakett:\\nVersioon:\\nOS versioon: + Mis:\nPäring:\nSisu keel:\nSisu maa:\nRakenduse keel:\nTeenus:\nGMT aeg:\nPakett:\nVersioon:\nOS versioon: Oma kommentaar (inglise keeles): Üksikasjad: Esita video, kestus: diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 1bac3b498..8b23cf8ea 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -78,7 +78,7 @@ Salatu Informazioa: Zer gertatu da: - Zer:\\nEskaria:\\nEdukiaren hizkuntza:\\nEdukiaren herrialdea:\\nAplikazioaren hizkuntza:\\nZerbitzua:\\nDenbora-zigilua:\\nPaketea:\\nBertsioa:\\nSE bertsioa: + Zer:\nEskaria:\nEdukiaren hizkuntza:\nEdukiaren herrialdea:\nAplikazioaren hizkuntza:\nZerbitzua:\nDenbora-zigilua:\nPaketea:\nBertsioa:\nSE bertsioa: Zure iruzkina (Ingelesez): Xehetasunak: Bideoa diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index cd2d1ec32..09a01e0bd 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -275,7 +275,7 @@ نمایش راهنما هنگام فشردن پس زمینه یا دکمهٔ تصویر در تصویر در «جزییات:» ویدیو برای در صف قرار دادن، نگه دارید بازگردانی - چی:\\nدرخواست:\\nزبان محتوا:\\nکشور محتوا:\\nزبان اپ:\\nخدمت:\\nزمان GMT\\nپکیج:T:\\nنسخه:\\nنسخه‌اندروید: + چی:\nدرخواست:\nزبان محتوا:\nکشور محتوا:\nزبان اپ:\nخدمت:\nزمان GMT\nپکیج:T:\nنسخه:\nنسخه‌اندروید: چالش ری‌کپچا نیاز به چالش ری‌کپچا است این اجازه برای گشودن در حالت diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 3f66a85eb..1ce4df009 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -155,7 +155,7 @@ Haluatko poistaa tämän hakuhistoriasta? Jatka toistoa Info: - Mikä:\\nPyyntö:\\nSisällön kieli:\\nSisällön maa:\\n:Sovelluksen kieli:\\nPalvelu:\\nGMT Aika:\\nPaketti:\\nVersio:\\nOS versio: + Mikä:\nPyyntö:\nSisällön kieli:\nSisällön maa:\n:Sovelluksen kieli:\nPalvelu:\nGMT Aika:\nPaketti:\nVersio:\nOS versio: © %1$s %2$s %3$s alla Pääsivun sisältö Tyhjä sivu diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index efd735bc8..f7459e409 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -86,7 +86,7 @@ Ouvrir en mode flottant Lecture en mode flottant Désactivés - Quoi :\\nRequest :\\nContent Language :\\nContent Country :\\nApp Language :\\nService :\\nGMT Time :\\nPackage :\\nVersion :\\nOS version : + Quoi :\nRequest :\nContent Language :\nContent Country :\nApp Language :\nService :\nGMT Time :\nPackage :\nVersion :\nOS version : Cette autorisation est nécessaire pour \nutiliser le mode flottant Arrière-plan diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 6c7fa3e3c..bea6c2eb7 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -145,7 +145,7 @@ Informe Información: Que ocorreu: - Que: \\n Solicitar: \\n Idioma de contido: \\n País de contido: \\n Idioma do aplicativo: \\nServicio: \\n Tempo GMT: \\n Paquete: \\n Versión: \\n versión de nOS: + Que: \n Solicitar: \n Idioma de contido: \n País de contido: \n Idioma do aplicativo: \nServicio: \n Tempo GMT: \n Paquete: \n Versión: \n versión de nOS: O teu comentario (en inglés): Detalles: Reproducir o vídeo, duración: diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index 24d916464..3d630394f 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -73,7 +73,7 @@ דיווח מידע: מה קרה: - מה:\\nבקשה:\\nשפת התוכן:\\nמדינת התוכן:\\nשפת היישומון:\\nשירות:\\nשעון גריניץ׳:\\nחבילה:\\nגרסה:\\nגרסת מערכת ההפעלה: + מה:\nבקשה:\nשפת התוכן:\nמדינת התוכן:\nשפת היישומון:\nשירות:\nשעון גריניץ׳:\nחבילה:\nגרסה:\nגרסת מערכת ההפעלה: רישום למינוי נרשמת ביטול מינוי לערוץ diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 5c7be01b4..3a5cda8c9 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -114,7 +114,7 @@ रिपोर्ट करें जानकारी: क्या हुआ: - क्या:\\nअनुरोध:\\nसामग्री भाषा:\\nसामग्री देश:\\nऐप भाषा:\\nसेवा:\\nजीएमटी समय:\\nपैकेज:\\nसंस्करण:\\nOS संस्करण: + क्या:\nअनुरोध:\nसामग्री भाषा:\nसामग्री देश:\nऐप भाषा:\nसेवा:\nजीएमटी समय:\nपैकेज:\nसंस्करण:\nOS संस्करण: आपकी टिप्पणी(अंग्रेजी में): विवरण: वीडियो चलाएं, अवधि : diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 85a2fa367..757f6244d 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -87,7 +87,7 @@ Prijavi Informacije: Što se dogodilo: - Što:\\nZahtjev:\\nJezik sadržaja:\\nZemlja sadržaja:\\nJezik aplikacije:\\nUsluga:\\nGMT vrijeme:\\nPaket:\\nVerzija:\\nVerzija OS-a: + Što:\nZahtjev:\nJezik sadržaja:\nZemlja sadržaja:\nJezik aplikacije:\nUsluga:\nGMT vrijeme:\nPaket:\nVerzija:\nVerzija OS-a: Tvoj komentar (na engleskom): Detalji: Pokreni video, trajanje: diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 03f868de9..1110fd248 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -129,7 +129,7 @@ A külső lejátszó nem támogatja az ilyen típusú hivatkozásokat Nem található videófolyam Nem található hangfolyam - Mi:\\nKérés:\\nTartalom nyelve:\\nTartalom származási országa:\\nAlkalmazás nyelve:\\nSzolgáltatás:\\nGMT idő:\\nCsomag:\\nVerzió:\\nOperációs rendszer verzió: + Mi:\nKérés:\nTartalom nyelve:\nTartalom származási országa:\nAlkalmazás nyelve:\nSzolgáltatás:\nGMT idő:\nCsomag:\nVerzió:\nOperációs rendszer verzió: Nincs találat Közvetítési fájl letöltése Hozzáadás ehhez diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 003994de2..d023e9fb3 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -76,7 +76,7 @@ Silakan pilih folder unduhan di pengaturan Pemutar penjaliran tidak ditemukan. Pasang VLC? App/UI rusak - Apa:\\nPermintaan:\\nBahasa Konten:\\nNegara Konten:\\nBahasa Apl:\\nLayanan:\\nWaktu GMT:\\nPaket:\\nVersi:\\nVersi OS: + Apa:\nPermintaan:\nBahasa Konten:\nNegara Konten:\nBahasa Apl:\nLayanan:\nWaktu GMT:\nPaket:\nVersi:\nVersi OS: Thread Tantangan reCAPTCHA Meminta kode reCAPTCHA diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml index cf3fbd8b2..34c29ff10 100644 --- a/app/src/main/res/values-is/strings.xml +++ b/app/src/main/res/values-is/strings.xml @@ -212,7 +212,7 @@ Því miður fór eitthvað úrskeiðis. Líkar við Það sem gerðist: - Hvað:\\nBeiðni:\\nTungumál Efnis:\\nLand Efnis:\\nTungumál forrits:\\nÞjónusta:\\nGMT Tími:\\nPakki:\\nÚtgáfa:\\nÚtgáfu Stýrikerfis: + Hvað:\nBeiðni:\nTungumál Efnis:\nLand Efnis:\nTungumál forrits:\nÞjónusta:\nGMT Tími:\nPakki:\nÚtgáfa:\nÚtgáfu Stýrikerfis: Athugasemd þín (á ensku): Engar niðurstöður Myndskeið diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 7955eed15..3a3995b14 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -78,7 +78,7 @@ Copiato negli appunti Seleziona una cartella per i file scaricati L\'app/UI si è interrotta - Cosa:\\nRichiesta:\\nLingua contenuti:\\nPaese contenuti\\nLingua app:\\nServizio:\\nOrario GMT:\\nPacchetto:\\nVersione:\\nVersione SO: + Cosa:\nRichiesta:\nLingua contenuti:\nPaese contenuti\nLingua app:\nServizio:\nOrario GMT:\nPacchetto:\nVersione:\nVersione SO: Risoluzione reCAPTCHA Nero Tutto diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index d78a06547..ac9fe3684 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -78,7 +78,7 @@ ダウンロード 不具合報告 アプリ(UI)がクラッシュしました - どんな問題:\\nリクエスト:\\nコンテンツ言語:\\nコンテンツ国:\\nアプリ言語:\\nサービス:\\nGMT 時間:\\nパッケージ:\\nバージョン:\\nOSバージョン: + どんな問題:\nリクエスト:\nコンテンツ言語:\nコンテンツ国:\nアプリ言語:\nサービス:\nGMT 時間:\nパッケージ:\nバージョン:\nOSバージョン: reCAPTCHA の要求 reCAPTCHA を要求しました ブラック diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml index 61b3ee523..444625fc0 100644 --- a/app/src/main/res/values-ka/strings.xml +++ b/app/src/main/res/values-ka/strings.xml @@ -604,7 +604,7 @@ გარე დამკვრელს არ აქვთ ამ ტიპის ბმულების მხარდაჭერა ფაილი არ არსებობს ან მასზე წაკითხვის ან ჩაწერის ნებართვა აკლია შენახული ჩანართების წაკითხვა ვერ მოხერხდა, ამიტომ გამოიყენეთ ნაგულისხმევი ჩანართები - რა:\\nმოითხოვეთ:\\nშემცველობის ენა:\\nშემცველობის ქვეყანა:\\nაპლიკაციის ენა:\\nსერვისი:\\nGMT დრო:\\nპაკეტი:\\nვერსია:\\nOS ვერსია: + რა:\nმოითხოვეთ:\nშემცველობის ენა:\nშემცველობის ქვეყანა:\nაპლიკაციის ენა:\nსერვისი:\nGMT დრო:\nპაკეტი:\nვერსია:\nOS ვერსია: ამტვირთველის ავატარის ესკიზი კომენტარები გამორთულია Შექმნა diff --git a/app/src/main/res/values-kmr/strings.xml b/app/src/main/res/values-kmr/strings.xml index f8da8d1a7..f4b83eda2 100644 --- a/app/src/main/res/values-kmr/strings.xml +++ b/app/src/main/res/values-kmr/strings.xml @@ -64,7 +64,7 @@ Vîdeo, demdirêj bilîze: Hûrî: Şîroveya we (bi Îngilîzî): - Çi:\\nRequest:\\nContent Language:\\nContent Welat:\\nApp Language:\\nService:\\nGMT Dem:\\nPackage:\\nVersion:\\nOS version: + Çi:\nRequest:\nContent Language:\nContent Welat:\nApp Language:\nService:\nGMT Dem:\nPackage:\nVersion:\nOS version: Çi qewimî: Agahdarî: Nûçe diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 8eb19ade8..59832ece4 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -113,7 +113,7 @@ 이 스트림을 재생할 수 없습니다 복구할 수 없는 플레이어 오류가 발생했습니다 플레이어 오류로부터 복구 중 - 무엇:\\n요청:\\n콘텐츠 언어:\\n콘텐츠 국가:\\n앱 언어:\\n서비스:\\nGMT 시간:\\n패키지:\\n버전:\\nOS 버전: + 무엇:\n요청:\n콘텐츠 언어:\n콘텐츠 국가:\n앱 언어:\n서비스:\nGMT 시간:\n패키지:\n버전:\nOS 버전: 결과 없음 구독할 항목을 추가하세요 구독자 없음 diff --git a/app/src/main/res/values-ku/strings.xml b/app/src/main/res/values-ku/strings.xml index e556fcf26..c788f252a 100644 --- a/app/src/main/res/values-ku/strings.xml +++ b/app/src/main/res/values-ku/strings.xml @@ -328,7 +328,7 @@ گێڕانەوەی کارپێکەر بۆکاتی پێش کێشە هەمان فۆڵدەر بوونی نییە هەمان فایل/بابەت بوونی نییە - چی:\\nداواکراو:\\nناوەڕۆک:\\nلانگ:\\nخزمەتگوزاری:\\nGMT:\\nکات:\\nپاکێج:\\nوەشان:\\nوەشانی سیستەم: + چی:\nداواکراو:\nناوەڕۆک:\nلانگ:\nخزمەتگوزاری:\nGMT:\nکات:\nپاکێج:\nوەشان:\nوەشانی سیستەم: هێما ڕێگەپێدراوەکان لە فایلێکی ناویدا هێما نادروستەکان بەم بەهایە جێگۆڕکێ دەکرێن هێمای جێگۆڕین diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 70700bb5d..dd7874809 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -74,7 +74,7 @@ Ataskaita Informacija: Kas nutiko: - Kas:\\nUžklausa:\\nTurinio Kalba:\\nTurinio Šalis:\\nProgramėlės Kalba:\\nPaslauga:\\nGMT Laikas:\\nPaketas:\\nVersija:\\nOS versija: + Kas:\nUžklausa:\nTurinio Kalba:\nTurinio Šalis:\nProgramėlės Kalba:\nPaslauga:\nGMT Laikas:\nPaketas:\nVersija:\nOS versija: Jūsų komentaras (anglų kalba): Išsami informacija: Paleisti vaizdo įrašą, trukmė: diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml index bb41037a1..0580b9dd7 100644 --- a/app/src/main/res/values-lv/strings.xml +++ b/app/src/main/res/values-lv/strings.xml @@ -151,7 +151,7 @@ Atskaņot video, ilgums: Detaļas: Jūsu komentārs (Angliski): - Kas:\\nRequest:\\nContent Valoda:\\nContent Valsts:\\nApp Valoda:\\nService:\\nGMT Laiks:\\nPackage:\\nVersion:\\nOS versija: + Kas:\nRequest:\nContent Valoda:\nContent Valsts:\nApp Valoda:\nService:\nGMT Laiks:\nPackage:\nVersion:\nOS versija: Paziņojumi video apstrādes progresam Video haša paziņojums Atcerēties pēdējo uznirstošā loga izmēru un pozīciju diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index 5ce379216..8931cef3d 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -133,7 +133,7 @@ Извештај Инфо: Што се случи: - What:\\nRequest:\\nContent Language:\\nContent Country:\\nApp Language:\\nService:\\nGMT Time:\\nPackage:\\nVersion:\\nOS version: + What:\nRequest:\nContent Language:\nContent Country:\nApp Language:\nService:\nGMT Time:\nPackage:\nVersion:\nOS version: Ваш коментар (на Англиски): Детали: Емитување на видео, времетраење diff --git a/app/src/main/res/values-ml/strings.xml b/app/src/main/res/values-ml/strings.xml index 2fce034d2..a149b910b 100644 --- a/app/src/main/res/values-ml/strings.xml +++ b/app/src/main/res/values-ml/strings.xml @@ -112,7 +112,7 @@ കൂടുതൽ വിവരങ്ങൾക്കും വാർത്തകൾക്കും ന്യൂപൈപ്പിന്റെ വെബ്സൈറ്റ് സന്ദർശിക്കുക. വെബ്സൈറ്റ് തിരികെ നൽകുക - എന്താണ്:\\nഅപേക്ഷ:\\nഉള്ളടക്കത്തിന്റെ ഭാഷ:\\nഉള്ളടക്കത്തിന്റെ രാജ്യം:\\n അപ്ലിക്കേഷന്റെ ഭാഷ:\\nസേവനം:\\nGMT സമയം:\\nപാക്കേജ്:\\nപതിപ്പ്:\\nOS ന്റെ പതിപ്പ്: + എന്താണ്:\nഅപേക്ഷ:\nഉള്ളടക്കത്തിന്റെ ഭാഷ:\nഉള്ളടക്കത്തിന്റെ രാജ്യം:\n അപ്ലിക്കേഷന്റെ ഭാഷ:\nസേവനം:\nGMT സമയം:\nപാക്കേജ്:\nപതിപ്പ്:\nOS ന്റെ പതിപ്പ്: നിങ്ങൾക്ക് മികച്ച ഉപഭോക്തൃ അനുഭവം നൽകാനായി പ്രയത്‌നിക്കുന്ന ലോകമെമ്പാടുമുള്ള വൊളന്റിയർമാരാണ് ന്യൂപൈപ്പിന്റെ ശക്തി. ന്യൂപൈപ്പിനെ ഇനിയും മികവുറ്റതാക്കാൻ നിങ്ങൾക്ക് കഴിയും, നിങ്ങളുടെ സംഭാവനയിലൂടെ. സംഭാവന ചെയ്യുക ജിറ്റ്ഹബിൽ കാണുക diff --git a/app/src/main/res/values-ms/strings.xml b/app/src/main/res/values-ms/strings.xml index b0039bf0c..bf4da3440 100644 --- a/app/src/main/res/values-ms/strings.xml +++ b/app/src/main/res/values-ms/strings.xml @@ -158,7 +158,7 @@ Lapor Maklumat: Apa yang berlaku: - Apa:\\nPermintaan:\\nBahasa Kandungan:\\nNegara Kandungan:\\nBahasa Aplikasi:\\nPerkhidmatan:\\nWaktu GMT:\\nPakej:\\nVersi:\\nVersi OS: + Apa:\nPermintaan:\nBahasa Kandungan:\nNegara Kandungan:\nBahasa Aplikasi:\nPerkhidmatan:\nWaktu GMT:\nPakej:\nVersi:\nVersi OS: Ulasan anda (dalam bahasa Inggeris): Butiran: Main video, tempoh masa: diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 404851e6d..633140dcc 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -76,7 +76,7 @@ Trykk for detaljer Vent… Kopiert til utklippstavle - Hva:\\nForespørsel:\\nInnholdsspråk:\\nInnholdsland:\\nAppspråk:\\nTjeneste:\\nGMT-tid:\\nPakke:\\nVersjon:\\nOS-versjon: + Hva:\nForespørsel:\nInnholdsspråk:\nInnholdsland:\nAppspråk:\nTjeneste:\nGMT-tid:\nPakke:\nVersjon:\nOS-versjon: Start Definer en nedlastingsmappe senere i innstillingene reCAPTCHA-oppgave diff --git a/app/src/main/res/values-ne/strings.xml b/app/src/main/res/values-ne/strings.xml index 75e113d4e..06e2bacc1 100644 --- a/app/src/main/res/values-ne/strings.xml +++ b/app/src/main/res/values-ne/strings.xml @@ -163,7 +163,7 @@ रिपोर्ट जानकारी: के भयो: - के:\\nअनुरोध:\\nसामग्री भाषा: \\nसेवा:\\nGMT समय:\\nप्याकेज:\\nसंस्करण: \\nOS संस्करण: + के:\nअनुरोध:\nसामग्री भाषा: \nसेवा:\nGMT समय:\nप्याकेज:\nसंस्करण: \nOS संस्करण: तपाईंको टिप्पणी (अंग्रेजी मा): विवरण: प्ले भिडियो, अवधि: diff --git a/app/src/main/res/values-nl-rBE/strings.xml b/app/src/main/res/values-nl-rBE/strings.xml index 148468dd2..92d36ab77 100644 --- a/app/src/main/res/values-nl-rBE/strings.xml +++ b/app/src/main/res/values-nl-rBE/strings.xml @@ -134,7 +134,7 @@ Melden Info: Wat er is gebeurd: - Wat:\\nVerzoek:\\nTaal van inhoud:\\nLand:\\nTaal van applicatie:\\nDienst:\\nGMT tijd:\\nPakket:\\nVersie:\\nVersie van besturingssysteem: + Wat:\nVerzoek:\nTaal van inhoud:\nLand:\nTaal van applicatie:\nDienst:\nGMT tijd:\nPakket:\nVersie:\nVersie van besturingssysteem: Uw opmerking (in het Engels): Details: Speel video, tijd: diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index c7aab3577..7d2f0b7be 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -65,7 +65,7 @@ Downloads Foutrapport App/UI gecrasht - Wat:\\nVerzoek:\\nInhoudstaal:\\nInhoudsland:\\nApp-taal:\\nDienst:\\nGMT-tijd:\\nPakket:\\nVersie:\\nVersie van besturingssysteem: + Wat:\nVerzoek:\nInhoudstaal:\nInhoudsland:\nApp-taal:\nDienst:\nGMT-tijd:\nPakket:\nVersie:\nVersie van besturingssysteem: Starten Pauzeren Verwijderen diff --git a/app/src/main/res/values-nqo/strings.xml b/app/src/main/res/values-nqo/strings.xml index fb6950046..abf7ad70d 100644 --- a/app/src/main/res/values-nqo/strings.xml +++ b/app/src/main/res/values-nqo/strings.xml @@ -166,7 +166,7 @@ ߘߌ߬ߢߍ߬߸ ߞߏ߫ ߘߏ߫ ߡߊ߫ ߕߊ߬ߡߌ߲߬ ߞߏߢߊ߬. ߟߌ߬ߤߟߊ: ߡߎ߲߬ ߞߍߣߍ߲߫: - ߡߎ߲߬:\\nRequest:\\nContent Language:\\nContent Country:\\nApp Language:\\nService:\\nGMT Time:\\nPackage:\\nVersion:\\nOS version: + ߡߎ߲߬:\nRequest:\nContent Language:\nContent Country:\nApp Language:\nService:\nGMT Time:\nPackage:\nVersion:\nOS version: ߌ ߟߊ߫ ߞߊ߲߬ߞߎߡߊ (ߊ߲߬ߞߌ߬ߟߍ߬ ߞߊ߲ ߘߐ߫): ߕߐ߬ߝߍ߬ߦߊ ߟߎ߬: ߦߋߡߍ߲ߕߊ ߘߐߞߊ߬ߙߊ߲߸ ߥߎ߬ߛߎ: diff --git a/app/src/main/res/values-or/strings.xml b/app/src/main/res/values-or/strings.xml index d15afa4fe..c9d0e6758 100644 --- a/app/src/main/res/values-or/strings.xml +++ b/app/src/main/res/values-or/strings.xml @@ -461,7 +461,7 @@ ଫାଇଲ୍ ବିଦ୍ୟମାନ ନାହିଁ କିମ୍ବା ଏହାକୁ ପଢ଼ିବା କିମ୍ବା ଲେଖିବା ପାଇଁ ଅନୁମତି ଅଭାବ ଏପରି ଫୋଲ୍ଡର ନାହିଁ ସଞ୍ଚିତ ଟ୍ୟାବଗୁଡିକ ପଢ଼ି ପାରିଲା ନାହିଁ, ତେଣୁ ଡିଫଲ୍ଟଗୁଡିକ ବ୍ୟବହାର କରି - କଣ:\\nRequest:\\nContent Language:\\nContent Country:\\nApp Language:\\nService:\\nGMT Time:\\nPackage:\\nVersion:\\nOS ସଂସ୍କରଣ: + କଣ:\nRequest:\nContent Language:\nContent Country:\nApp Language:\nService:\nGMT Time:\nPackage:\nVersion:\nOS ସଂସ୍କରଣ: କୌଣସି ଫଳାଫଳ ନାହିଁ ଏଠାରେ କ୍ରିକେଟ୍ ବ୍ୟତୀତ ଆଉ କିଛି ନାହିଁ ପୁନଃଚେଷ୍ଟା କରନ୍ତୁ diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml index 2c6158355..8c69dd850 100644 --- a/app/src/main/res/values-pa/strings.xml +++ b/app/src/main/res/values-pa/strings.xml @@ -140,7 +140,7 @@ ਇਤਲਾਹ ਕਰੋ ਜਾਣਕਾਰੀ: ਕੀ ਹੋਇਆ ਹੈ: - ਕੀ:\\nRequest:\\nContent ਭਾਸ਼ਾ/ਬੋਲੀ:\\nContent Country:\\nApp ਭਾਸ਼ਾ/ਬੋਲੀ:\\nService:\\nGMT ਸਮਾਂ:\\nPackage:\\nVersion:\\nOS version: + ਕੀ:\nRequest:\nContent ਭਾਸ਼ਾ/ਬੋਲੀ:\nContent Country:\nApp ਭਾਸ਼ਾ/ਬੋਲੀ:\nService:\nGMT ਸਮਾਂ:\nPackage:\nVersion:\nOS version: ਤੁਹਾਡੀ ਟਿੱਪਣੀ (ਅੰਗਰੇਜ਼ੀ ਵਿਚ): ਵੇਰਵੇ: ਵੀਡੀਓ ਚਲਾਓ, ਮਿਆਦ: diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index c72e6de26..910b11044 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -55,7 +55,7 @@ Zgłoś Informacje: Co się stało: - Co:\\nŻądanie:\\nJęzyk treści:\\nKraj treści:\\nJęzyk aplikacji:\\nUsługa:\\nZnacznik czasu:\\nPakiet:\\nWersja:\\nWersja systemu: + Co:\nŻądanie:\nJęzyk treści:\nKraj treści:\nJęzyk aplikacji:\nUsługa:\nZnacznik czasu:\nPakiet:\nWersja:\nWersja systemu: Twój komentarz (po angielsku): Szczegóły: Odtwarzane wideo, czas trwania: diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 7488e69c7..44cfb9e2a 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -81,7 +81,7 @@ Usar player de áudio externo Usar player de vídeo externo Mostrar opção \"Reproduzir no Kodi\" - O que aconteceu:\\nPedido:\\nIdioma do conteúdo:\\nPaís do conteúdo:\\nIdioma do aplicativo:\\nServiço:\\nHora GMT:\\nPacote:\\nVersão:\\nVersão do SO: + O que aconteceu:\nPedido:\nIdioma do conteúdo:\nPaís do conteúdo:\nIdioma do aplicativo:\nServiço:\nHora GMT:\nPacote:\nVersão:\nVersão do SO: Abrir no modo Popup Resolução padrão do Popup Mostrar resoluções mais altas diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 4e9a85522..80f943ce5 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -202,7 +202,7 @@ Gerar nome único Ação a executar ao trocar para outra aplicação a partir do menu principal - %s Utilizar reprodutor de vídeo externo - O quê:\\nPedido:\\nIdioma do conteúdo:\\nPaís do conteúdo\\nIdioma da aplicação\\nServiço:\\nHora GMT:\\nPacote:\\nVersão:\\nSO Versão: + O quê:\nPedido:\nIdioma do conteúdo:\nPaís do conteúdo\nIdioma da aplicação\nServiço:\nHora GMT:\nPacote:\nVersão:\nSO Versão: Se tem ideias para: tradução, alterações de desenho, limpeza de código, ou alterações significativas no código fonte - todas as ajudas são bem-vindas. Quanto mais se faz, melhor ficará! Limpar dados Apenas uma vez diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index e18984dc2..1ae1f8b6f 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -78,7 +78,7 @@ Processos Descarga NewPipe Aplicação terminou em erro - O quê:\\nPedido:\\nIdioma do conteúdo:\\nPaís do conteúdo\\nIdioma da aplicação\\nServiço:\\nHora GMT:\\nPacote:\\nVersão:\\nSO Versão: + O quê:\nPedido:\nIdioma do conteúdo:\nPaís do conteúdo\nIdioma da aplicação\nServiço:\nHora GMT:\nPacote:\nVersão:\nSO Versão: Abrir no modo popup Preto Tudo diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index ccd1483a1..2afe73875 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -91,7 +91,7 @@ Toate Dezactivat Aplicația/UI s-a oprit - Ce:\\nSolicitare:\\nLimba conținutului:\\nȚara conținutului:\\nLimba aplicației:\\nServiciu:\\nOra GMT:\\nPachet:\\nVersiune:\\nVersiune SO: + Ce:\nSolicitare:\nLimba conținutului:\nȚara conținutului:\nLimba aplicației:\nServiciu:\nOra GMT:\nPachet:\nVersiune:\nVersiune SO: Elimină sunetul audio la anumite rezoluții Fundal Pop-up diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index b96667f93..a10681060 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -87,7 +87,7 @@ Воспроизведение во всплывающем окне Очистить Всё - Что:\\nЗапрос:\\nЯзык контента:\\nСтрана контента:\\nЯзык приложения:\\nСервис:\\nВремя по Гринвичу:\\nПакет:\\nВерсия пакета:\\nВерсия ОС: + Что:\nЗапрос:\nЯзык контента:\nСтрана контента:\nЯзык приложения:\nСервис:\nВремя по Гринвичу:\nПакет:\nВерсия пакета:\nВерсия ОС: Это разрешение нужно для \nвоспроизведения в окне Открыть во всплывающем окне diff --git a/app/src/main/res/values-ryu/strings.xml b/app/src/main/res/values-ryu/strings.xml index 6b70c0c8e..4be7d5328 100644 --- a/app/src/main/res/values-ryu/strings.xml +++ b/app/src/main/res/values-ryu/strings.xml @@ -78,7 +78,7 @@ ダウンロード ふぐあいほうくーく アプリ(UI)やしがクラッシュさびたん - ちゃーるむんだい:\\nリクエスト:\\nコンテンツぬぎんぐ:\\nコンテンツぬくに:\\nアプリぬぎんぐ:\\nサービス:\\nGMTじかん:\\nパッケージ:\\nバージョン:\\nOSぬバージョン: + ちゃーるむんだい:\nリクエスト:\nコンテンツぬぎんぐ:\nコンテンツぬくに:\nアプリぬぎんぐ:\nサービス:\nGMTじかん:\nパッケージ:\nバージョン:\nOSぬバージョン: reCAPTCHAぬようきゅう reCAPTCHAようきゅうさびたん ブラック diff --git a/app/src/main/res/values-sat/strings.xml b/app/src/main/res/values-sat/strings.xml index 88e9cfca1..71a8067b1 100644 --- a/app/src/main/res/values-sat/strings.xml +++ b/app/src/main/res/values-sat/strings.xml @@ -209,7 +209,7 @@ ᱢᱤᱫ ᱵᱷᱩᱞ ᱦᱩᱭ ᱞᱮᱱᱟ, ᱱᱤᱴᱤᱯᱷᱤᱠᱮᱥᱚᱱ ᱧᱮᱞ ᱢᱮ GitHub ᱨᱮ ᱚᱱᱚᱞ ᱨᱤᱯᱚᱨᱴ - What:\\nRequest:\\nContent Language:\\nContent ᱫᱤᱥᱚᱢ:\\nApp Language:\\nService:\\nGMT ᱚᱠᱛᱚ:\\nPackage:\\nVersion:\\nOS version: + What:\nRequest:\nContent Language:\nContent ᱫᱤᱥᱚᱢ:\nApp Language:\nService:\nGMT ᱚᱠᱛᱚ:\nPackage:\nVersion:\nOS version: ᱟᱢᱟᱜ ᱯᱟᱹᱛᱭᱟᱹᱣ (ᱤᱝᱞᱤᱥ ᱛᱮ): ᱚᱯᱞᱚᱰᱟᱨᱟᱜ ᱟᱵᱟᱛᱟᱨ ᱛᱷᱩᱱᱤᱠᱟ ᱞᱟᱭᱠ diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml index dcaf7290e..f47e8e569 100644 --- a/app/src/main/res/values-sc/strings.xml +++ b/app/src/main/res/values-sc/strings.xml @@ -224,7 +224,7 @@ Esportende… B\'at bisòngiu de custu permissu pro \nabèrrere sa modalidade ventanedda - Ite:\\nRechesta:\\nLimba de su cuntenutu\\nIstadu de su cuntenutu:\\nLimba de s\'aplicatzione:\\nServìtziu:\\nOràriu GMT:\\nPachete:\\nVersione:\\nVersione SO: + Ite:\nRechesta:\nLimba de su cuntenutu\nIstadu de su cuntenutu:\nLimba de s\'aplicatzione:\nServìtziu:\nOràriu GMT:\nPachete:\nVersione:\nVersione SO: A dolu mannu b\'at àpidu carchi problema. Cronologia de chirca iscantzellada Custu vìdeu tenet unu lìmite de edade. diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index e05ab3842..ff6cd720a 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -78,7 +78,7 @@ Stiahnuté Hlásenie o chybe Aplikácia/UP zlyhalo - Čo:\\nPožiadavka:\\nJazyk obsahu:\\nKrajina Obsahu:\\nJazyk Aplikácie:\\nSlužba:\\nČas v GMT:\\nBalík:\\nVerzia:\\nOS: + Čo:\nPožiadavka:\nJazyk obsahu:\nKrajina Obsahu:\nJazyk Aplikácie:\nSlužba:\nČas v GMT:\nBalík:\nVerzia:\nOS: Výzva reCAPTCHA Čierna Všetko diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index 8b4ba8f7b..ed316e93e 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -80,7 +80,7 @@ Program se je sesul Izziv reCAPTCHA Zahtevan izziv reCAPTCHA - Predmet:\\nZahteva:\\nJezik vsebine:\\nDržava vsebine:\\nJezik aplikacije:\\nStoritev:\\nČas v GMT:\\nPaket:\\nRazličica:\\nRazličica OS: + Predmet:\nZahteva:\nJezik vsebine:\nDržava vsebine:\nJezik aplikacije:\nStoritev:\nČas v GMT:\nPaket:\nRazličica:\nRazličica OS: Črna Vse Odpri v pojavnem načinu diff --git a/app/src/main/res/values-so/strings.xml b/app/src/main/res/values-so/strings.xml index f40df57f1..1453e3491 100644 --- a/app/src/main/res/values-so/strings.xml +++ b/app/src/main/res/values-so/strings.xml @@ -252,7 +252,7 @@ inta ka heshay Sawirka u saaran soosaareha Daar muuqaalka, intuu socdo: - Shayga:\\nCodsiga:\\nLuuqada Shayga:\\nWadanka Shayga:\\nLuuqada Appka:\\nAdeega:\\nWakhtiga oo GMT ah:\\nXidhmada:\\nTirsiga Appka:\\nTirsiga Nooca Barnaamijka: + Shayga:\nCodsiga:\nLuuqada Shayga:\nWadanka Shayga:\nLuuqada Appka:\nAdeega:\nWakhtiga oo GMT ah:\nXidhmada:\nTirsiga Appka:\nTirsiga Nooca Barnaamijka: Faahfaahin: Faalladaada (oo Ingiriis ah): Waxa dhacay: diff --git a/app/src/main/res/values-sq/strings.xml b/app/src/main/res/values-sq/strings.xml index 5a33ad77f..398a6cf45 100644 --- a/app/src/main/res/values-sq/strings.xml +++ b/app/src/main/res/values-sq/strings.xml @@ -307,7 +307,7 @@ Luaje videon, kohëzgjatja: Detajet: Komenti juaj (në Anglisht): - Çfarë:\\nKërkesa:\\nGjuha e përmbajtjes:\\nShteti i pëmbajtjes:\\nGjuha e aplikacionit:\\nShërbimi:\\nKoha në GMT:\\nPaketa:\\nVersioni:\\nVersioni i sistemit operativ: + Çfarë:\nKërkesa:\nGjuha e përmbajtjes:\nShteti i pëmbajtjes:\nGjuha e aplikacionit:\nShërbimi:\nKoha në GMT:\nPaketa:\nVersioni:\nVersioni i sistemit operativ: Çfarë ndodhi: Informacion: Raporto diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 847b60f2f..2d14361b3 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -78,7 +78,7 @@ Преузимања Извештај о грешци Програм је отказао - Шта:\\nЗахтев:\\nЈезик садржаја:\\nДржава садржаја:\\nЈезик апликације:\\nУслуга:\\nGMT време:\\nПакет:\\nВерзија:\\nВерзија ОС-а: + Шта:\nЗахтев:\nЈезик садржаја:\nДржава садржаја:\nЈезик апликације:\nУслуга:\nGMT време:\nПакет:\nВерзија:\nВерзија ОС-а: „reCAPTCHA“ задатак Решите „reCAPTCHA“ задатак Црна diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 7806044ce..d9742c80e 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -104,7 +104,7 @@ Allvarligt spelarfel inträffade Återhämtar sig från spelarfel Rapportera via e-post - Vad:\\nBegäran:\\nInnehållsspråk:\\nInnehållsland:\\nApp-språk:\\nTjänst:\\nGMT-tid:\\nPaket:\\nVersion:\\nOS-version: + Vad:\nBegäran:\nInnehållsspråk:\nInnehållsland:\nApp-språk:\nTjänst:\nGMT-tid:\nPaket:\nVersion:\nOS-version: Spela video, längd: Uppladdarens avatar-miniatyrbild Inga resultat diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml index b7534ccc0..068a099d2 100644 --- a/app/src/main/res/values-ta/strings.xml +++ b/app/src/main/res/values-ta/strings.xml @@ -256,7 +256,7 @@ இயல்பிருப்புகளை மீட்டெடு NewPipe பிழையைச் எதிர்கொண்டது, புகாரளிக்க தட்டு புகாரளி - என்ன:\\nகோரிக்கை:\\nஉள்ளடக்க மொழி:\\nஉள்ளடக்க நாடு:\\nசெயலி மொழி:\\nசேவை:\\nGMT நேரம்:\\nசிப்பம்:\\nபதிப்பு:\\nOS பதிப்பு: + என்ன:\nகோரிக்கை:\nஉள்ளடக்க மொழி:\nஉள்ளடக்க நாடு:\nசெயலி மொழி:\nசேவை:\nGMT நேரம்:\nசிப்பம்:\nபதிப்பு:\nOS பதிப்பு: காணொளியை இயக்கு, காலவளவு: கருத்தளிப்புகள் இயக்கியைச் சிதை diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index aa641503b..9c84ee81d 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -55,7 +55,7 @@ Bildir Bilgi: Ne oldu: - Ne:\\nİstek:\\nİçerik Dili:\\nİçerik Ülkesi:\\nUygulama Dili:\\nHizmet:\\nGMT Zamanı:\\nPaket:\\nSürüm:\\nİşletim sistemi sürümü: + Ne:\nİstek:\nİçerik Dili:\nİçerik Ülkesi:\nUygulama Dili:\nHizmet:\nGMT Zamanı:\nPaket:\nSürüm:\nİşletim sistemi sürümü: Videoyu oynat, süre: Yükleyenin avatar küçük resmi Beğeni diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 4526ea837..df8ee490d 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -170,7 +170,7 @@ Показувати підказку під час натискання фонової або спливної кнопки у відео \"Деталі:\" Сталася невиправна помилка програвача Зовнішні програвачі не підтримують такі види посилань - Що:\\nЗапит:\\nМова вмісту:\\nКраїна вмісту:\\nМова застосунку:\\nСлужба:\\nЧас GMT:\\nПакунок:\\nВерсія:\\nВерсія ОС: + Що:\nЗапит:\nМова вмісту:\nКраїна вмісту:\nМова застосунку:\nСлужба:\nЧас GMT:\nПакунок:\nВерсія:\nВерсія ОС: Мініатюрний аватар завантажувача відео Вподобані Не сподобалося diff --git a/app/src/main/res/values-ur/strings.xml b/app/src/main/res/values-ur/strings.xml index bb95e2811..6c596b64c 100644 --- a/app/src/main/res/values-ur/strings.xml +++ b/app/src/main/res/values-ur/strings.xml @@ -133,7 +133,7 @@ رپورٹ کریں معلومات: کیا ہوا: - کیا ہوا:\\nدرخواست:\\nمواد کی زبان:\\nملک:\\nایپ کی زبان:\\nسروس:\\nجی ایم ٹٰ:\\nوقت:\\nپیکیج:\\nورژن:\\nآپریٹنگ سسٹم ورزن: + کیا ہوا:\nدرخواست:\nمواد کی زبان:\nملک:\nایپ کی زبان:\nسروس:\nجی ایم ٹٰ:\nوقت:\nپیکیج:\nورژن:\nآپریٹنگ سسٹم ورزن: آپ کا تبصرہ (انگریزی میں): تفصیلات: ویڈیو چلائیں، دورانیہ: diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index cde4821fa..efa12f11d 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -72,7 +72,7 @@ Báo cáo Thông tin: Chuyện gì đã xảy ra: - Loại lỗi:\\nYêu cầu:\\nNgôn ngữ của nội dung:\\nVùng miền (quốc gia) của nội dung:\\nNgôn ngữ của ứng dụng:\\nDịch vụ:\\nThời gian GMT:\\nTên gói:\\nPhiên bản:\\nPhiên bản hệ điều hành: + Loại lỗi:\nYêu cầu:\nNgôn ngữ của nội dung:\nVùng miền (quốc gia) của nội dung:\nNgôn ngữ của ứng dụng:\nDịch vụ:\nThời gian GMT:\nTên gói:\nPhiên bản:\nPhiên bản hệ điều hành: Nhận xét của bạn (bằng tiếng Anh): Chi tiết: Phát video, thời lượng: diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 88b30af5e..adbf2ce64 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -146,7 +146,7 @@ 反馈 信息: 发生了什么: - 详情:\\n请求:\\n内容语言:\\n内容国家:\\n客户端语言:\\n服务:\\nGMT时间:\\n包名:\\n版本:\\n操作系统版本: + 详情:\n请求:\n内容语言:\n内容国家:\n客户端语言:\n服务:\nGMT时间:\n包名:\n版本:\n操作系统版本: 您的附加说明(请用英文): 详细信息: 播放视频,时长: diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index c483ca96b..0dd10f1bc 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -86,7 +86,7 @@ 浮面播緊 全部嘢 App/界面閃退 - 經過:\\n請求:\\n內容語言:\\n內容國家:\\nApp 語言:\\n服務:\\nGMT 時間:\\n封裝:\\n版本:\\nOS 版本: + 經過:\n請求:\n內容語言:\n內容國家:\nApp 語言:\n服務:\nGMT 時間:\n封裝:\n版本:\nOS 版本: reCAPTCHA 考驗 以浮面模式開啟 \n有呢個權限至得 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index f5ebc2bf8..1f4bfb290 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -76,7 +76,7 @@ 回報 資訊: 發生了什麼事: - 發生了什麼:\\n請求:\\n內容語言:\\n內容國家:\\n應用程式語言:\\n服務:\\nGMT 時間:\\n套件:\\n版本:\\n系統版本: + 發生了什麼:\n請求:\n內容語言:\n內容國家:\n應用程式語言:\n服務:\nGMT 時間:\n套件:\n版本:\n系統版本: 您的留言 (請用英語): 詳細資訊: 影片 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1a2a5b6f1..9095fe927 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -271,7 +271,7 @@ Report Info: What happened: - What:\\nRequest:\\nContent Language:\\nContent Country:\\nApp Language:\\nService:\\nTimestamp:\\nPackage:\\nVersion:\\nOS version: + What:\nRequest:\nContent Language:\nContent Country:\nApp Language:\nService:\nTimestamp:\nPackage:\nVersion:\nOS version: Your comment (in English): Details: From 6c69a5409b9313a9b6853cf609ce2216bac6fa96 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Wed, 11 Feb 2026 22:49:11 +0100 Subject: [PATCH 28/56] Translated using Weblate (Slovak) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 77.5% (69 of 89 strings) Translated using Weblate (Basque) Currently translated at 100.0% (764 of 764 strings) Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (764 of 764 strings) Translated using Weblate (Portuguese (Brazil)) Currently translated at 49.4% (44 of 89 strings) Translated using Weblate (Icelandic) Currently translated at 99.2% (758 of 764 strings) Translated using Weblate (Czech) Currently translated at 100.0% (89 of 89 strings) Translated using Weblate (French) Currently translated at 100.0% (89 of 89 strings) Translated using Weblate (Chinese (Simplified Han script)) Currently translated at 100.0% (89 of 89 strings) Translated using Weblate (German) Currently translated at 100.0% (89 of 89 strings) Added translation using Weblate (Gaelic) Translated using Weblate (French) Currently translated at 77.2% (68 of 88 strings) Translated using Weblate (Turkish) Currently translated at 34.0% (30 of 88 strings) Co-authored-by: Erenay Co-authored-by: Fjuro Co-authored-by: Hosted Weblate Co-authored-by: Mickaël Binos Co-authored-by: Milan Co-authored-by: Nico Co-authored-by: S.B. MacQueen Co-authored-by: Sveinn í Felli Co-authored-by: Thadah D. Denyse Co-authored-by: VfBFan Co-authored-by: delvani Co-authored-by: 大王叫我来巡山 Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/cs/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/de/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/fr/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pt_BR/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/sk/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/tr/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/zh_Hans/ Translation: NewPipe/Metadata --- app/src/main/res/values-eu/strings.xml | 4 +- app/src/main/res/values-gd/strings.xml | 3 ++ app/src/main/res/values-is/strings.xml | 10 ++++- app/src/main/res/values-pt-rBR/strings.xml | 2 +- .../metadata/android/cs/changelogs/1008.txt | 4 ++ .../metadata/android/de/changelogs/1007.txt | 12 +++++- .../metadata/android/de/changelogs/1008.txt | 4 ++ .../metadata/android/fr/changelogs/1000.txt | 16 +++---- .../metadata/android/fr/changelogs/1005.txt | 5 --- .../metadata/android/fr/changelogs/1008.txt | 4 ++ .../metadata/android/fr/changelogs/65.txt | 41 +----------------- .../metadata/android/fr/changelogs/66.txt | 42 ------------------- .../metadata/android/fr/changelogs/68.txt | 30 ------------- .../metadata/android/fr/changelogs/69.txt | 9 ---- .../metadata/android/fr/changelogs/70.txt | 20 +-------- .../metadata/android/fr/changelogs/740.txt | 16 +------ .../metadata/android/fr/changelogs/750.txt | 26 ------------ .../metadata/android/fr/changelogs/760.txt | 34 --------------- .../metadata/android/fr/changelogs/800.txt | 21 ---------- .../metadata/android/fr/changelogs/810.txt | 10 ----- .../metadata/android/fr/changelogs/840.txt | 13 ------ .../metadata/android/fr/changelogs/930.txt | 7 ---- .../metadata/android/fr/changelogs/992.txt | 2 - .../metadata/android/fr/changelogs/993.txt | 1 - .../metadata/android/fr/changelogs/994.txt | 3 -- .../metadata/android/fr/changelogs/995.txt | 5 +-- .../metadata/android/fr/changelogs/997.txt | 7 +--- .../metadata/android/fr/changelogs/999.txt | 2 - .../android/pt-BR/changelogs/1000.txt | 20 ++++----- .../metadata/android/sk/changelogs/1008.txt | 4 ++ .../metadata/android/tr/changelogs/995.txt | 16 +++++++ .../android/zh-Hans/changelogs/1007.txt | 12 +++++- .../android/zh-Hans/changelogs/1008.txt | 4 ++ 33 files changed, 93 insertions(+), 316 deletions(-) create mode 100644 app/src/main/res/values-gd/strings.xml create mode 100644 fastlane/metadata/android/cs/changelogs/1008.txt create mode 100644 fastlane/metadata/android/de/changelogs/1008.txt create mode 100644 fastlane/metadata/android/fr/changelogs/1008.txt create mode 100644 fastlane/metadata/android/sk/changelogs/1008.txt create mode 100644 fastlane/metadata/android/tr/changelogs/995.txt create mode 100644 fastlane/metadata/android/zh-Hans/changelogs/1008.txt diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 8b23cf8ea..a34a050fa 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -494,8 +494,8 @@ Kanalaren avatarraren miniatura Erakutsi taldekatuta ez dauden harpidetzak soilik Bai, partzialki ikusitako bideoak ere bai - Dagoeneko ikusi eta gero erreprodukzio-zerrendara gehitu diren bideoak kendu egingo dira. \nJarraitu nahi duzu? Ekintza hau ezin da desegin! - Ikusitako bideoak kendu? + Dagoeneko ikusi eta gero erreprodukzio-zerrendara gehitu diren igorpenak kendu egingo dira. \nJarraitu nahi duzu? + Ikusitako igorpenak kendu? Kendu ikusitako bideoak Inoiz ez WiFi-arekin soilik diff --git a/app/src/main/res/values-gd/strings.xml b/app/src/main/res/values-gd/strings.xml new file mode 100644 index 000000000..55344e519 --- /dev/null +++ b/app/src/main/res/values-gd/strings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml index 34c29ff10..029c411ef 100644 --- a/app/src/main/res/values-is/strings.xml +++ b/app/src/main/res/values-is/strings.xml @@ -212,7 +212,7 @@ Því miður fór eitthvað úrskeiðis. Líkar við Það sem gerðist: - Hvað:\nBeiðni:\nTungumál Efnis:\nLand Efnis:\nTungumál forrits:\nÞjónusta:\nGMT Tími:\nPakki:\nÚtgáfa:\nÚtgáfu Stýrikerfis: + Hvað:\nBeiðni:\nTungumál efnis:\nLandsvæði efnis:\nTungumál forrits:\nÞjónusta:\nTímastimpill:\nPakki:\nÚtgáfa:\nÚtgáfa stýrikerfis: Athugasemd þín (á ensku): Engar niðurstöður Myndskeið @@ -369,7 +369,7 @@ Fjarleitar leitartillögur Halda áfram Óstudd vefslóð - Sjálfgefið efnisland + Sjálfgefið landsvæði efnis PeerTube þjónar Bæta við Sláðu inn slóð tilviks @@ -817,4 +817,10 @@ Eyða færslu Aðgangi lokað\n\n%1$s gefur þessa ástæðu: %2$s Færslu eytt + Samsettur vinsældalisti YouTube fjarlægður + YouTube hætti með samsetta vinsældalistann sinn frá og með 21. júlí 2025. NewPipe skipti út sjálfgefna vinsældalistanum fyrir vinsæl streymi í beinni útsendingu.\n\nÞú getur líka valið annað vinsælt efni með því að fara í \"Stillingar > Efni > Efni aðalsíðu\". + Tók við HTTP-villu 403 frá þjóni á meðan afspilun stóð, líklega vegna útrunninar URL-slóðar streymis eða banns á IP-vistfang + Tók við HTTP-villu %1$s frá þjóni á meðan afspilun stóð + Tók við HTTP-villu 403 frá þjóni á meðan afspilun stóð, líklega vegna banns á IP-vistfang eða vandamála með afkóðun URL-slóðar streymis + Þetta efni er ekki í boði fyrir valið landsvæði efnis.\n\nBreyttu valinu með því að fara í \"Stillingar > Efni > Sjálfgefið landsvæði efnis\". diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 44cfb9e2a..490c5f617 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -518,7 +518,7 @@ \n \nAtive \"%1$s\" nas configurações se quiser vê-lo. Sim, e vídeos parcialmente assistidos - Os vídeos que foram assistidos antes e depois de terem sidos adicionados à playlist serão removidos. \nTem certeza? Esta ação não pode ser desfeita! + Os vídeos que foram assistidos antes e depois de terem sidos adicionados à playlist serão removidos. \nTem certeza? Remover vídeos assistidos? Remover assistidos Textos originais dos serviços serão visíveis nos itens de transmissão diff --git a/fastlane/metadata/android/cs/changelogs/1008.txt b/fastlane/metadata/android/cs/changelogs/1008.txt new file mode 100644 index 000000000..8be67b02a --- /dev/null +++ b/fastlane/metadata/android/cs/changelogs/1008.txt @@ -0,0 +1,4 @@ +∙ Opraveno obnovení streamů na poslední pozici přehrávání +∙ [YouTube] Přidána podpora pro více formátů URL kanálů +∙ [YouTube] Přidána podpora pro více formátů metainformací videí +∙ Aktualizovány překlady diff --git a/fastlane/metadata/android/de/changelogs/1007.txt b/fastlane/metadata/android/de/changelogs/1007.txt index 43623578f..edeb158e7 100644 --- a/fastlane/metadata/android/de/changelogs/1007.txt +++ b/fastlane/metadata/android/de/changelogs/1007.txt @@ -1 +1,11 @@ -Behoben, dass YouTube keinen Stream abspielte +Dieser Hotfix behebt „Inhalt nicht verfügbar“: YouTube-Videos können nun wieder abgespielt werden! + +Einige in 0.28.1 aufgetretene Fehler behoben: +• Wiedergabelisten-Elemente können nur auf benachbarte Pos. gezogen werden +• Titel/Kommentare flackern zwischen aktuellem und vorherigem Video +• „Hauptplayer im Vollbildmodus starten“ + +Weitere Verbesserungen: +• [YouTube] Livestreams bis zu 4 Stunden zurückspulen +• Livestreams bei Wiedergabe im Hintergrund nicht laden +• Neue UI für „Gesehene entfernen“ diff --git a/fastlane/metadata/android/de/changelogs/1008.txt b/fastlane/metadata/android/de/changelogs/1008.txt new file mode 100644 index 000000000..3adb1ef96 --- /dev/null +++ b/fastlane/metadata/android/de/changelogs/1008.txt @@ -0,0 +1,4 @@ +∙ Fortsetzen von Streams an der letzten Wiedergabeposition korrigiert +∙ [YouTube] Unterstützung für weitere Kanal-URL-Formate +∙ [YouTube] Unterstützung für weitere Video-Metainfo-Formate +∙ Übersetzungen aktualisiert diff --git a/fastlane/metadata/android/fr/changelogs/1000.txt b/fastlane/metadata/android/fr/changelogs/1000.txt index 994b6061d..db858eafd 100644 --- a/fastlane/metadata/android/fr/changelogs/1000.txt +++ b/fastlane/metadata/android/fr/changelogs/1000.txt @@ -1,13 +1,9 @@ Améliorations -• La description de la playlist est désormais cliquable pour afficher plus ou moins de contenu. -• [PeerTube] Gestion automatique des liens d'instance `subscribeto.me` -• Lecture d'un seul élément à la fois depuis l'historique +• Rendre la description de la liste de lecture cliquable pour afficher plus / moins de contenu. +• Ne lancer la lecture que d'un seul élément dans l'écran de l'historique. Corrections -• Amélioration de la visibilité du bouton RSS -• Correction des plantages liés à l'aperçu de la barre de progression -• Correction de l'ajout d'un élément sans vignette à la playlist -• Correction de la fermeture prématurée de la boîte de dialogue de téléchargement -• Correction de la fenêtre contextuelle d'ajout à la file d'attente de la liste des éléments associés -• Amélioration de l'ordre d'affichage dans la boîte de dialogue « Ajouter à la playlist » -• Ajustement de la mise en page des signets de playlist +• Correction des plantages de l'aperçu de la barre de recherche. +• Correction de l'ajout à la playlist d'un élément sans vignette. +• Correction de la fenêtre contextuelle de mise en file d'attente des éléments associés. +• Ajustement de la disposition des éléments des signets de la liste de lecture. diff --git a/fastlane/metadata/android/fr/changelogs/1005.txt b/fastlane/metadata/android/fr/changelogs/1005.txt index 269ba2105..8f4a61f1e 100644 --- a/fastlane/metadata/android/fr/changelogs/1005.txt +++ b/fastlane/metadata/android/fr/changelogs/1005.txt @@ -1,17 +1,12 @@ Nouveautés • Ajout de la compatibilité avec Android Auto • Possibilité de définir des groupes de flux comme onglets de l'écran principal -• [YouTube] Partager comme playlist temporaire -• [SoundCloud] Onglet « J'aime » sur les chaînes Améliorations • Amélioration des suggestions de la barre de recherche • Affichage de la date de téléchargement dans Téléchargements -• Utilisation de la langue par application d'Android 13 Corrections • Correction des couleurs de texte défectueuses en mode sombre • [YouTube] Correction du chargement des playlists de plus de 100 éléments • [YouTube] Correction de l'affichage des vidéos recommandées manquantes -• Correction des plantages dans l'historique -• Correction des horodatages dans les réponses aux commentaires diff --git a/fastlane/metadata/android/fr/changelogs/1008.txt b/fastlane/metadata/android/fr/changelogs/1008.txt new file mode 100644 index 000000000..2580e888c --- /dev/null +++ b/fastlane/metadata/android/fr/changelogs/1008.txt @@ -0,0 +1,4 @@ +∙ Correction de la reprise des flux à la dernière position de lecture. +∙ [YouTube] Ajout de la prise en charge d'autres formats d'URL de chaîne. +∙ [YouTube] Ajout de la prise en charge d'autres formats de métadonnées vidéo. +∙ Mise à jour des traductions diff --git a/fastlane/metadata/android/fr/changelogs/65.txt b/fastlane/metadata/android/fr/changelogs/65.txt index 9d06cac17..b7a9d47e5 100644 --- a/fastlane/metadata/android/fr/changelogs/65.txt +++ b/fastlane/metadata/android/fr/changelogs/65.txt @@ -1,41 +1,2 @@ ### Améliorations - -- Désactivation de l'animation de l'icône du menu hamburger #1486 - -- Annulation de la suppression des téléchargements #1472 - -- Option de téléchargement dans le menu de partage #1498 - -- Ajout de l'option de partage au menu contextuel (appui long) #1454 - -- Réduction du lecteur principal à la fermeture #1354 - -- Mise à jour de la version de la bibliothèque et correction de la sauvegarde de la base de données #1510 - -- Mise à jour ExoPlayer 2.8.2 #1392 - -- Refonte de la boîte de dialogue de contrôle de la vitesse de lecture pour permettre des incréments différents et ainsi accélérer les changements de vitesse. - -- Ajout d'une option pour avancer rapidement pendant les silences dans le contrôle de la vitesse de lecture. Cette fonction devrait être utile pour les livres audio et certains genres musicaux, et peut offrir une expérience d'écoute parfaitement fluide (mais peut aussi perturber la lecture d'un morceau comportant de nombreux silences =\\). - -- Refonte de la résolution de la source multimédia pour permettre la transmission des métadonnées directement dans le lecteur, au lieu d'une saisie manuelle. Nous disposons désormais d'une source unique de métadonnées, directement disponible au démarrage de la lecture. - Correction du problème de mise à jour des métadonnées des listes de lecture distantes lors de la disponibilité de nouvelles métadonnées à l'ouverture d'un fragment de liste de lecture. - -- Diverses corrections d'interface utilisateur : #1383, les commandes de notification du lecteur en arrière-plan sont désormais toujours blanches, fermeture plus facile du lecteur contextuel par un mouvement brusque. - -- Utilisation d'un nouvel extracteur avec une architecture remaniée pour le multiservice. - -### Corrections - -- Correction du problème #1440 : affichage incorrect des informations vidéo. #1491 - -- Correction de l'historique de visionnage. #1497 - -- #1495 : mise à jour des métadonnées (miniature, titre et nombre de vidéos) dès que l'utilisateur accède à la liste de lecture. - -- #1475 : enregistrement d'une vue dans la base de données lorsque l'utilisateur lance une vidéo sur un lecteur externe dans le fragment de détails. - -- Correction du délai d'expiration de l'écran en mode contextuel. #1463 (Correction du problème #640) - -- Correction du lecteur vidéo principal. #1509 - -- [#1412] Correction du mode répétition provoquant une exception NullPointerException (NPE) du lecteur lors de la réception d'une nouvelle intention alors que l'activité du lecteur est en arrière-plan. - Correction d'un problème où la réduction du lecteur dans une fenêtre contextuelle ne détruisait pas le lecteur lorsque l'autorisation d'afficher la fenêtre contextuelle n'était pas accordée. +- Ajout d'une option pour avancer rapidement pendant les silences dans le contrôle de la vitesse de lecture. Cette fonction devrait être utile pour les livres audio et certains genres musicaux, et peut offrir une expérience d'écoute parfaitement fluide (mais peut aussi perturber la lecture d'un morceau comportant de nombreux silences =\\) diff --git a/fastlane/metadata/android/fr/changelogs/66.txt b/fastlane/metadata/android/fr/changelogs/66.txt index b6092f44f..c62f13dce 100644 --- a/fastlane/metadata/android/fr/changelogs/66.txt +++ b/fastlane/metadata/android/fr/changelogs/66.txt @@ -1,50 +1,8 @@ # Journal des modifications de la v0.13.7 -### Corrigé -- Correction des problèmes de filtre de tri de la v0.13.6 - -# Journal des modifications de la v0.13.6 - ### Améliorations - -- Désactivation de l'animation de l'icône du menu hamburger #1486 - -- Annulation de la suppression des téléchargements #1472 - -- Option de téléchargement dans le menu de partage #1498 - -- Ajout de l'option de partage au menu contextuel (appui long) #1454 - -- Réduction du lecteur principal à la fermeture #1354 - - Mise à jour de la version de la bibliothèque et correction de la sauvegarde de la base de données #1510 - -- Mise à jour ExoPlayer 2.8.2 #1392 - - Refonte de la boîte de dialogue de contrôle de la vitesse de lecture pour permettre des incréments différents et ainsi accélérer les changements de vitesse. -- Ajout d'une option pour avancer rapidement pendant les silences dans le contrôle de la vitesse de lecture. Ceci devrait être utile pour les livres audio et certains genres musicaux, et peut offrir une expérience d'écoute parfaitement fluide (mais peut aussi perturber une chanson avec de nombreux silences =\\). - Résolution de la source multimédia remaniée pour permettre la transmission interne des métadonnées au lecteur, au lieu d'une saisie manuelle. Les métadonnées proviennent désormais d'une source unique et sont directement disponibles au démarrage de la lecture. - -- Correction du problème de mise à jour des métadonnées des listes de lecture distantes lors de l'ouverture d'un fragment de liste de lecture, même lorsque de nouvelles métadonnées sont disponibles. - -- Diverses corrections d'interface : #1383, les commandes de notification du lecteur en arrière-plan sont désormais toujours blanches ; il est plus facile de fermer le lecteur contextuel en le faisant glisser. - -- Utilisation d'un nouvel extracteur avec une architecture remaniée pour le multiservice. - ### Corrections - -- Correction du problème #1440 : affichage incorrect des informations vidéo ; #1491 - -- Correction de l'historique de visionnage ; #1497 - - #1495 : mise à jour des métadonnées (miniature, titre et nombre de vidéos) dès que l'utilisateur accède à la liste de lecture. - -- #1475 : enregistrement d'une vue dans la base de données lorsque l'utilisateur lance une vidéo sur un lecteur externe dans le fragment de détails. - -- Correction du délai d'expiration de l'écran en mode fenêtre contextuelle. #1463 (Correction de #640) - -- Correction du lecteur vidéo principal #1509 - -- [#1412] Correction du mode de répétition provoquant une exception de pointeur nul (NPE) du lecteur lors de la réception d'une nouvelle intention alors que l'activité du lecteur est en arrière-plan. - -- Correction du problème suivant : la réduction du lecteur dans une fenêtre contextuelle ne le détruisait pas lorsque l'autorisation d'ouvrir une fenêtre contextuelle n'était pas accordée. diff --git a/fastlane/metadata/android/fr/changelogs/68.txt b/fastlane/metadata/android/fr/changelogs/68.txt index 3c9c4446f..30f2e1e10 100644 --- a/fastlane/metadata/android/fr/changelogs/68.txt +++ b/fastlane/metadata/android/fr/changelogs/68.txt @@ -1,11 +1,5 @@ # Modifications de la v0.14.1 -### Corrigé -- Correction du problème de décryptage de l'URL vidéo (#1659) -- Correction du problème d'extraction du lien de description (#1657) - -# Modifications de la v0.14.0 - ### Nouveau - Nouveau design du tiroir (#1461) - Nouvelle page d'accueil personnalisable (#1461) @@ -15,30 +9,6 @@ - Nouvelle méthode pour fermer le lecteur pop-up (#1597) ### Corrigé -- Correction d'une erreur lorsque le nombre d'abonnements n'est pas disponible. Résout le problème n° 1649. - - Afficher « Nombre d'abonnés indisponible » dans ces cas - -- Correction d'une exception NPE lorsqu'une playlist YouTube est vide - -- Correction rapide pour les bornes interactives sur SoundCloud - -- Refactorisation et correction du bug n° 1623 - -- Correction du résultat de recherche cyclique n° 1562 - -- Correction de la barre de progression (position statique) - - Correction du blocage incorrect des vidéos YouTube Premium - -- Correction du chargement intempestif des vidéos (dû à l'analyse DASH) - -- Correction des liens dans la description des vidéos - - Afficher un avertissement lors d'une tentative de téléchargement sur carte SD externe - -- Correction d'une exception déclenchant un rapport en cas d'absence d'affichage - -- Correction de l'affichage des miniatures dans le lecteur en arrière-plan sous Android 8.1 [voir ici](https://github.com/TeamNewPipe/NewPipe/issues/943) - -- Correction de l'enregistrement du récepteur de diffusion. Résout le problème n° 1641. diff --git a/fastlane/metadata/android/fr/changelogs/69.txt b/fastlane/metadata/android/fr/changelogs/69.txt index c96b390d9..d27dfb97a 100644 --- a/fastlane/metadata/android/fr/changelogs/69.txt +++ b/fastlane/metadata/android/fr/changelogs/69.txt @@ -3,17 +3,8 @@ - Interface utilisateur pour tablettes et disposition de la liste en grille #1617 ### Améliorations -- Stockage/recharge du dernier rapport d'aspect utilisé #1748 - Activation de la disposition linéaire dans l'activité Téléchargements avec les noms complets des vidéos #1771 -- Suppression et partage des abonnements directement à partir de l'onglet abonnements #1516 - La mise en file d'attente déclenche désormais la lecture de la vidéo si la file d'attente de lecture est déjà terminée #1783 -- Paramètres distincts pour les gestes de volume et de luminosité #1644 -- Ajout de la prise en charge de la localisation #1792 - -### Corrections -- Analyse de l'heure pour le format . , afin que NewPipe puisse être utilisé en Finlande. -- Compte d'abonnement -- Ajout permission de service de premier plan pour les appareils API 28+ #1830 ### Bugs connus - État de lecture ne peut être enregistré sur Android P diff --git a/fastlane/metadata/android/fr/changelogs/70.txt b/fastlane/metadata/android/fr/changelogs/70.txt index 185f98f69..e3b909b4c 100644 --- a/fastlane/metadata/android/fr/changelogs/70.txt +++ b/fastlane/metadata/android/fr/changelogs/70.txt @@ -1,25 +1,7 @@ -ATTENTION : Cette version est probablement un festival de bugs, tout comme la dernière. Cependant, en raison de la fermeture complète depuis la 17. une version cassée est mieux que pas de version. N'est-ce pas ? ¯\_(ツ)_/¯ - ### Améliorations * Les fichiers téléchargés peuvent maintenant être ouverts en un seul clic. -* Suppression du support pour Android 4.1 - 4.3 #1884 -* Suppression de l'ancien lecteur #1884 -* Suppression des flux de la file d'attente de lecture actuelle en les faisant glisser vers la droite #1915 -* Suppression du flux en file d'attente automatique lorsqu'un nouveau flux est mis en file d'attente manuellement #1878 * Post-traitement pour les téléchargements et implémentation des fonctionnalités manquantes #1759 par @kapodamy - * Infrastructure de post-traitement - * Infrastructure de gestion des erreurs (pour le téléchargeur) - * File d'attente au lieu de téléchargements multiples - * Déplacer les téléchargements sérialisés en attente (fichiers `.giga`) vers les données de l'application. - * Implémentation de la répétition maximale des téléchargements - * Mise en pause des téléchargements multi-threads - * Arrêter les téléchargements lors du passage au réseau mobile (ne fonctionne jamais, voir 2ème point) - * Sauvegarder le nombre de threads pour les prochains téléchargements - * Beaucoup d'incohérences corrigées +* Déplacer les téléchargements sérialisés en attente (fichiers `.giga`) vers les données de l'application. ### Corrigé * Correction d'un crash avec la résolution par défaut réglée sur la meilleure et la résolution limitée des données mobiles #1835 -* Correction du crash du lecteur de pop-up #1874 -* NPE lors de l'ouverture du lecteur de fond #1901 -* Correction de l'insertion de nouveaux flux lorsque la mise en file d'attente automatique est activée #1878 -* Correction du problème de décryptage de Shuttown diff --git a/fastlane/metadata/android/fr/changelogs/740.txt b/fastlane/metadata/android/fr/changelogs/740.txt index 167608b66..83f5cb7db 100644 --- a/fastlane/metadata/android/fr/changelogs/740.txt +++ b/fastlane/metadata/android/fr/changelogs/740.txt @@ -1,23 +1,9 @@

Améliorations

-
  • Rendre les liens dans les commentaires cliquables, augmenter la taille du texte
  • Rechercher en cliquant sur les liens d'horodatage dans les commentaires
  • -
  • Afficher l'onglet préféré en fonction de l'état récemment sélectionné
  • -
  • Ajouter la playlist à la file d'attente lors d'un clic long sur 'Arrière-plan' dans la fenêtre de la playlist
  • -
  • Rechercher le texte partagé lorsqu'il ne s'agit pas d'une URL
  • -
  • Ajouter "partager à l'heure actuelle" bouton au lecteur vidéo principal lecteur vidéo principal
  • -
  • Ajouter un bouton de fermeture du lecteur principal lorsque la file d'attente vidéo est terminée
  • -
  • Ajouter "jouer directement en arrière-plan" au menu longpress pour les éléments de la liste vidéo
  • -
  • Améliorer les traductions en anglais des commandes Play/Enqueue
  • -
  • Petites améliorations des performances
  • -
  • Supprimer les fichiers inutilisés
  • -
  • Mise à jour ExoPlayer à 2.9.6
  • -
  • Ajouter le support pour les liens Invidious
  • +

Corrections

-
    -
  • Défilement avec les commentaires et les flux associés désactivés
  • -
  • CheckForNewAppVersionTask qui est exécuté alors qu'il ne devrait pas l'être'
  • Importation des abonnements YouTube : ignorer ceux dont l’URL est invalide et conserver ceux dont le titre est vide
  • URL YouTube invalide : le nom de la balise signature n'est pas toujours "signature", ce qui empêche le chargement des flux.
diff --git a/fastlane/metadata/android/fr/changelogs/750.txt b/fastlane/metadata/android/fr/changelogs/750.txt index 7273ae1f0..57da00cbc 100644 --- a/fastlane/metadata/android/fr/changelogs/750.txt +++ b/fastlane/metadata/android/fr/changelogs/750.txt @@ -1,36 +1,10 @@ Nouveautés - -Reprise de la lecture #2288 - -• Reprise des flux là où vous les avez interrompus -Améliorations du téléchargeur #2149 - • Utilisation de Storage Access Framework pour stocker les téléchargements sur des cartes SD externes - -• Nouveau multiplexeur mp4 - • Possibilité de modifier le répertoire de téléchargement avant de lancer un téléchargement -• Respect des réseaux limités - Améliorations - • Suppression des chaînes gema #2295 - • Gestion des changements de rotation (automatique) pendant le cycle de vie de l'activité #2444 -• Harmonisation des menus accessibles par appui long #2368 - Corrections - -• Correction de l'affichage du nom de la piste de sous-titres sélectionnée #2394 - -• Correction du plantage en cas d'échec de la vérification des mises à jour de l'application (version GitHub) #2423 - • Correction du blocage des téléchargements à 99,9 % #2440 - -• Mise à jour des métadonnées de la file d'attente de lecture #2453 - -• [SoundCloud] Correction du plantage lors du chargement des playlists TeamNewPipe/NewPipeExtractor#170 - -• [YouTube] Correction de l'impossibilité d'afficher la durée paresd TeamNewPipe/NewPipeExtractor#177 diff --git a/fastlane/metadata/android/fr/changelogs/760.txt b/fastlane/metadata/android/fr/changelogs/760.txt index e0a225fce..4e62425d2 100644 --- a/fastlane/metadata/android/fr/changelogs/760.txt +++ b/fastlane/metadata/android/fr/changelogs/760.txt @@ -1,43 +1,9 @@ Changements dans la version 0.17.1 -Nouveauté -• Localisation en thaïlandais - - Améliorations • Ajout de l'action "Commencer à jouer ici" dans les menus qui s'appuient longuement pour les playlists #2518 • Ajout d'un commutateur pour le sélecteur de fichiers SAF / hérité #2521 Corrections -• Correction des boutons qui disparaissent dans la vue des téléchargements lors du changement d'applications #2487 -• Correction de la position de lecture qui est enregistrée même si l'historique de visionnage est désactivé -• Correction des performances réduites causées par la position de lecture dans les vues de liste #2517 • [Extractor] Correction de ReCaptchaActivity #2527, TeamNewPipe/NewPipeExtractor#186 • [Extractor] [YouTube] Correction de l'erreur de recherche occasionnelle lorsque les playlists sont dans les résultats TeamNewPipe/NewPipeExtractor#185 - - - -Changements dans la version 0.17.0 - -Nouveautés -Reprise de lecture #2288 -• Reprise des flux là où vous vous étiez arrêté la dernière fois -Améliorations du téléchargeur #2149 -• Utilisation du Storage Access Framework pour stocker les téléchargements sur des cartes SD externes -• Nouveau multiplexeur mp4 -• Possibilité de changer le répertoire de téléchargement avant de commencer un téléchargement -• Respect des réseaux tarifés - - -Améliorations -• Suppression des chaînes gema #2295 -• Gestion des changements de (auto)rotation pendant le cycle de vie de l'activité #2444 -• Uniformisation des menus qui s'appuient longuement #2368 - -Corrections -• Correction du nom de la piste de sous-titres sélectionnée qui ne s'affiche pas #2394 -• Ne plante pas lorsque la vérification de la mise à jour de l'application échoue (version GitHub) #2423 -• Correction des téléchargements bloqués à 99,9 % #2440 -• Mise à jour des métadonnées de la file de lecture #2453 -• [SoundCloud] Correction du plantage lors du chargement des playlists TeamNewPipe/NewPipeExtractor#170 -• [YouTube] Correction de la durée qui ne peut pas être analysée TeamNewPipe/NewPipeExtractor#177 diff --git a/fastlane/metadata/android/fr/changelogs/800.txt b/fastlane/metadata/android/fr/changelogs/800.txt index 46fe1504e..5f41e6026 100644 --- a/fastlane/metadata/android/fr/changelogs/800.txt +++ b/fastlane/metadata/android/fr/changelogs/800.txt @@ -1,27 +1,6 @@ -Nouveau -- Support de PeerTube sans P2P (#2201) [Beta] : - ◦ Regarder et télécharger des vidéos depuis des instances PeerTube - ◦ Ajouter des instances dans les paramètres pour accéder à l'ensemble du monde PeerTube - ◦ Il peut y avoir des problèmes avec les handshakes SSL sur Android 4.4 et 7.1 lors de l'accès à certaines instances, ce qui entraîne une erreur de réseau. - -- Téléchargeur (#2679) : - ◦ Calculer l'heure d'arrivée du téléchargement - ◦ Télécharger les opus (fichiers webm) en ogg - ◦ Récupération des liens de téléchargement expirés pour reprendre les téléchargements après une longue pause - Amélioré - Le KioskFragment est informé des changements dans le pays de contenu préféré et améliore les performances de tous les onglets principaux #2742 -- Utilisation des nouvelles implémentations Localization et Downloader de l'extracteur #2713 -- Rendre la chaîne « Default kiosk » traduisible -- Barre de navigation noire pour le thème noir #2569 Correction - Correction d'un bogue qui ne permettait pas de déplacer le lecteur popup si un autre doigt était placé pendant le déplacement du lecteur popup #2772 - Autorise les playlists sans uploader et corrige les crashs liés à ce problème #2724, TeamNewPipe/NewPipeExtractor#219 -- Activation de TLS1.1/1.2 sur les appareils Android 4.4 (API 19/KitKat) pour corriger le handshake TLS avec MediaCCC et certaines instances PeerTube #2792 -- SoundCloud] Correction de l'extraction de l'identifiant client TeamNewPipe/NewPipeExtractor#217 -- [SoundCloud] Correction de l'extraction du flux audio - -Développement -- Mise à jour d'ExoPlayer vers la version 2.10.8 #2791, #2816 -- Mise à jour de Gradle vers 3.5.1 et ajout du support Kotlin #2714 diff --git a/fastlane/metadata/android/fr/changelogs/810.txt b/fastlane/metadata/android/fr/changelogs/810.txt index 573ea9889..8b8b9d518 100644 --- a/fastlane/metadata/android/fr/changelogs/810.txt +++ b/fastlane/metadata/android/fr/changelogs/810.txt @@ -4,16 +4,6 @@ Nouveautée : Améliorations : • Ajout de la playlist locale à la file d'attente lors d'une pression longue sur le bouton arrière-plan / flottant • Possibilité de faire défiler les onglets de la page principale et les masquent lorsqu'il n'y a qu'un seul onglet -• Limite le nombre de mises à jour de la miniature des notifications avec le lecteur en arrière-plan -• Ajout d'une miniature fictive pour les playlists locales vides -• Utilisation de l'extension de fichier *.opus au lieu de *.webm et affiche « opus » pour le nom du format au lieu de « WebM Opus » dans la liste déroulante de téléchargement. -• Ajout d'un bouton pour supprimer les fichiers téléchargés ou l'historique de téléchargements dans les « Téléchargements » -• [YouTube] Ajout de la prise en charge des liens de chaînes /c/shortened_url Corrections : • Correction de plusieurs problèmes lors du partage d'une vidéo sur NewPipe et du téléchargement direct de ses flux -• Correction de l'accès du lecteur hors de son fil de création -• Correction de la pagination des résultats de recherche -• [YouTube] Correction de null résultant en une erreur NPE -• [YouTube] Correction de l'affichage des commentaires lors de l'ouverture d'une url invidio.us -• [SoundCloud] client_id mis à jour diff --git a/fastlane/metadata/android/fr/changelogs/840.txt b/fastlane/metadata/android/fr/changelogs/840.txt index 240b77824..a09ce98c1 100644 --- a/fastlane/metadata/android/fr/changelogs/840.txt +++ b/fastlane/metadata/android/fr/changelogs/840.txt @@ -1,22 +1,9 @@ Nouveau • Ajout d'un sélecteur de langue pour changer la langue de l'application -• Ajout du bouton Envoyer vers Kodi au menu déroulant du lecteur • Ajout de la possibilité de copier les commentaires en appuyant longuement Amélioré -• Corriger l'activité ReCaptcha et enregistrer correctement les cookies obtenus • Suppression du menu à points au profit du tiroir et du bouton Masquer l'historique lorsque l'historique de visionnage n'est pas activé dans les paramètres -• Demander correctement l'autorisation d'affichage sur d'autres applications dans les paramètres sur Android 6 et versions ultérieures -• Renommer la playlist locale en cliquant longuement dans BookmarkFragment -• Diverses améliorations de PeerTube -• Amélioration de plusieurs chaînes sources en anglais Corrigé • Correction du redémarrage du lecteur bien qu'il soit en pause lorsque l'option « Réduire au changement d'application » est activée et que NewPipe est réduit -• Correction de la valeur de luminosité initiale pour le geste -• Correction des téléchargements de sous-titres .srt ne contenant pas tous les sauts de ligne -• Correction du téléchargement sur la carte SD qui échoue car certains appareils Android 5 ne sont pas conformes CTF -• Correction du téléchargement sur Android KitKat -• Correction du fichier vidéo .mp4 corrompu reconnu comme fichier audio -• Correction de plusieurs problèmes de localisation, y compris des codes de langue chinois erronés -• [YouTube] Les horodatages dans la description sont à nouveau cliquables diff --git a/fastlane/metadata/android/fr/changelogs/930.txt b/fastlane/metadata/android/fr/changelogs/930.txt index 4bf050a24..d6151d5ea 100644 --- a/fastlane/metadata/android/fr/changelogs/930.txt +++ b/fastlane/metadata/android/fr/changelogs/930.txt @@ -5,15 +5,8 @@ Nouveau Amélioré • Ajout de la possibilité de supprimer toutes les vidéos regardées d'une playlist locale • Afficher un message lorsque le contenu n'est pas encore pris en charge au lieu de planter -• Redimensionnement amélioré du lecteur contextuel avec des gestes de pincement -• Mettre les flux en file d'attente en appuyant longuement sur les boutons d'arrière-plan et contextuels dans la chaîne -• Gestion améliorée de la taille du titre de l'en-tête du tiroir Corrigé • Correction du paramètre de contenu restreint par âge qui ne fonctionne pas • Correction de certains types de reCAPTCHA • Correction du crash lors de l'ouverture des signets alors que la playlist est « nulle » -• Correction de la détection des exceptions liées au réseau -• Correction de la visibilité du bouton de tri de groupe dans le fragment d'abonnements - -et plus diff --git a/fastlane/metadata/android/fr/changelogs/992.txt b/fastlane/metadata/android/fr/changelogs/992.txt index dc1fad35b..4aa8a0e67 100644 --- a/fastlane/metadata/android/fr/changelogs/992.txt +++ b/fastlane/metadata/android/fr/changelogs/992.txt @@ -8,10 +8,8 @@ Nouveau Amélioré • Bouton de fermeture du mini-lecteur plus grand • Réduction d'échelle des vignettes plus fluide -• Cible Android 13 (API 33) • La recherche ne met plus le lecteur en pause Corrigé • Correction de la superposition sur DeX/souris • Autoriser le lecteur d'arrière-plan sans flux audio séparés -• Divers correctifs YouTube et plus encore… diff --git a/fastlane/metadata/android/fr/changelogs/993.txt b/fastlane/metadata/android/fr/changelogs/993.txt index 9865a19ac..875b09c94 100644 --- a/fastlane/metadata/android/fr/changelogs/993.txt +++ b/fastlane/metadata/android/fr/changelogs/993.txt @@ -9,4 +9,3 @@ Amélioré Corrigé • Correction de l'ouverture des URL du navigateur, des téléchargements et des lecteurs externes sur Android 11+ -• Correction de l'interaction avec le plein écran nécessitant deux appuis sur MIUI diff --git a/fastlane/metadata/android/fr/changelogs/994.txt b/fastlane/metadata/android/fr/changelogs/994.txt index 35a77aa91..20d64ac94 100644 --- a/fastlane/metadata/android/fr/changelogs/994.txt +++ b/fastlane/metadata/android/fr/changelogs/994.txt @@ -8,8 +8,5 @@ Amélioré Corrigé • [YouTube] Erreurs HTTP 403 pour les flux -• Lecteur noir lors du passage au lecteur principal depuis la vue playlist • Fuite de mémoire du service de lecture • [PeerTube] Les avatars du téléchargeur et du sous-canal ont été échangés - -et plus diff --git a/fastlane/metadata/android/fr/changelogs/995.txt b/fastlane/metadata/android/fr/changelogs/995.txt index b91f83875..da96067ef 100644 --- a/fastlane/metadata/android/fr/changelogs/995.txt +++ b/fastlane/metadata/android/fr/changelogs/995.txt @@ -4,13 +4,10 @@ Nouveau • Obtenir les URL de toutes les images Amélioré -• Accessibilité des interfaces du lecteur • Meilleure sélection audio pour les téléchargements de vidéos uniquement • Option permettant d'inclure les noms de playlist et de vidéo dans le contenu de playlist partagé Corrigé -• [YouTube] Correction de l'obtention du nombre de likes +• [YouTube] Correction de l'obtention du nombre de like • Correction des fenêtres contextuelles et des plantages du lecteur • Sélection de mauvaises langues dans le sélecteur de langue -• Le focus audio du lecteur ne respectait pas la fonction muet -• L'ajout d'éléments de playlist ne fonctionnait parfois pas diff --git a/fastlane/metadata/android/fr/changelogs/997.txt b/fastlane/metadata/android/fr/changelogs/997.txt index b1a550577..4d9a7c29a 100644 --- a/fastlane/metadata/android/fr/changelogs/997.txt +++ b/fastlane/metadata/android/fr/changelogs/997.txt @@ -2,16 +2,11 @@ Nouveau • Ajouter des réponses aux commentaires • Autoriser la réorganisation des playlists • Afficher la description et la durée de la playlist -• Autoriser la réinitialisation des paramètres Amélioré -• [Android 13+] Restaurer les actions de notification personnalisées • Demander le consentement pour la vérification des mises à jour -• Autoriser la lecture/pause des notifications pendant la mise en mémoire tampon -• Réorganiser certains paramètres +• Autoriser la lecture/pause de notifications pendant la mise en mémoire tampon Corrigé • [YouTube] Correction des commentaires qui ne se chargent pas, ainsi que d'autres correctifs et améliorations • Résoudre la vulnérabilité dans l'importation des paramètres et passer à JSON -• Divers correctifs de téléchargement -• Couper le texte de recherche diff --git a/fastlane/metadata/android/fr/changelogs/999.txt b/fastlane/metadata/android/fr/changelogs/999.txt index a2271fde6..f7e1fd2f0 100644 --- a/fastlane/metadata/android/fr/changelogs/999.txt +++ b/fastlane/metadata/android/fr/changelogs/999.txt @@ -1,5 +1,3 @@ -Ce correctif corrige les erreurs HTTP 403 au milieu des vidéos YouTube. - Nouveau • [SoundCloud] Ajout de la prise en charge des URL on.soundcloud.com diff --git a/fastlane/metadata/android/pt-BR/changelogs/1000.txt b/fastlane/metadata/android/pt-BR/changelogs/1000.txt index 7f89cd9b2..c158f5222 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/1000.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/1000.txt @@ -1,13 +1,13 @@ -Melhorado -• Torne a descrição da lista de reprodução clicável para mostrar mais / menos conteudo -• [PeerTube] Gerênciar links de instâncias `subscribeto.me` automaticamente -• Começar a reprodução apenas de um item na tela de histórico +Melhorias +• Tornar a descrição da lista de reprodução clicável para mostrar mais/menos conteúdo +• [PeerTube] Lidar automaticamente com links de instâncias do `subscribeto.me` +• Iniciar a reprodução de apenas um item na tela de histórico Corrigido -• Corrigir visibilidade do botão RSS +• Corrigir a visibilidade do botão RSS • Corrigir falhas na pré-visualização da barra de busca -• Corrigir erro ao adicionar item sem miniatura à playlist -• Corrigir erro ao sair da caixa de diálogo de descarregar antes de ela aparecer -• Corrigir itens relacionados ao pop-up de colocar na fila -• Corrigir a ordem no diálogo de adicionar à lista de reprodução -• Ajustar o layout do item de marcador de lista de reprodução +• Corrigir a inclusão de um item sem miniatura na lista de reprodução +• Corrigir o fechamento da caixa de diálogo de download antes de ela aparecer +• Corrigir o pop-up de enfileiramento da lista de itens relacionados +• Corrigir a ordem na caixa de diálogo de adicionar à lista de reprodução +• Ajustar o layout do item de marcador da lista de reprodução diff --git a/fastlane/metadata/android/sk/changelogs/1008.txt b/fastlane/metadata/android/sk/changelogs/1008.txt new file mode 100644 index 000000000..fd5ebc93c --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/1008.txt @@ -0,0 +1,4 @@ +Opravené obnovenie streamov na poslednej pozícii prehrávania. +∙ [YouTube] Pridaná podpora pre viac formátov URL kanálov. +∙ [YouTube] Pridaná podpora pre viac formátov metainformácií videí. +∙ Aktualizované preklady diff --git a/fastlane/metadata/android/tr/changelogs/995.txt b/fastlane/metadata/android/tr/changelogs/995.txt new file mode 100644 index 000000000..edfd248fd --- /dev/null +++ b/fastlane/metadata/android/tr/changelogs/995.txt @@ -0,0 +1,16 @@ +Yeni +• Kanal sekmeleri desteği +• Resim kalite seçme özelliği +• Tüm resimlerin URL'lerini alma özelliği + +İyileştirmeler +• Oynatıcı arayüzlerinin erişilebilirliği +• Yalnızca video indirmeleri için daha iyi ses seçimi +• Paylaşılan oynatma listesi içeriğine oynatma listesi ve video adlarını ekleme seçeneği + +Düzeltilenler +• [YouTube] Beğeni sayısını alma sorunu düzeltildi +• Oynatıcının yanıt vermemesi ve çökmesi sorunu düzeltildi +• Dil seçicide yanlış dil seçimi sorunu düzeltildi +• Oynatıcı ses odaklı modda, sessize alma özelliğini dikkate almıyordu +• Oynatma listesi öğesi ekleme özelliği bazen çalışmıyordu diff --git a/fastlane/metadata/android/zh-Hans/changelogs/1007.txt b/fastlane/metadata/android/zh-Hans/changelogs/1007.txt index 8a5424c9e..285ca3827 100644 --- a/fastlane/metadata/android/zh-Hans/changelogs/1007.txt +++ b/fastlane/metadata/android/zh-Hans/changelogs/1007.txt @@ -1 +1,11 @@ -修复YouTube无法播放任何视频 +这个热修复版本修复了“内容不可用”错误:又能播放 YouTube 视频了! + +还修复了几个 0.28.1 版本引入的故障: +• 播放列表项只拖动到相邻位置 +• 标题、评论在当前和上一个视频之间闪烁 +• “全屏模式启动主播放器”选项不工作 + +其他改进: +• [YouTube] 再次允许将直播倒退最多 4 小时 +• 后台播放时不加载直播视频 +• “删除已观看”的新用户界面 diff --git a/fastlane/metadata/android/zh-Hans/changelogs/1008.txt b/fastlane/metadata/android/zh-Hans/changelogs/1008.txt new file mode 100644 index 000000000..7ba4bfab4 --- /dev/null +++ b/fastlane/metadata/android/zh-Hans/changelogs/1008.txt @@ -0,0 +1,4 @@ +∙ 修复了在上次播放位置继续播放音视频流的问题 +∙ [YouTube] 支持更多频道 URL 格式 +∙ [YouTube] 支持更多视频元信息格式 +∙ 更新翻译 From 3815f5f593d0c0d66389166858b27bba276ea953 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Thu, 12 Feb 2026 09:16:41 +0100 Subject: [PATCH 29/56] Translated using Weblate (Bengali (India)) Currently translated at 39.2% (300 of 764 strings) --- app/src/main/res/values-bn-rIN/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-bn-rIN/strings.xml b/app/src/main/res/values-bn-rIN/strings.xml index bf226e28e..17e317dfe 100644 --- a/app/src/main/res/values-bn-rIN/strings.xml +++ b/app/src/main/res/values-bn-rIN/strings.xml @@ -309,6 +309,6 @@ কিছু না হ্যাঁ না - সার্চ - খুঁজুন + সার্চ %1$s + খুঁজুন %1$s (%2$s) From 70cdaf5550d02f6c0b60bf31f08956a0afdebdbe Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Fri, 13 Feb 2026 13:33:27 +0200 Subject: [PATCH 30/56] Partially revert: ErrorActivity: Kotlin-fy buildMarkdown method Partially reverts c3dbed54e50430b585e9d7b88cf22c9f3a6cc54c Fix the bug where collapse container for several crashlogs is created when only one crash log present --- .../org/schabi/newpipe/error/ErrorActivity.kt | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt index a8555abae..5dd0755c5 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.kt @@ -228,24 +228,26 @@ class ErrorActivity : AppCompatActivity() { // Collapse all logs to a single paragraph when there are more than one // to keep the GitHub issue clean. - if (errorInfo.stackTraces.isNotEmpty()) { + if (errorInfo.stackTraces.size > 1) { append("
Exceptions (") append(errorInfo.stackTraces.size) append(")

\n") + } - // add the logs - errorInfo.stackTraces.forEachIndexed { index, stacktrace -> - append("

Crash log ") - if (errorInfo.stackTraces.isNotEmpty()) { - append(index + 1) - } - append("") - append("

\n") - append("\n```\n${stacktrace}\n```\n") - append("

\n") + // add the logs + errorInfo.stackTraces.forEachIndexed { index, stacktrace -> + append("
Crash log ") + if (errorInfo.stackTraces.size > 1) { + append(index + 1) } + append("") + append("

\n") + append("\n```\n${stacktrace}\n```\n") + append("

\n") + } - // make sure to close everything + // make sure to close everything + if (errorInfo.stackTraces.size > 1) { append("

\n") } From 95367dd338efa7f9bfc7707aa648c54997d5f72e Mon Sep 17 00:00:00 2001 From: pierreeurope Date: Mon, 16 Feb 2026 12:46:30 +0100 Subject: [PATCH 31/56] Fix subtitle post-processing error losing original exception Previously, TtmlConverter.process() caught all exceptions during TTML to SRT conversion and returned opaque error codes (1 for IOException, 8 for other exceptions). These error codes were then wrapped by Postprocessing.run() into a generic RuntimeException with the message 'post-processing algorithm returned N', losing the original exception and its stack trace. This made it impossible for users and developers to diagnose the root cause of subtitle download failures, as reported in #13206. Now, IOExceptions are re-thrown directly, and other exceptions are wrapped in an IOException with the original exception as the cause. This allows DownloadMission.doPostprocessing() to properly catch and report the actual error, including the full stack trace in the crash report. Fixes #13206 Signed-off-by: pierreeurope --- .../us/shandian/giga/postprocessing/TtmlConverter.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/us/shandian/giga/postprocessing/TtmlConverter.java b/app/src/main/java/us/shandian/giga/postprocessing/TtmlConverter.java index 8ed0dfae5..d723bfb45 100644 --- a/app/src/main/java/us/shandian/giga/postprocessing/TtmlConverter.java +++ b/app/src/main/java/us/shandian/giga/postprocessing/TtmlConverter.java @@ -29,9 +29,12 @@ class TtmlConverter extends Postprocessing { try { writer.build(sources[0]); + } catch (IOException err) { + Log.e(TAG, "subtitle conversion failed due to I/O error", err); + throw err; } catch (Exception err) { - Log.e(TAG, "subtitle parse failed", err); - return err instanceof IOException ? 1 : 8; + Log.e(TAG, "subtitle conversion failed", err); + throw new IOException("TTML to SRT conversion failed", err); } return OK_RESULT; From 7e7ad1e41063fbbc5cf220358e50aaba84b5a8dc Mon Sep 17 00:00:00 2001 From: vt Date: Fri, 13 Feb 2026 08:21:33 +0530 Subject: [PATCH 32/56] fix layout of comment replies header to work when avatar image is gone (disabled in content -> image settings) --- .../res/layout/comment_replies_header.xml | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/app/src/main/res/layout/comment_replies_header.xml b/app/src/main/res/layout/comment_replies_header.xml index ed5ba1a10..f99b101f7 100644 --- a/app/src/main/res/layout/comment_replies_header.xml +++ b/app/src/main/res/layout/comment_replies_header.xml @@ -24,6 +24,8 @@ android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" + android:layout_marginTop="16dp" + app:layout_goneMarginStart="16dp" android:ellipsize="end" android:lines="1" android:textAppearance="?android:attr/textAppearanceLarge" @@ -31,22 +33,21 @@ app:layout_constraintBottom_toTopOf="@+id/uploadDate" app:layout_constraintEnd_toStartOf="@+id/thumbsUpImage" app:layout_constraintStart_toEndOf="@+id/authorAvatar" - app:layout_constraintTop_toTopOf="@+id/authorAvatar" + app:layout_constraintTop_toTopOf="parent" tools:text="@tools:sample/lorem/random" /> @@ -57,9 +58,9 @@ android:layout_marginEnd="@dimen/video_item_detail_like_margin" android:contentDescription="@string/detail_likes_img_view_description" android:src="@drawable/ic_thumb_up" - app:layout_constraintBottom_toBottomOf="@+id/authorAvatar" + app:layout_constraintBottom_toBottomOf="@+id/uploadDate" app:layout_constraintEnd_toStartOf="@+id/thumbsUpCount" - app:layout_constraintTop_toTopOf="@+id/authorAvatar" /> + app:layout_constraintTop_toTopOf="@+id/authorName" /> + app:layout_constraintTop_toTopOf="@+id/authorName" /> Date: Sun, 8 Feb 2026 13:07:23 +0530 Subject: [PATCH 33/56] remove existing comment replies screens before adding new one --- .../fragments/list/search/SearchFragment.java | 6 +++- .../schabi/newpipe/util/NavigationHelper.java | 36 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) 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 8cb5f6497..5c0d7d321 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 @@ -1009,7 +1009,11 @@ public class SearchFragment extends BaseListFragment searchBinding.suggestionsList.scrollToPosition(0)); + () -> { + if (searchBinding != null) { + searchBinding.suggestionsList.scrollToPosition(0); + } + }); if (suggestionsPanelVisible && isErrorPanelVisible()) { hideLoading(); 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 f702c5bd5..bfdf6a02c 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -501,6 +501,7 @@ public final class NavigationHelper { public static void openCommentRepliesFragment(@NonNull final FragmentActivity activity, @NonNull final CommentsInfoItem comment) { + closeCommentRepliesFragments(activity); defaultTransaction(activity.getSupportFragmentManager()) .replace(R.id.fragment_holder, new CommentRepliesFragment(comment), CommentRepliesFragment.TAG) @@ -508,6 +509,41 @@ public final class NavigationHelper { .commit(); } + /** + * Closes all open {@link CommentRepliesFragment}s in {@code activity}, + * including those that are not at the top of the back stack. + * This is needed to prevent multiple open CommentRepliesFragments + * Ideally there should only be one since we remove existing before opening a new one. + * @param activity the activity in which to close the CommentRepliesFragments + */ + public static void closeCommentRepliesFragments(@NonNull final FragmentActivity activity) { + final FragmentManager fm = activity.getSupportFragmentManager(); + + // Remove all existing fragment instances tagged as CommentRepliesFragment + final FragmentTransaction tx = defaultTransaction(fm); + boolean removed = false; + for (final Fragment fragment : fm.getFragments()) { + if (fragment != null && CommentRepliesFragment.TAG.equals(fragment.getTag())) { + tx.remove(fragment); + removed = true; + } + } + if (removed) { + tx.commit(); + } + + // Only pop back stack entries named CommentRepliesFragment.TAG if they are at the top. + while (fm.getBackStackEntryCount() > 0 + && CommentRepliesFragment.TAG.equals( + fm.getBackStackEntryAt(fm.getBackStackEntryCount() - 1).getName() + ) + ) { + fm.popBackStackImmediate(CommentRepliesFragment.TAG, + FragmentManager.POP_BACK_STACK_INCLUSIVE); + } + + } + public static void openPlaylistFragment(final FragmentManager fragmentManager, final int serviceId, final String url, @NonNull final String name) { From feb442492b7f5152a4e9d61a3f8131c99b1bd1b1 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Thu, 19 Feb 2026 09:41:02 +0100 Subject: [PATCH 34/56] Translated using Weblate (Dutch) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 100.0% (764 of 764 strings) Translated using Weblate (Dutch) Currently translated at 57.3% (51 of 89 strings) Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (764 of 764 strings) Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (764 of 764 strings) Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (764 of 764 strings) Translated using Weblate (Somali) Currently translated at 72.1% (551 of 764 strings) Translated using Weblate (Russian) Currently translated at 100.0% (764 of 764 strings) Translated using Weblate (Portuguese (Brazil)) Currently translated at 66.2% (59 of 89 strings) Translated using Weblate (Portuguese (Brazil)) Currently translated at 66.2% (59 of 89 strings) Translated using Weblate (Spanish) Currently translated at 100.0% (764 of 764 strings) Translated using Weblate (Dutch) Currently translated at 99.8% (763 of 764 strings) Translated using Weblate (Latvian) Currently translated at 97.6% (746 of 764 strings) Translated using Weblate (Portuguese (Portugal)) Currently translated at 99.8% (763 of 764 strings) Translated using Weblate (Portuguese (Brazil)) Currently translated at 53.9% (48 of 89 strings) Translated using Weblate (Spanish) Currently translated at 99.8% (763 of 764 strings) Translated using Weblate (Croatian) Currently translated at 100.0% (764 of 764 strings) Translated using Weblate (Chinese (Simplified Han script)) Currently translated at 100.0% (89 of 89 strings) Translated using Weblate (Marathi) Currently translated at 30.4% (233 of 764 strings) Translated using Weblate (Portuguese) Currently translated at 99.8% (763 of 764 strings) Translated using Weblate (Polish) Currently translated at 56.1% (50 of 89 strings) Co-authored-by: 439JBYL80IGQTF25UXNR0X1BG <439JBYL80IGQTF25UXNR0X1BG@users.noreply.hosted.weblate.org> Co-authored-by: AMOL GHORPADE Co-authored-by: Daria Szatan Co-authored-by: Hosted Weblate Co-authored-by: Kairos Co-authored-by: Milo Ivir Co-authored-by: Miq Maq Co-authored-by: Nicolás Pérez Co-authored-by: Philip Goto Co-authored-by: delvani Co-authored-by: igoroliveira-letras Co-authored-by: ojppe Co-authored-by: ssantos Co-authored-by: ℂ𝕠𝕠𝕠𝕝 (𝕘𝕚𝕥𝕙𝕦𝕓.𝕔𝕠𝕞/ℂ𝕠𝕠𝕠𝕝) Co-authored-by: 大王叫我来巡山 Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/nl/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pl/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pt_BR/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/zh_Hans/ Translation: NewPipe/Metadata --- app/src/main/res/values-es/strings.xml | 4 +- app/src/main/res/values-hr/strings.xml | 4 +- app/src/main/res/values-lv/strings.xml | 21 +++--- app/src/main/res/values-mr/strings.xml | 4 +- app/src/main/res/values-nl/strings.xml | 6 +- app/src/main/res/values-pt-rBR/strings.xml | 24 +++---- app/src/main/res/values-pt-rPT/strings.xml | 2 +- app/src/main/res/values-pt/strings.xml | 2 +- app/src/main/res/values-ru/strings.xml | 8 +-- app/src/main/res/values-so/strings.xml | 4 ++ .../metadata/android/nl/changelogs/1000.txt | 13 ++++ .../metadata/android/nl/changelogs/1002.txt | 2 +- .../metadata/android/nl/changelogs/1003.txt | 7 +- .../metadata/android/nl/changelogs/1004.txt | 4 +- .../metadata/android/nl/changelogs/1007.txt | 12 +++- .../metadata/android/nl/changelogs/64.txt | 2 +- .../metadata/android/nl/changelogs/930.txt | 2 +- .../metadata/android/nl/changelogs/952.txt | 10 +-- .../metadata/android/nl/changelogs/953.txt | 2 +- .../metadata/android/nl/changelogs/998.txt | 5 +- .../metadata/android/pl/changelogs/996.txt | 2 + .../android/pt-BR/changelogs/1000.txt | 24 +++---- .../android/pt-BR/changelogs/1002.txt | 5 +- .../android/pt-BR/changelogs/1003.txt | 7 +- .../android/pt-BR/changelogs/1004.txt | 4 +- .../android/pt-BR/changelogs/1005.txt | 28 ++++---- .../android/pt-BR/changelogs/1006.txt | 16 +++++ .../android/pt-BR/changelogs/1007.txt | 12 +++- .../android/pt-BR/changelogs/1008.txt | 4 ++ .../metadata/android/pt-BR/changelogs/65.txt | 27 +------- .../metadata/android/pt-BR/changelogs/66.txt | 54 ++++++++-------- .../metadata/android/pt-BR/changelogs/68.txt | 52 +++++++-------- .../metadata/android/pt-BR/changelogs/69.txt | 32 +++++----- .../metadata/android/pt-BR/changelogs/70.txt | 46 ++++++------- .../metadata/android/pt-BR/changelogs/71.txt | 18 +++--- .../metadata/android/pt-BR/changelogs/740.txt | 46 ++++++------- .../metadata/android/pt-BR/changelogs/750.txt | 38 +++++------ .../metadata/android/pt-BR/changelogs/760.txt | 64 +++++++++---------- .../metadata/android/pt-BR/changelogs/780.txt | 20 +++--- .../metadata/android/pt-BR/changelogs/790.txt | 24 +++---- .../metadata/android/pt-BR/changelogs/800.txt | 46 ++++++------- .../metadata/android/pt-BR/changelogs/810.txt | 34 +++++----- .../metadata/android/pt-BR/changelogs/840.txt | 40 ++++++------ .../metadata/android/pt-BR/changelogs/850.txt | 2 +- .../metadata/android/pt-BR/changelogs/930.txt | 32 +++++----- .../metadata/android/pt-BR/changelogs/954.txt | 12 ++-- .../metadata/android/pt-BR/changelogs/964.txt | 16 ++--- .../metadata/android/pt-BR/changelogs/966.txt | 24 +++---- .../metadata/android/pt-BR/changelogs/968.txt | 9 +++ .../metadata/android/pt-BR/changelogs/969.txt | 10 +++ .../metadata/android/pt-BR/changelogs/971.txt | 3 + .../metadata/android/pt-BR/changelogs/973.txt | 4 ++ .../metadata/android/pt-BR/changelogs/974.txt | 5 ++ .../metadata/android/pt-BR/changelogs/976.txt | 9 +++ .../metadata/android/pt-BR/changelogs/995.txt | 26 ++++---- .../metadata/android/pt-BR/changelogs/998.txt | 5 +- .../metadata/android/pt-BR/changelogs/999.txt | 13 +++- .../android/zh-Hans/changelogs/972.txt | 4 +- 58 files changed, 533 insertions(+), 422 deletions(-) create mode 100644 fastlane/metadata/android/nl/changelogs/1000.txt create mode 100644 fastlane/metadata/android/pl/changelogs/996.txt create mode 100644 fastlane/metadata/android/pt-BR/changelogs/1006.txt create mode 100644 fastlane/metadata/android/pt-BR/changelogs/1008.txt create mode 100644 fastlane/metadata/android/pt-BR/changelogs/968.txt create mode 100644 fastlane/metadata/android/pt-BR/changelogs/969.txt create mode 100644 fastlane/metadata/android/pt-BR/changelogs/971.txt create mode 100644 fastlane/metadata/android/pt-BR/changelogs/973.txt create mode 100644 fastlane/metadata/android/pt-BR/changelogs/974.txt create mode 100644 fastlane/metadata/android/pt-BR/changelogs/976.txt diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 9838eb3c1..1841b6c09 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -513,8 +513,8 @@ Canciones Este vídeo tiene restricción de edad. \n \nHabilitar \"%1$s\" en los ajustes si quieres verlo. Sí, y también vídeos vistos parcialmente - Los vídeos que ya se hayan visto luego de añadidos a la lista de reproducción, serán quitados. \n¿Estás seguro? ¡Esta acción no se puede deshacer! - ¿Quitar vídeos ya vistos? + Los vídeos que ya se hayan visto antes y después de ser añadidos a la lista de reproducción serán quitados. \n¿Estás seguro? + ¿Quitar streams ya vistos? Quitar vídeos ya vistos Por %s Creado por %s diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 757f6244d..f9f95db72 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -437,7 +437,7 @@ Ograniči popis preuzimanja Koristi sustavksi birač mapa (SAF) Ukloni pregledano - Ukloni pogledana videa? + Ukloniti pogledana emitiranja? %d sekunda %d sekunde @@ -510,7 +510,7 @@ Napredak je izgubljen, jer je datoteka izbrisana NewPipe se zatvorio tijekom rada s datotekom Stranica playliste - Videa koji su gledani prije i nakon dodavanja u playlistu će se ukloniti. \nStvarno ih želiš ukloniti? Ovo je nepovratna radnja! + Emitiranja koji su gledani prije i nakon dodavanja u playlistu će se ukloniti. \nStvarno ih želiš ukloniti? Još nema zabilježenih playlista Odaberi playlistu obnavljanje diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml index 0580b9dd7..45d126183 100644 --- a/app/src/main/res/values-lv/strings.xml +++ b/app/src/main/res/values-lv/strings.xml @@ -15,7 +15,7 @@ Popup atskaņotājs Fona atskaņotājs Sākt atskaņot ar popup - Sākt atskaņot fonā + Klausīties fonā šo Ielikts rindā Ielikt rindā Turiet, lai ieliktu atskaņošanas rindā @@ -123,7 +123,7 @@ Neviens neskatās - %s skatījumu + %s skatījumi %s skatījums %s skatījumi @@ -301,7 +301,7 @@ Plūsmas atjaunināšanas biežuma slieksnis Straume Rādīt tikai nepievienotus grupai abonementus - Jauna + Izveidot jaunu grupu Vai tiešām vēlaties izdzēst šo grupu? Tukšs grupas nosaukums @@ -339,8 +339,8 @@ ExoPlayer ierobežojumu dēļ meklēšanas ilgums tika iestatīts uz %d sekundēm Jā, un daļēji skatītos video - Video, kas skatīti pirms un pēc pievienošanas atskaņošanas sarakstam, tiks noņemti. \nVai tiešām turpināt? Šo darbību nevarēs atsaukt! - Vai tiešām noņemt skatītos video? + Tiešraides, kas pirms tam skatītas un pēc tam pievienotas atskaņošanas sarakstam, tiks noņemtas. \nVai tiešām turpināt? + Vai tiešām noņemt skatītās tiešraides? Noņemt skatīto System default Lietotnes valoda @@ -440,7 +440,7 @@ Minimizēt uz popup atskaņotāju Minimizēt uz fona atskaņotāju Nav - Rādīt paziņojumu, kad ir pieejama jauna aplikācijas versija + Rādīt paziņojumu, ja pieejama jauna lietotnes versija Atjauninājumi Ierobežots izšķirtspēju, izmantojot mobilos datus Nav ierobežojuma @@ -554,7 +554,7 @@ Lejupielādētās video datnes tiek glabātas šeit Video lejupielādes mape Pievienot - Fonā + Klausīties fonā Atlasiet cilni Saglabātie saraksti Abonementi @@ -620,7 +620,7 @@ Rādīt attēlu indikatorus Augstas kvalitātes (lielāks) Pārbaudīt atjauninājumus - Manuāli pārbaudīt, vai ir jaunas versijas + Pašrocīgi pārbaudīt jaunas versijas pieejamību Video atskaņošanas joslas sīktēla priekšskatījums Pārbauda, vai ir atjauninājumi… Sākot ar Android 10, tikai“Krātuves Piekļuves Sistēma” ir atbalstīta @@ -658,7 +658,7 @@ Jaunās tiešraides Radās kļūda, detalizētāku informāciju skatiet paziņojumā - %s jauna tiešraide + %s jaunas tiešraides %s jauna tiešraide %s jaunas tiešraides @@ -728,8 +728,7 @@ Par Sīkattēli Kārtot - NewPipe var automātiski pārbaudīt, vai ir jaunas versijas laiku pa laikam un paziņot jūs, kad tās ir pieejamas. -\nVai jūs gribat šo ieslēgt? + NewPipe var pati automātiski pārbaudīt jaunas versijas pieejamību laiku pa laikam un informēt jūs, kad tā ir pieejama.\nVai jūs tiešām gribiet ieslēgt šo funkciju? Netika atrasts atbilstošs failu pārvaldnieks šai darbībai. \nLūdzu instalējiet failu pārvaldnieku vai pamēģiniet atspējot \'%s\' lejuplādēšanas iestatījumos oriģinālais diff --git a/app/src/main/res/values-mr/strings.xml b/app/src/main/res/values-mr/strings.xml index 7a6b2eda4..de6cec2a0 100644 --- a/app/src/main/res/values-mr/strings.xml +++ b/app/src/main/res/values-mr/strings.xml @@ -31,7 +31,7 @@ पॉप अप मोड मध्ये उघडा हा मेन्यू नमुना व्हिडिओ किंवा ऑडियो वेब ब्राउजर मध्ये चालवू शकतो रद्द करा - इंस्टॉल + स्थापित करा प्लेअर सापडले नाही (तुम्ही VLC player वापरून फाईल चालवू शकता). प्लेअर सापडले नाही. VLC प्लेअर इंस्टॉल करू इच्छिता का\? प्रारंभ करण्यासाठी मॅग्निफाइंग ग्लासवर टॅप करा. @@ -236,4 +236,4 @@ माहिती रांगेत आहे बंद करा - \ 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 7d2f0b7be..845e7431c 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -213,7 +213,7 @@ Dit overschrijft je huidige configuratie. Streambestand downloaden Informatie tonen - Bijgehouden afspeellijsten + Afspeellijsten Toevoegen aan Versleep om de volgorde te wijzigen Aanmaken @@ -503,8 +503,8 @@ \n \nHopelijk zal dit bij een toekomstige versie ondersteund worden.
Ja, en deels bekeken video\'s - Video\'s die zijn bekeken voor, en na ze werden toegevoegd aan de afspeellijst worden verwijderd. \nWeet u dit zeker? Deze actie kan niet ongedaan gemaakt worden! - Bekeken video\'s verwijderen? + Streams die zijn bekeken voor, en na ze werden toegevoegd aan de afspeellijst worden verwijderd. \nWeet u dit zeker? + Bekeken streams verwijderen? ∞ video\'s 100+ video\'s Deze video heeft een leeftijdsbeperking. diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 490c5f617..1cbfa6947 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -69,20 +69,20 @@ Vídeos baixados são salvos aqui Pasta para vídeos baixados Instalar Kore? - Toque na lupa para começar. + Toque no ícone de lupa para iniciar sua busca. Processos Por favor, defina uma pasta de download depois nas configurações - Player de vídeo não encontrado. Instalar VLC? + O player de video não foi encontrado, mas você pode instalar o VLC. Deseja fazer isso? O site não pôde ser analisado Áudio Reproduzir no Kodi Buscar Mostrar opção para reproduzir o vídeo no Kodi Usar player de áudio externo - Usar player de vídeo externo + Usar um player de vídeo alternativo Mostrar opção \"Reproduzir no Kodi\" O que aconteceu:\nPedido:\nIdioma do conteúdo:\nPaís do conteúdo:\nIdioma do aplicativo:\nServiço:\nHora GMT:\nPacote:\nVersão:\nVersão do SO: - Abrir no modo Popup + Reproduzir no modo flutuante Resolução padrão do Popup Mostrar resoluções mais altas Apenas alguns dispositivos suportam vídeos em 2K/4K @@ -97,7 +97,7 @@ Segundo plano Lembrar propriedades do Popup Lembrar último tamanho e posição do Popup - Remove áudio em algumas resoluções + Atenção: o áudio pode não funcionar em certas resoluções Sugestões de busca Escolha as sugestões a serem exibidas enquanto estiver buscando Melhor resolução @@ -129,7 +129,7 @@ Continuar a reprodução após interrupções (por exemplo, chamadas telefônicas) Histórico de busca Armazena o histórico de busca localmente - Histórico de exibição + Histórico de reprodução Mantenha o controle dos vídeos assistidos Histórico Histórico @@ -188,7 +188,7 @@ Retribuir Site oficial Visite o site do NewPipe para mais informações e novidades. - Player de vídeo não encontrado (você pode instalar o VLC para reproduzi-lo). + O player de vídeo não foi encontrado, mas você pode instalar o VLC para tentar reproduzi-lo. País padrão do conteúdo Sempre Apenas uma vez @@ -212,7 +212,7 @@ Nenhum arquivo ZIP válido Aviso: Não foi possível importar todos os arquivos. Isso irá sobrescrever suas configurações atuais. - Baixar arquivo + Salvar arquivo para reprodução sem internet Mostrar informação Playlists favoritas Adicionar a @@ -295,10 +295,10 @@ Fechar gaveta Legendas Mudar tamanho da legenda e estilos de plano de fundo. Requer reiniciar o aplicativo para ter efeito - Remover histórico de exibição + Remover histórico de reprodução Remove o histórico de vídeos assistidos e as posições de reprodução - Remover todo o histórico de exibição? - Histórico de exibição removido + Remover todo o histórico de reprodução? + Histórico de reprodução removido Remover histórico de buscas Remove o histórico de buscas Remover todo o histórico de buscas? @@ -581,7 +581,7 @@ Comentários Desative para ocultar a descrição do vídeo e informações adicionais Mostrar descrição - Abrir com + Reproduzir com Nenhum aplicativo em seu dispositivo pode abrir isso O aplicativo parou Este conteúdo está disponível apenas para usuários que pagaram, portanto não pode ser transmitido ou baixado pelo NewPipe. diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 80f943ce5..f6e1b5a67 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -280,7 +280,7 @@ Notificações para novas versões do NewPipe Histórico Lista - Remover vídeos visualizados? + Remover transmissões vistas? %d minuto %d minutos diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 1ae1f8b6f..8e0210dbc 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -519,7 +519,7 @@ \nPara o poder ver, tem que ativar \"%1$s\" nas definições. Os vídeos que tenham sido vistos antes e depois de serem adicionados à lista de reprodução serão removidos. \nTem a certeza? Esta ação não pode ser revertida! Sim e também os vídeos parcialmente vistos - Remover vídeos visualizados? + Remover transmissões vistas? Remover visualizados Os textos originais dos serviços serão visíveis nos itens do vídeo Mostrar antiguidade nos itens diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index a10681060..fc32c0da3 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -345,7 +345,7 @@ Сетка Автоматически Загрузка на SD-карту невозможна. Сбросить расположение папки загрузки\? - SD-карта недоступна + Внешнее хранилище недоступно Вкладки, видимые на главной странице Значения по умолчанию Восстановить значения по умолчанию\? @@ -510,7 +510,7 @@ \nКак пример, YouTube поддерживает быстрое обновление. \n \nВыбор за вами: скорость или точность.
- Обновление по RSS, если доступно + Получать из выделенной ленты, когда доступно Доступно для некоторых сервисов, быстрое, может возвращать не всё содержимое канала и не содержать часть сведений (длительность, статус трансляции) Период актуальности подписок после обновления — %s Это видео имеет возрастное ограничение. @@ -526,8 +526,8 @@ Альбомы Удалить просмотренные Да, и частично просмотренные - Видео, просмотренные до или после добавления в плейлист, будут удалены. \nПродолжить? Не может быть отменено! - Удалить просмотренные видео? + Трансляции, просмотренные до или после добавления в плейлист, будут удалены. \nВы уверены? + Удалить просмотренные трансляции? Отображать сообщённое сервисом время с момента публикации Исходное время публикации Включить \"Ограниченный режим\" YouTube diff --git a/app/src/main/res/values-so/strings.xml b/app/src/main/res/values-so/strings.xml index 1453e3491..22d5fe16f 100644 --- a/app/src/main/res/values-so/strings.xml +++ b/app/src/main/res/values-so/strings.xml @@ -633,4 +633,8 @@ Soojeedinada raadinta gudaha Cabirka soodaarida udhexeeya Jabi Daareha + Haa + Maya + Raadi %1$s + Raadi %1$s (%2$s) diff --git a/fastlane/metadata/android/nl/changelogs/1000.txt b/fastlane/metadata/android/nl/changelogs/1000.txt new file mode 100644 index 000000000..91c136da5 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/1000.txt @@ -0,0 +1,13 @@ +Verbeterd: +• Maak de beschrijving van de afspeellijst klikbaar om meer/minder content te tonen +• [PeerTube] Verwerk `subscribeto.me`-instantiekoppelingen automatisch +• Begin alleen met het afspelen van één item in het geschiedenisscherm +Opgelost: + +• Herstel de zichtbaarheid van de RSS-knop +• Herstel crashes van de zoekbalkvoorvertoning +• Herstel het afspelen van een item zonder miniatuur +• Herstel het afsluiten van het downloaddialoogvenster voordat het verschijnt +• Herstel de pop-up van de lijst met gerelateerde items enqueue +• Herstel de volgorde in het dialoogvenster Toevoegen aan afspeellijst +• Pas de lay-out van het bladwijzeritem van de afspeellijst aan diff --git a/fastlane/metadata/android/nl/changelogs/1002.txt b/fastlane/metadata/android/nl/changelogs/1002.txt index 9bd8adf86..b31d08284 100644 --- a/fastlane/metadata/android/nl/changelogs/1002.txt +++ b/fastlane/metadata/android/nl/changelogs/1002.txt @@ -1 +1 @@ -YouTube speelt geen stream af opgelost +YouTube speelt geen stream af opgelost. diff --git a/fastlane/metadata/android/nl/changelogs/1003.txt b/fastlane/metadata/android/nl/changelogs/1003.txt index 9bd8adf86..9f1814388 100644 --- a/fastlane/metadata/android/nl/changelogs/1003.txt +++ b/fastlane/metadata/android/nl/changelogs/1003.txt @@ -1 +1,6 @@ -YouTube speelt geen stream af opgelost +Dit is een hotfix-release die YouTube-fouten verhelpt: +• [YouTube] Probleem opgelost waarbij geen video-informatie werd geladen, HTTP 403-fouten tijdens het afspelen van video's werden verholpen en de weergave van sommige video's met leeftijdsbeperking werd hersteld +• Probleem opgelost waarbij de ondertitelgrootte niet werd aangepast +• Probleem opgelost waarbij informatie twee keer werd gedownload bij het openen van een stream +• [Soundcloud] Niet-afspeelbare DRM-beveiligde streams verwijderd +• Vertalingen bijgewerkt diff --git a/fastlane/metadata/android/nl/changelogs/1004.txt b/fastlane/metadata/android/nl/changelogs/1004.txt index 9bd8adf86..f03db87b7 100644 --- a/fastlane/metadata/android/nl/changelogs/1004.txt +++ b/fastlane/metadata/android/nl/changelogs/1004.txt @@ -1 +1,3 @@ -YouTube speelt geen stream af opgelost +Deze release verhelpt het probleem dat YouTube alleen een 360p-stream aanbiedt. + +Houd er rekening mee dat de oplossing in deze versie waarschijnlijk tijdelijk is en dat op de lange termijn het SABR-videoprotocol geïmplementeerd moet worden. De leden van TeamNewPipe hebben het momenteel echter erg druk, dus alle hulp is van harte welkom! https://github.com/TeamNewPipe/NewPipe/issues/12248 diff --git a/fastlane/metadata/android/nl/changelogs/1007.txt b/fastlane/metadata/android/nl/changelogs/1007.txt index 9bd8adf86..95c723500 100644 --- a/fastlane/metadata/android/nl/changelogs/1007.txt +++ b/fastlane/metadata/android/nl/changelogs/1007.txt @@ -1 +1,11 @@ -YouTube speelt geen stream af opgelost +Deze hotfix verhelpt de foutmelding "Inhoud niet beschikbaar": YouTube-video's kunnen nu weer worden afgespeeld! + +Het lost ook een aantal bugs op die in versie 0.28.1 zijn geïntroduceerd: +• Playlist-items konden alleen naar aangrenzende posities worden gesleept +• Titel/opmerkingen flikkerden tussen de huidige en vorige video +• De optie "Start de hoofdspeler in volledig scherm" werkte niet + +Andere verbeteringen: +• [YouTube] Het is weer mogelijk om livestreams tot 4 uur terug te spoelen +• Livestreamvideo's worden niet geladen wanneer ze op de achtergrond worden afgespeeld +• Nieuwe gebruikersinterface voor "Verwijder bekeken" diff --git a/fastlane/metadata/android/nl/changelogs/64.txt b/fastlane/metadata/android/nl/changelogs/64.txt index dd457279c..dbed16537 100644 --- a/fastlane/metadata/android/nl/changelogs/64.txt +++ b/fastlane/metadata/android/nl/changelogs/64.txt @@ -1,5 +1,5 @@ ### Verbeteringen -- Mogelijkheid toegevoegd om de videokwaliteit te beperken bij het gebruik van mobiele data. #1339 +- Mogelijkheid toegevoegd om de videokwaliteit te beperken bij het gebruik van mobiele data. #1339 - Helderheid voor de sessie onthouden #1442 - Downloadprestaties voor zwakkere CPU's verbeterd #1431 - (werkende) ondersteuning voor mediasessie toegevoegd #1433 diff --git a/fastlane/metadata/android/nl/changelogs/930.txt b/fastlane/metadata/android/nl/changelogs/930.txt index 853bfa5de..9be06db77 100644 --- a/fastlane/metadata/android/nl/changelogs/930.txt +++ b/fastlane/metadata/android/nl/changelogs/930.txt @@ -10,7 +10,7 @@ Nieuw • Verbeterde formaatverwerking van de titel van de ladekoptekst Opgelost - • instelling voor inhoud met leeftijdsbeperking werkt niet opgelost + • instelling voor inhoud met leeftijdsbeperking werkt niet opgelost • Bepaalde soorten reCAPTCHA's opgelost • Crash opgelost bij het openen van bladwijzers terwijl de afspeellijst 'null' is • Vaste detectie van netwerkgerelateerde uitzonderingen diff --git a/fastlane/metadata/android/nl/changelogs/952.txt b/fastlane/metadata/android/nl/changelogs/952.txt index 3ff60109a..5dba7daed 100644 --- a/fastlane/metadata/android/nl/changelogs/952.txt +++ b/fastlane/metadata/android/nl/changelogs/952.txt @@ -1,7 +1,7 @@ Verbeterd -• Automatisch afspelen is beschikbaar voor alle services (in plaats van alleen voor YouTube) +• Auto-afspelen is beschikbaar voor alle services (in plaats van alleen voor YouTube) -Aangepast -• Vaste gerelateerde streams door de nieuwe voortzettingen van YouTube te ondersteunen -• YouTube-video's met leeftijdsbeperking -• [Android TV] Opgeloste overlay met focusaccenten +Opgelost +• Gerelateerde streams opgelost door YouTube's nieuwe voortzettingen te steunen +• Leeftijdsbeperkte YouTube videos opgelost +• [Android TV] Aanhoudende focusmarkeringlaag opgelost diff --git a/fastlane/metadata/android/nl/changelogs/953.txt b/fastlane/metadata/android/nl/changelogs/953.txt index 8f7f8b89a..7454c3ddc 100644 --- a/fastlane/metadata/android/nl/changelogs/953.txt +++ b/fastlane/metadata/android/nl/changelogs/953.txt @@ -1 +1 @@ -Herstel de extractie van de decoderingsfunctie van YouTube. +Extractie van YouTube's decryptiefunctie opgelost. diff --git a/fastlane/metadata/android/nl/changelogs/998.txt b/fastlane/metadata/android/nl/changelogs/998.txt index 9bd8adf86..fca4440dd 100644 --- a/fastlane/metadata/android/nl/changelogs/998.txt +++ b/fastlane/metadata/android/nl/changelogs/998.txt @@ -1 +1,4 @@ -YouTube speelt geen stream af opgelost +Het probleem dat YouTube geen streams afspeelde vanwege HTTP 403-fouten is opgelost. + +Incidentele HTTP 403-fouten midden in een YouTube-video zijn nog niet verholpen. +Dit probleem zal zo snel mogelijk in een volgende hotfix-release worden aangepakt. diff --git a/fastlane/metadata/android/pl/changelogs/996.txt b/fastlane/metadata/android/pl/changelogs/996.txt new file mode 100644 index 000000000..51b21ce58 --- /dev/null +++ b/fastlane/metadata/android/pl/changelogs/996.txt @@ -0,0 +1,2 @@ +Naprawiono NullPointerException podczas otwierania kanału / konferencji na media.ccc.de. +Grinch próbował zepsuć nasz prezent świąteczny, który został przygotowany dla Ciebie, ale to naprawiliśmy. diff --git a/fastlane/metadata/android/pt-BR/changelogs/1000.txt b/fastlane/metadata/android/pt-BR/changelogs/1000.txt index c158f5222..6a884f967 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/1000.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/1000.txt @@ -1,13 +1,13 @@ -Melhorias -• Tornar a descrição da lista de reprodução clicável para mostrar mais/menos conteúdo -• [PeerTube] Lidar automaticamente com links de instâncias do `subscribeto.me` -• Iniciar a reprodução de apenas um item na tela de histórico +Improved +• Make playlist description clickable to show more / less content +• [PeerTube] Handle `subscribeto.me` instance links automatically +• Only start playing single item in history screen -Corrigido -• Corrigir a visibilidade do botão RSS -• Corrigir falhas na pré-visualização da barra de busca -• Corrigir a inclusão de um item sem miniatura na lista de reprodução -• Corrigir o fechamento da caixa de diálogo de download antes de ela aparecer -• Corrigir o pop-up de enfileiramento da lista de itens relacionados -• Corrigir a ordem na caixa de diálogo de adicionar à lista de reprodução -• Ajustar o layout do item de marcador da lista de reprodução +Fixed +• Fix RSS button visibility +• Fix seekbar preview crashes +• Fix playlisting a thumbnail-less item +• Fix exiting the download dialog before it appears +• Fix related items list enqueue popup +• Fix order in add to playlist dialog +• Adjust the playlist bookmark item layout diff --git a/fastlane/metadata/android/pt-BR/changelogs/1002.txt b/fastlane/metadata/android/pt-BR/changelogs/1002.txt index 59fc6a5cd..7879b39db 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/1002.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/1002.txt @@ -1 +1,4 @@ -Corrigido YouTube não reproduzir qualquer transmissão +Corrigido o problema do YouTube não reproduzir nenhum vídeo. + +Esta versão corrige apenas o erro mais urgente que impede o carregamento de detalhes dos vídeos do YouTube. +Estamos cientes de que existem outros problemas e, em breve, lançaremos uma versão separada para resolvê-los. diff --git a/fastlane/metadata/android/pt-BR/changelogs/1003.txt b/fastlane/metadata/android/pt-BR/changelogs/1003.txt index 59fc6a5cd..3cad38acf 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/1003.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/1003.txt @@ -1 +1,6 @@ -Corrigido YouTube não reproduzir qualquer transmissão +Esta é uma versão de correção que corrige erros do YouTube: +• [YouTube] Corrige o não carregamento de informações de vídeo, corrige erros HTTP 403 durante a reprodução de vídeos e restaura a reprodução de alguns vídeos com restrição de idade +• Corrige o tamanho das legendas que não era alterado +• Corrige o download de informações duas vezes ao abrir uma transmissão. +• [Soundcloud] Remove transmissões protegidas por DRM que não podem ser reproduzidas +• Traduções atualizadas diff --git a/fastlane/metadata/android/pt-BR/changelogs/1004.txt b/fastlane/metadata/android/pt-BR/changelogs/1004.txt index 59fc6a5cd..a2c33d8ed 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/1004.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/1004.txt @@ -1 +1,3 @@ -Corrigido YouTube não reproduzir qualquer transmissão +Esta versão corrige o problema do YouTube fornecer apenas uma transmissão de 360p. + +Observe que a solução empregada nesta versão é provavelmente temporária e, a longo prazo, o protocolo de vídeo SABR precisa ser implementado, mas os membros da TeamNewPipe estão ocupados no momento, portanto, qualquer ajuda será muito bem-vinda! https://github.com/TeamNewPipe/NewPipe/issues/12248 diff --git a/fastlane/metadata/android/pt-BR/changelogs/1005.txt b/fastlane/metadata/android/pt-BR/changelogs/1005.txt index 3ef1f3e2e..2bfdfca0e 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/1005.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/1005.txt @@ -1,17 +1,17 @@ New -• Suporte adicionado para Android Auto -• Permitir configuração de grupos de feed como abas da tela principal -• [YouTube] Compartilhe como playlist temporária -• [SoundCloud] Aba de curtidas do canal +• Add support for Android Auto +• Allow setting feed groups as main screen tabs +• [YouTube] Share as temporary playlist +• [SoundCloud] Likes channel tab -Melhorado -• Melhor sugestão na barra de busca -• Mostra data do download em Downloads -• Usar idioma por aplicativo no Android 13 +Improved +• Better search bar hints +• Show download date in Downloads +• Use Android 13 per-app language -Consertado -• Texto no modo escuro consertado -• [YouTube] Conserta playlists não carregando mais do que 100 itens -• [YouTube] Conserta videos recomendados faltando -• Conserta lista de visualização do histórico -• Conserta registro de tempo na resposta de comentários +Fixed +• Fix broken text colors in dark mode +• [YouTube] Fix playlists not loading more than 100 items +• [YouTube] Fix missing recommended videos +• Fix crashes in History list view +• Fix timestamps in comment replies diff --git a/fastlane/metadata/android/pt-BR/changelogs/1006.txt b/fastlane/metadata/android/pt-BR/changelogs/1006.txt new file mode 100644 index 000000000..90fd823f9 --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/1006.txt @@ -0,0 +1,16 @@ +# Melhorias +Mantém o player ao tocar nas minutagens do vídeo. +Recupera downloads pendentes quando possível. +Limpa a lista de downloads sem excluir o arquivo permanentemente. +Aviso de Permissão de Sobreposição (Android R+). +Suporte a links do SoundCloud. +Pequenas melhorias e otimizações. + +# Correções +Formato de contagem para Android < 7. +Notificações confusas ou incoerentes. +Ajustes em legendas SRT. +Correção de fechamentos bruscos (crashes). + +# Desenvolvimento +Modernização do código interno. diff --git a/fastlane/metadata/android/pt-BR/changelogs/1007.txt b/fastlane/metadata/android/pt-BR/changelogs/1007.txt index 59fc6a5cd..d3bd98aea 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/1007.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/1007.txt @@ -1 +1,11 @@ -Corrigido YouTube não reproduzir qualquer transmissão +This hotfix release fixes the "Content not available" error: YouTube videos can now be played again! + +It also fixes a few bugs introduced in 0.28.1: +• Playlist items dragging to only neighbor positions +• Title/comments flickering between current and previous video +• "Start main player in fullscreen" option not working + +Other improvements: +• [YouTube] Allow rewinding livestreams up to 4 hours again +• Don't load livestream video when playing in background +• New UI for "Remove watched" diff --git a/fastlane/metadata/android/pt-BR/changelogs/1008.txt b/fastlane/metadata/android/pt-BR/changelogs/1008.txt new file mode 100644 index 000000000..ef7d70a9b --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/1008.txt @@ -0,0 +1,4 @@ +∙ Corrigido o retomar de streams na última posição de reprodução +∙ [YouTube] Adicionado suporte a mais formatos de URL de canal +∙ [YouTube] Adicionado suporte a mais formatos de metadados de vídeo +∙ Traduções atualizadas diff --git a/fastlane/metadata/android/pt-BR/changelogs/65.txt b/fastlane/metadata/android/pt-BR/changelogs/65.txt index bd7a638f6..ed37e78e5 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/65.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/65.txt @@ -1,26 +1 @@ -### Melhorias - -- Desabilitar a animação do ícone do burgermenu #1486 -- Desfazer a eliminação de descarregamentos #1472 -- Opção de descarregamento no menu de partilha #1498 -- Opção de partilha adicionada ao menu de toque longo #1454 -- Minimize o jogador principal na saída #1354 -- Atualização da versão da biblioteca e correção de cópia de segurança da base de dados #1510 -- ExoPlayer 2.8.2 Atualização #1392 - - Retrabalhado a caixa de diálogo de controlo de velocidade de reprodução para suportar diferentes tamanhos de etapa para uma mudança de velocidade mais rápida. - - Adicionado uma alternância para avanço rápido durante silêncios no controle de velocidade de reprodução. Isso deve ser útil para audiolivros e certos gêneros musicais, e pode trazer uma experiência verdadeiramente perfeita (e pode quebrar uma música com muitos silêncios =\\) - - Resolução de fonte de média ré fatorada para permitir a passagem de metadados junto com a média internamente no reprodutor, em vez de fazê-lo manualmente. Agora temos uma única fonte de metadados e está disponível diretamente quando a reprodução é iniciada. - - Correção de metadados de listas de reprodução remotas que não são atualizadas quando novos metadados estão disponíveis quando o fragmento da lista de reprodução é aberta. - - Várias correções de interface do utilizador : #1383, controles de notificação do reprodutor em segundo plano agora sempre brancos, mais fácil de desligar o reprodutor pop-up por meio de arremesso -- Use novo extrator com arquitetura ré fatorada para multisserviço - -### Correções - -- Corrigir #1440 Layout de informações de vídeo quebrado #1491 -- Ver correção de histórico #1497 - - #1495, atualizando os metadados (miniatura, título e contagem de vídeos) assim que o usuário acessar a lista de reprodução. - - #1475, registando uma visualização na base de dados quando o utilizador inicia um vídeo no reprodutor externo no fragmento de detalhes. -- Correção de tempo limite de criação em caso de modo pop-up. #1463 (Corrigido #640) -- Correção do reprodutor de vídeo principal #1509 - [#1412] Corrigido o modo de repetição causando NPE do reprodutor quando uma nova intenção é recebida enquanto a atividade do reprodutor está em segundo plano. - - Corrigida a minimização de reprodutor para pop-up não destrói o reprodutor quando a permissão de pop-up não é concedida. +A tradução não deve exceder o comprimento. diff --git a/fastlane/metadata/android/pt-BR/changelogs/66.txt b/fastlane/metadata/android/pt-BR/changelogs/66.txt index ed84a2759..30c20b0e8 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/66.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/66.txt @@ -1,33 +1,33 @@ -# Changelog de v0.13.7 +# Changelog of v0.13.7 -### Fixo -- Fixar questões de filtro de ordenação da v0.13.6 +### Fixed +- Fix sort filter issues of v0.13.6 -# Mudança do v0.13.6 +# Changelog of v0.13.6 -### Melhorias +### Improvements -- Desactivar animação de ícones de burgermenu #1486 -- anular a eliminação dos downloads #1472 -- Opção de download no menu de partilha #1498 -- Adicionada a opção de partilha no menu de toque longo #1454 -- Minimizar o jogador principal na saída #1354 -- Actualização da versão da biblioteca e correcção da cópia de segurança da base de dados #1510 -- ExoPlayer 2.8.2 Actualização #1392 - - Reformulou o diálogo de controlo de velocidade de reprodução para suportar diferentes tamanhos de passos para uma mudança de velocidade mais rápida. - - Adicionada uma alternância para avançar rapidamente durante os silêncios no controlo de velocidade de reprodução. Isto deve ser útil para audiolivros e certos géneros musicais, e pode trazer uma verdadeira experiência sem falhas (e pode quebrar uma canção com muitos silêncios =\i1). - - A resolução da fonte dos meios de comunicação foi refeita para permitir a passagem de metadados ao lado dos meios de comunicação internamente no leitor, em vez de o fazer manualmente. Agora temos uma única fonte de metadados e está directamente disponível quando a reprodução começa. - - Fixados os metadados da lista de reprodução remota que não são actualizados quando novos metadados estão disponíveis quando o fragmento da lista de reprodução é aberto. - - Várias correcções UI: #1383, a notificação do leitor de fundo controla agora sempre branco, mais fácil de desligar o leitor de pop-ups através do fling -- Usar novo extractor com arquitectura refacturada para multiserviços +- Disable burgermenu icon animation #1486 +- undo delete of downloads #1472 +- Download option in share menu #1498 +- Added share option to long tap menu #1454 +- Minimize main player on exit #1354 +- Library version update and database backup fix #1510 +- ExoPlayer 2.8.2 Update #1392 + - Reworked the playback speed control dialog to support different step sizes for faster speed change. + - Added a toggle to fast-forward during silences in playback speed control. This should be helpful for audiobooks and certain music genres, and can bring a true seamless experience (and can break a song with lots of silences =\\). + - Refactored media source resolution to allow passing metadata alongside media internally in the player, rather than doing so manually. Now we have a single source of metadata and is directly available when playback starts. + - Fixed remote playlist metadata not updating when new metadata is available when playlist fragment is opened. + - Various UI fixes: #1383, background player notification controls now always white, easier to shutdown popup player through flinging +- Use new extractor with refactored architecture for multiservice -### Correcções +### Fixes -- Reparação #1440 Layout de Informação de Vídeo Partido #1491 -- Ver histórico correcção #1497 - - #1495, actualizando os metadados (miniatura, título e contagem de vídeo) assim que o utilizador aceda à lista de reprodução. - - #1475, através do registo de uma vista na base de dados quando o utilizador inicia um vídeo no leitor externo sobre fragmento de detalhe. -- Fixar tempo limite de creen em caso de modo popup. #1463 (Fixado #640) -- Correcção principal do leitor de vídeo #1509 - - [#1412] Modo de repetição fixo causando NPE do jogador quando novas intenções são recebidas enquanto a actividade do jogador está em segundo plano. - - Fixa a minimização do jogador a popup não destrói o jogador quando não é concedida permissão de popup. +- Fix #1440 Broken Video Info Layout #1491 +- View history fix #1497 + - #1495, by updating the metadata (thumbnail, title and video count) as soon as the user access the playlist. + - #1475, by registering a view in the database when the user starts a video on external player on detail fragment. +- Fix creen timeout in case of popup mode. #1463 (Fixed #640) +- Main video player fix #1509 + - [#1412] Fixed repeat mode causing player NPE when new intent is received while player activity is in background. + - Fixed minimizing player to popup does not destroy player when popup permission is not granted. diff --git a/fastlane/metadata/android/pt-BR/changelogs/68.txt b/fastlane/metadata/android/pt-BR/changelogs/68.txt index 1e6c42e01..238b1e0b1 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/68.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/68.txt @@ -1,31 +1,31 @@ -# mudanças da v0.14.1 +# changes of v0.14.1 -### fixo -- Fixo falhou em desencriptar a url de vídeo #1659 -- Ligação de descrição fixa não extraída bem #1657 +### Fixed +- Fixed failed to decrypt video url #1659 +- Fixed description link not extract well #1657 -# mudanças de v0.14.0 +# changes of v0.14.0 -### Novo -- Novo desenho de gaveta #1461 -- Nova página inicial personalizável #1461 +### New +- New Drawer design #1461 +- New customizable front page #1461 -### Melhorias -- Controlos por gestos retrabalhados #1604 -- Nova forma de fechar o leitor de popup #1597 +### Improvements +- Reworked Gesture controls #1604 +- New way to close the popup player #1597 -### Fixa -- Corrigir erro quando a contagem de assinaturas não está disponível. Fecha #1649. - - Mostrar "Contagem de subscritores não disponível" nesses casos -- Consertar NPE quando uma lista de reprodução do YouTube está vazia -- Correcção rápida para os quiosques em SoundCloud -- Refactor e correcção de bugs #1623 - - Resultado de pesquisa cíclica reparada #1562 - - Barra de procura fixa não estática - - Os vídeos do YT Premium não estão bloqueados correctamente - - Vídeos Fixos por vezes não carregados (devido à análise do DASH) - - Corrigir ligações na descrição vídeo - - Mostrar aviso quando alguém tenta descarregar para sdcard externo - - nada de excepção mostrado dispara o relatório - - thumbnail não mostrado no leitor de fundo para andróide 8.1 [ver aqui](https://github.com/TeamNewPipe/NewPipe/issues/943) -- Correcção do registo do receptor de radiodifusão. Fecha #1641. +### Fixed +- Fix error when subscription count is not available. Closes #1649. + - Show "Subscriber count not available" in those cases +- Fix NPE when a YouTube playlist is empty +- Quick fix for the kiosks in SoundCloud +- Refactor and bugfix #1623 + - Fix Cyclic search result #1562 + - Fix Seek bar not statically lay outed + - Fix YT Premium video are not blocked correctly + - Fix Videos sometimes not loading (due to DASH parsing) + - Fix links in video description + - Show warning when someone tries to download to external sdcard + - fix nothing shown exception triggers report + - thumbnail not shown in background player for android 8.1 [see here](https://github.com/TeamNewPipe/NewPipe/issues/943) +- Fix registering of broadcast receiver. Closes #1641. diff --git a/fastlane/metadata/android/pt-BR/changelogs/69.txt b/fastlane/metadata/android/pt-BR/changelogs/69.txt index fa7d5d85c..c8262d1b0 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/69.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/69.txt @@ -1,19 +1,19 @@ -#### Novo -- Eliminação de longa duração e partilha de subscrições #1516 -- Tabela UI e esquema de lista de grelha #1617 +### New +- Long-tap delete and share in subscriptions #1516 +- Tablet UI and grid list layout #1617 -### Melhorias -- armazenar e recarregar a última relação de aspeto utilizada #1748 -- Ativar a disposição linear na atividade de Downloads com nomes de vídeo completos #1771 -- Apagar e partilhar subscrições diretamente do separador de subscrições #1516 -- Enqueuing agora ativa a reprodução de vídeo se a fila de reprodução já tiver terminado #1783 -- Configurações separadas para os gestos de volume e luminosidade #1644 -- Adicionar apoio à Localização #1792 +### Improvements +- store and reload the last used aspect ratio #1748 +- Enable linear layout in Downloads activity with full video names #1771 +- Delete and share subscriptions directly from within the subscriptions tab #1516 +- Enqueuing now triggers video playing if the play queue has already ended #1783 +- Separate settings for volume and brightness gestures #1644 +- Add support for Localization #1792 -### Correções -- Fixar a análise do tempo para . formato, para que NewPipe possa ser usado na Finlândia -- Contagem fixa de assinaturas -- Adicionar permissão de serviço em primeiro plano para dispositivos API 28+ #1830 +### Fixes +- Fix time parsing for . format, so NewPipe can be used in Finland +- Fix subscription count +- Add foreground service permission for API 28+ devices #1830 -### Bugs conhecidos -- O estado de reprodução não pode ser guardado no Android P +### Known Bugs +- Playback state can not be saved on Android P diff --git a/fastlane/metadata/android/pt-BR/changelogs/70.txt b/fastlane/metadata/android/pt-BR/changelogs/70.txt index 61de40666..ad87a4409 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/70.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/70.txt @@ -1,25 +1,25 @@ -Atenção: esta versão é provavelmente um bugfest, tal como a última. No entanto, devido ao desligamento total desde o 17. uma versão quebrada é melhor do que nenhuma versão. Certo? ¯\_(ツ)_/¯ +ATTENTION: This version probably is a bugfest, just like the last one. However due to the full shutdown since the 17. a broken version is better then no version. Right? ¯\_(ツ)_/¯ -### Melhoria -* os arquivos baixados agora podem ser abertos com um clique #1879 -* suporte drop para android 4.1-4.3 #1884 -* remover jogador antigo #1884 -* remova os fluxos da fila de reprodução atual passando-os para a direita #1915 -* remova o fluxo enfileirado automático quando um novo fluxo é enfileirado manualmente # 1878 -* Pós-processamento para downloads e implementar recursos ausentes #1759 por @ kapodamy - * Infra-estruturas de pós-processamento - * Tratamento adequado de erros "infraestrutura" (para downloader) - * Fila em vez de vários downloads - * Mover transferências pendentes serializadas (`.arquivos giga`) para dados do aplicativo - * Implementar nova tentativa máxima de download - * Pausa adequada para o download de vários segmentos - * Parar downloads quando swicthing à rede móvel (nunca funciona, ver ponto 2) - * Salve a contagem de threads para os próximos downloads - * Muitas incoerências corrigidas +### Improvements +* downloaded files can now be opened with one click #1879 +* drop support for android 4.1 - 4.3 #1884 +* remove old player #1884 +* remove streams from current play queue by swiping them to the right #1915 +* remove auto queued stream when a new stream is enqueued manually #1878 +* Postprocessing for downloads and implement missing features #1759 by @kapodamy + * Post-processing infrastructure + * Proper error handling "infrastructure" (for downloader) + * Queue instead of multiple downloads + * Move serialized pending downloads (`.giga` files) to app data + * Implement max download retry + * Proper multi-thread download pausing + * Stop downloads when swicthing to mobile network (never works, see 2nd point) + * Save the thread count for next downloads + * A lot of incoherences fixed -### Corrigido -* Corrigir falha com resolução padrão definida como a melhor e limitada resolução de dados móveis #1835 -* falha do jogador pop-up corrigida #1874 -* NPE ao tentar abrir o jogador de fundo #1901 -* Correção para inserir novos fluxos quando o enfileiramento automático está habilitado #1878 -* Corrigido o problema decypering shuttown +### Fixed +* Fix crash with default resolution set to best and limited mobile data resolution #1835 +* pop-up player crash fixed #1874 +* NPE when trying to open background player #1901 +* Fix for inserting new streams when auto queuing is enabled #1878 +* Fixed the decypering shuttown issue diff --git a/fastlane/metadata/android/pt-BR/changelogs/71.txt b/fastlane/metadata/android/pt-BR/changelogs/71.txt index fb525cccc..5facfc05f 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/71.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/71.txt @@ -1,10 +1,10 @@ -### Melhoria -* Adicionar notificação de atualização do aplicativo para compilação do GitHub (#1608 por @ krtkush) -* Várias melhorias para o downloader(# 1944 por @kapodamy): - * * adicione ícones brancos ausentes e use o modo hardcore para alterar as cores dos ícones - * verifique se o iterador foi inicializado (correções #2031) - * * permitir novas tentativas de downloads com erro "Falha no pós-processamento" no novo mixer - * novo muxer MPEG - 4 que fixa fluxos de vídeo e áudio não síncronos (#2039) +### Improvements +* Add app update notification for GitHub build (#1608 by @krtkush) +* Various improvements to the downloader (#1944 by @kapodamy): + * add missing white icons and use hardcored way for change the icon colors + * check if the iterator is initialized (fixes #2031) + * allow retry downloads with "post-processing failed" error in the new muxer + * new MPEG-4 muxer fixing non-synchronous video and audio streams (#2039) -### Corrigido -* * As transmissões ao vivo do YouTube param de ser reproduzidas após um curto período de tempo(# 1996 por @username) +### Fixed +* YouTube live streams stop playing after a short time (#1996 by @yausername) diff --git a/fastlane/metadata/android/pt-BR/changelogs/740.txt b/fastlane/metadata/android/pt-BR/changelogs/740.txt index d591eda53..c795978a8 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/740.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/740.txt @@ -1,23 +1,23 @@ -< H4 > melhorias< / h4> -< ul> -< li>tornar os links nos comentários clicáveis, aumentar o tamanho do texto< / li> -< li>procurar ao clicar em links de carimbo de data/hora nos comentários< / li> -< li>mostrar a guia preferida com base no estado selecionado recentemente< / li> -< li>adicionar lista de reprodução à fila ao clicar longamente em & # 39;fundo& # 39; na janela da lista de reprodução< / li> -< li>procurar texto partilhado quando não é um URL< / li> -< li>adicionar o botão"Partilhar no momento atual & quot; ao leitor de vídeo principal< / li> -< li>adicionar botão fechar ao leitor principal quando terminar a fila de vídeo< / li> -< li>Adicionar & quot;Reproduzir diretamente em segundo plano & quot; ao menu longpress para itens da lista de vídeos< / li> -< li>melhorar as traduções em Inglês para comandos Play / Enqueue< / li> -< li>pequenas melhorias de desempenho< / li> -< li>remover ficheiros não utilizados < / li> -< li>Atualizar o ExoPlayer para 2.9.6< / li> -< li>adicionar suporte para links ofensivos< / li> -< / ul> -

fixo < /h4> -< ul> -< li>rolagem fixa com comentários e fluxos relacionados desativados < / li> -< li>Corrigido CheckForNewAppVersionTask sendo executado quando deveria & # 39; t< / li> -< li>importação de assinatura fixa do youtube: ignore aqueles com url inválido e mantenha aqueles com título vazio< / li> -< li>corrigir URL inválido do YouTube: o nome da marca de assinatura nem sempre é "Assinatura", impedindo o carregamento de fluxos< / li> -< / ul> +

Improvements

+
    +
  • make links in comments clickable, increase text size
  • +
  • seek on clicking timestamp links in comments
  • +
  • show preferred tab based on recently selected state
  • +
  • add playlist to queue when long clicking on 'Background' in playlist window
  • +
  • search for shared text when it is not an URL
  • +
  • add "share at current time" button to the main video player
  • +
  • add close button to main player when video queue is finished
  • +
  • add "Play directly in Background" to longpress menu for video list items
  • +
  • improve English translations for Play/Enqueue commands
  • +
  • small performance improvements
  • +
  • remove unused files
  • +
  • update ExoPlayer to 2.9.6
  • +
  • add support for Invidious links
  • +
+

Fixed

+
    +
  • fixed scroll w/ comments and related streams disabled
  • +
  • fixed CheckForNewAppVersionTask being executed when it shouldn't
  • +
  • fixed youtube subscription import: ignore ones with invalid url and keep ones with empty title
  • +
  • fix invalid YouTube url: signature tag name is not always "signature" preventing streams from loading
  • +
diff --git a/fastlane/metadata/android/pt-BR/changelogs/750.txt b/fastlane/metadata/android/pt-BR/changelogs/750.txt index 25f0c1dbf..39b77f7c3 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/750.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/750.txt @@ -1,22 +1,22 @@ -Novo -Resumo da reprodução #2288 -* Retomar fluxos onde parou da última vez -Melhorias Do Downloader #2149 -* Use o Storage Access Framework para armazenar downloads em cartões SD externos -* Novo MP4 muxer -* Opcionalmente, altere o diretório de download antes de iniciar um download -* Respeitar as redes de medição +New +Playback resume #2288 +• Resume streams where you stopped last time +Downloader Enhancements #2149 +• Use Storage Access Framework to store downloads on external SD-cards +• New mp4 muxer +• Optionally change the download directory before starting a download +• Respect metered networks -Melhorado -* Cordas gema removidas #2295 -* Lidar com mudanças de rotação (automática) durante o ciclo de vida da atividade #2444 -* Tornar os menus de pressão longa consistentes #2368 +Improved +• Removed gema strings #2295 +• Handle (auto)rotation changes during activity lifecycle #2444 +• Make long-press menus consistent #2368 -Corrigido -* Corrigido o nome da faixa de legenda selecionada não sendo mostrado #2394 -• Não trave quando a verificação da atualização do aplicativo falhar (versão do GitHub) #2423 -* Downloads fixos presos em 99,9% #2440 -* Atualizar meta dados da fila de reprodução #2453 -* [*[SoundCloud] corrigida a falha ao carregar listas de reprodução Team New Pipe / New Pipe Extractor#170 -* [*[YouTube] A duração fixa não pode ser analisada Team New Pipe / New Pipe Extractor#177 +Fixed +• Fixed selected subtitle track name not being shown #2394 +• Do not crash when check for app update fails (GitHub version) #2423 +• Fixed downloads stuck at 99.9% #2440 +• Update play queue metadata #2453 +• [SoundCloud] Fixed crash when loading playlists TeamNewPipe/NewPipeExtractor#170 +• [YouTube] Fixed duration can not be paresd TeamNewPipe/NewPipeExtractor#177 diff --git a/fastlane/metadata/android/pt-BR/changelogs/760.txt b/fastlane/metadata/android/pt-BR/changelogs/760.txt index 113a92615..6e000f6d9 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/760.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/760.txt @@ -1,43 +1,43 @@ -Alterações em 0.17.1 +Changes in 0.17.1 -Novo -* Localização tailandesa +New +• Thai localization -Melhorado -* Adicionar começar a jogar aqui ação em menus de longo imprensa para playlists novamente #2518 -* Adicionar interruptor para SAF / legacy file picker #2521 +Improved +• Add start playing here action in long-press menus for playlists again #2518 +• Add switch for SAF / legacy file picker #2521 -Corrigido -* Corrigir botões desaparecendo na visualização de downloads ao alternar aplicativos #2487 -* Corrigir a posição de reprodução é armazenada, embora o histórico de exibição esteja desativado -* Corrigir desempenho reduzido causado pela posição de reprodução em visualizações de lista #2517 -* [Extractor] Corrigir ReCaptchaActivity # 2527, TeamNewPipe / NewPipeExtractor#186 -* [Extractor] [YouTube] Corrigir Erro de pesquisa casual quando as listas de reprodução estão nos resultados TeamNewPipe / NewPipeExtractor#185 +Fixed +• Fix disappearing buttons in downloads view when switching apps #2487 +• Fix playback position is stored although watch history is disabled +• Fix reduced performance caused by playback position in list views #2517 +• [Extractor] Fix ReCaptchaActivity #2527, TeamNewPipe/NewPipeExtractor#186 +• [Extractor] [YouTube] Fix casual search error when playlists are in results TeamNewPipe/NewPipeExtractor#185 -Alterações em 0.17.0 +Changes in 0.17.0 -Novo -Resumo da reprodução #2288 -* Retomar fluxos onde parou da última vez -Melhorias Do Downloader #2149 -* Use o Storage Access Framework para armazenar downloads em cartões SD externos -* Novo MP4 muxer -* Opcionalmente, altere o diretório de download antes de iniciar um download -* Respeitar as redes de medição +New +Playback resume #2288 +• Resume streams where you stopped last time +Downloader Enhancements #2149 +• Use Storage Access Framework to store downloads on external SD-cards +• New mp4 muxer +• Optionally change the download directory before starting a download +• Respect metered networks -Melhorado -* Cordas gema removidas #2295 -* Lidar com mudanças de rotação (automática) durante o ciclo de vida da atividade #2444 -* Tornar os menus de pressão longa consistentes #2368 +Improved +• Removed gema strings #2295 +• Handle (auto)rotation changes during activity lifecycle #2444 +• Make long-press menus consistent #2368 -Corrigido -* Corrigido o nome da faixa de legenda selecionada não sendo mostrado #2394 -• Não trave quando a verificação da atualização do aplicativo falhar (versão do GitHub) #2423 -* Downloads fixos presos em 99,9% #2440 -* Atualizar metadados da fila de reprodução #2453 -* [SoundCloud] corrigida a falha ao carregar listas de reprodução TeamNewPipe / NewPipeExtractor#170 -* [YouTube] duração fixa não pode ser Paresd TeamNewPipe / NewPipeExtractor#177 +Fixed +• Fixed selected subtitle track name not being shown #2394 +• Do not crash when check for app update fails (GitHub version) #2423 +• Fixed downloads stuck at 99.9% #2440 +• Update play queue metadata #2453 +• [SoundCloud] Fixed crash when loading playlists TeamNewPipe/NewPipeExtractor#170 +• [YouTube] Fixed duration can not be paresd TeamNewPipe/NewPipeExtractor#177 diff --git a/fastlane/metadata/android/pt-BR/changelogs/780.txt b/fastlane/metadata/android/pt-BR/changelogs/780.txt index 61392c0df..9100d7335 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/780.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/780.txt @@ -1,12 +1,12 @@ -Alterações em 0.17.3 +Changes in 0.17.3 -Melhorado -- Adicionada opção para limpar estados de reprodução #2550 -- Mostrar diretórios ocultos no seletor de ficheiros #2591 -- URLs de apoio de instâncias `invidio.us` a serem abertas com NewPipe #2488 -- Adicionar suporte para `music.youtube.com` URLs TeamNewPipe/NewPipeExtractor#194 +Improved +• Added option to clear playback states #2550 +• Show hidden directories in the file picker #2591 +• Support URLs from `invidio.us` instances to be opened with NewPipe #2488 +• Add support for `music.youtube.com` URLs TeamNewPipe/NewPipeExtractor#194 -Corrigido -- [YouTube] Fixo 'java.lang.IllegalArgumentException #192 -- [YouTube] Fluxos fixos ao vivo não funcionam TeamNewPipe/NewPipeExtractor#195 -- Resolvido problema de desempenho em torta de android ao descarregar um fluxo #2592 +Fixed +• [YouTube] Fixed 'java.lang.IllegalArgumentException #192 +• [YouTube] Fixed live streams not working TeamNewPipe/NewPipeExtractor#195 +• Fixed performance problem in android pie when downloading a stream #2592 diff --git a/fastlane/metadata/android/pt-BR/changelogs/790.txt b/fastlane/metadata/android/pt-BR/changelogs/790.txt index f1b3a2dd9..ec77b2acb 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/790.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/790.txt @@ -1,14 +1,14 @@ -Melhorado -- Adicionar mais títulos para melhorar a acessibilidade para os cegos #2655 -- Tornar a linguagem da pasta de download mais consistente e menos ambígua #2637 +Improved +• Add more titles to improve accessibility for blind people #2655 +• Make language of download folder setting more consistent and less ambiguous #2637 -Fixa -- Verificar se o último byte no bloco é descarregado #2646 -- Rolagem fixa em fragmento de detalhe de vídeo #2672 -- Remover a dupla pesquisa de animações de caixa transparente para uma #2695 -- Fixar extracção client_id #2745 +Fixed +• Check if last byte in the block is downloaded #2646 +• Fixed scrolling in video detail fragment #2672 +• Remove double search clear box animations to one #2695 +• [SoundCloud] Fix client_id extraction #2745 -Desenvolvimento -- Adicionar dependências em falta herdadas de NewPipeExtractor em NewPipe #2535 -- Migrar para AndroidX #2685 -- Actualização para ExoPlayer 2.10.6 #2697, #2736 +Development +• Add missing dependencies inherited from NewPipeExtractor into NewPipe #2535 +• Migrate to AndroidX #2685 +• Update to ExoPlayer 2.10.6 #2697, #2736 diff --git a/fastlane/metadata/android/pt-BR/changelogs/800.txt b/fastlane/metadata/android/pt-BR/changelogs/800.txt index 1b6ec1a4c..332b5c994 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/800.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/800.txt @@ -1,27 +1,27 @@ -Novo -- Suporte PeerTube sem P2P (#2201) [Beta]: - ◦ Ver e descarregar vídeos de instâncias do PeerTube - ◦ Adicionar instâncias nas definições para aceder ao mundo completo do PeerTube - ◦ Pode haver problemas com apertos de mão SSL no Android 4.4 e 7.1 quando o acesso a certos casos resulta num erro de rede. +New +• PeerTube support without P2P (#2201) [Beta]: + ◦ Watch and download videos from PeerTube instances + ◦ Add instances in the settings to access the complete PeerTube world + ◦ There might be problems with SSL handshakes on Android 4.4 and 7.1 when accessing certain instances resulting in a network error. -- Downloader (#2679): - ◦ Calcular ETA de descarregamento - ◦ Descarregar opus (ficheiros webm) como ogg - ◦ Recuperar ligações expiradas para retomar os downloads após uma longa pausa +• Downloader (#2679): + ◦ Calculate download ETA + ◦ Download opus (webm files) as ogg + ◦ Recover expired download links to resume downloads after a long pause -Melhorado -- Tornar o KioskFragment consciente das mudanças no país de conteúdo preferido e melhorar o desempenho de todos os separadores principais #2742 -- Utilizar novas implementações de Localização e Downloader do extractor #2713 -- Tornar o fio "Quiosque por defeito" traduzível -- Barra de navegação preta para o tema preto #2569 +Improved +• Make the KioskFragment aware of changes in the preferred content country and improve performance of all main tabs #2742 +• Use new Localization and Downloader implementations from extractor #2713 +• Make "Default kiosk" string translatable +• Black navigation bar for black theme #2569 -Fixa -- Corrigido um bug que não podia mover o leitor de popup se outro dedo fosse colocado enquanto se movia o leitor de popup #2772 -- Permitir listas de reprodução sem um carregador e corrigir falhas relacionadas com este problema #2724, TeamNewPipe/NewPipeExtractor#219 -- Habilitação de TLS1.1/1.2 em dispositivos Android 4.4 (API 19/KitKat) para corrigir o aperto de mão de TLS com MediaCCC e algumas instâncias PeerTube #2792 -- [SoundCloud] Equipa fixa de extracção client_idNewPipe/NewPipeExtractor#217 -- Fixar a extracção do fluxo de áudio +Fixed +• Fixed a bug that could not move the popup player if another finger was placed while moving the popup player #2772 +• Allow playlists missing an uploader and fix crashes related to this problem #2724, TeamNewPipe/NewPipeExtractor#219 +• Enabling TLS1.1/1.2 on Android 4.4 devices (API 19/KitKat) to fix TLS handshake with MediaCCC and some PeerTube instances #2792 +• [SoundCloud] Fixed client_id extraction TeamNewPipe/NewPipeExtractor#217 +• [SoundCloud] Fix audio stream extraction -Desenvolvimento -- Atualizar ExoPlayer para 2.10.8 #2791, #2816 -- Atualizar o Gradle para 3.5.1 e adicionar o suporte Kotlin #2714 +Development +• Update ExoPlayer to 2.10.8 #2791, #2816 +• Update Gradle to 3.5.1 and add Kotlin support #2714 diff --git a/fastlane/metadata/android/pt-BR/changelogs/810.txt b/fastlane/metadata/android/pt-BR/changelogs/810.txt index 3cb60e434..c75855fd1 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/810.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/810.txt @@ -1,19 +1,19 @@ -Novo -- Mostrar a miniatura do vídeo no ecrã de bloqueio ao tocar em fundo +New +• Show video thumbnail on the lock screen when playing in the background -Melhorado -- Adicionar lista de reprodução local à fila de espera ao premir durante muito tempo no botão de fundo / popup -- Faça com que os separadores da página principal possam ser deslocados e escondidos quando só existe um único separador -- Quantidade limite de actualizações de miniaturas de notificação no leitor de fundo -- Adicionar miniatura de miniatura para listas de reprodução locais vazias -- Use a extensão de ficheiro *.opus em vez de *.webm e mostre "opus" na etiqueta de formato em vez de "WebM Opus" no menu pendente de download -- Adicionar botão para apagar ficheiros descarregados ou histórico de descarregamentos em "Downloads -- [YouTube] Adicionar suporte a /c/shortened_url channel links +Improved +• Add local playlist to queue when long pressing on background / popup button +• Make main page tabs scrollable and hide when there is only a single tab +• Limit amount of notification thumbnail updates in background player +• Add dummy thumbnail for empty local playlists +• Use *.opus file extension instead of *.webm and show "opus" in format label instead of "WebM Opus" in the download dropdown +• Add button to delete downloaded files or download history in "Downloads" +• [YouTube] Add support to /c/shortened_url channel links -Fixa -- Corrigido múltiplos problemas ao partilhar um vídeo para NewPipe e descarregar diretamente os seus fluxos -- Acesso fixo do jogador fora do seu fio de criação -- Paginação fixa de resultados de pesquisa -- Ligar nulo fixo causando NPE -- [YouTube] Comentários de visualização fixos ao abrir uma url invidio.us -- ClientCloud] Client_id actualizado +Fixed +• Fixed multiple issues when sharing a video to NewPipe and downloading its streams directly +• Fixed player access out of its creation thread +• Fixed search result paging +• [YouTube] Fixed switching on null causing NPE +• [YouTube] Fixed viewing comments when opening an invidio.us url +• [SoundCloud] Updated client_id diff --git a/fastlane/metadata/android/pt-BR/changelogs/840.txt b/fastlane/metadata/android/pt-BR/changelogs/840.txt index 4ee1d8ab3..95dc80844 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/840.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/840.txt @@ -1,22 +1,22 @@ -Novo -- Adicionado o seletor de língua para alterar a língua da aplicação -- Adicionado enviar para o botão Kodi ao menu desmontável do leitor -- Capacidade adicional de copiar comentários sobre imprensa longa +New +• Added language selector to change the app language +• Added send to Kodi button to player collapsible menu +• Added ability to copy comments on long press -Melhorado -- Fixar a actividade ReCaptcha e guardar corretamente os cookies obtidos -- Removido o ponto-menu a favor da gaveta e botão esconder histórico quando o histórico do relógio não está ativado nas definições -- Pedir permissão de visualização sobre outras aplicações em definições corretamente no Android 6 e posteriores -- Renomear playlist local através de um clique longo em BookmarkFragment -- Vários melhoramentos do PeerTube -- Melhorou várias cadeias de caracteres em inglês +Improved +• Fix ReCaptcha activity and correctly save obtained cookies +• Removed dot-menu in favour of drawer and hide history button when watch history is not enabled in settings +• Ask for display over other apps permission in settings correctly on Android 6 and later +• Rename local playlist by long-clicking in BookmarkFragment +• Various PeerTube improvements +• Improved several English source strings -Fixa -- Jogador fixo a recomeçar, embora seja pausado quando a opção "minimizar no comutador da aplicação" é ativada e o NewPipe é minimizado -- Fixar o valor de brilho inicial para o gesto -- Downloads de subtítulos .srt fixos contendo nem todas as quebras de linha -- Corrigido o download para cartão SD falhando porque alguns dispositivos Android 5 não são compatíveis com CTF -- Descarregamento fixo no Android KitKat -- Ficheiro fixo de vídeo corrupto .mp4 sendo reconhecido como ficheiro de áudio -- Resolvidos problemas de localização múltipla, incluindo códigos de língua chinesa errados -- Os carimbos temporais em descrição podem ser clicados novamente +Fixed +• Fixed player starting again although it is paused when option "minimize on app switch" enabled and NewPipe is minimized +• Fix initial brightness value for gesture +• Fixed .srt subtitle downloads containing not all line breaks +• Fixed download to SD card failing because some Android 5 devices are not CTF compliant +• Fixed downloading on Android KitKat +• Fixed corrupt video .mp4 file being recognized as audio file +• Fixed multiple localization problems, including wrong Chinese language codes +• [YouTube] Timestamps in description are clickable again diff --git a/fastlane/metadata/android/pt-BR/changelogs/850.txt b/fastlane/metadata/android/pt-BR/changelogs/850.txt index d5e7f5dba..b3219d7cc 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/850.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/850.txt @@ -1 +1 @@ -Neste lançamento, a versão do site do YouTube FOI foi atualizada. A versão Antiga do site será interrompida EM março, portanto, é obrigado a atualizar o NewPipe. +Nesta atualização, a versão do site do YouTube foi atualizada. A versão antiga do site será descontinuada em março e, portanto, você deverá atualizar o NewPipe. diff --git a/fastlane/metadata/android/pt-BR/changelogs/930.txt b/fastlane/metadata/android/pt-BR/changelogs/930.txt index 1ded9e887..b23b01ea8 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/930.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/930.txt @@ -1,19 +1,19 @@ -Novo -- Pesquisa no YouTube Música -- Suporte básico de TV Android +New +• Search on YouTube Music +• Basic Android TV support -Melhorado -- Adicionada a capacidade de remover todos os vídeos vistos de uma lista de reprodução local -- Mostrar mensagem quando o conteúdo ainda não é suportado, em vez de se chocar -- Reprodutor popup melhorado redimensionado com gestos de beliscão -- Enqueue streams em fundo e botões de popup no canal -- Melhor manuseamento do tamanho do título do cabeçalho da gaveta +Improved +• Added the ability to remove all watched videos from a local playlist +• Show message when content isn't supported yet instead of crashing +• Improved popup player resize with pinch gestures +• Enqueue streams on long press on background and popup buttons in channel +• Improved size handling of the drawer header title -Fixa -- Definição de conteúdo com restrição de idade fixa não funciona -- Fixação de certos tipos de reCAPTCHAs -- Corrigido o crash ao abrir marcadores enquanto a lista de reprodução é "nula". -- Deteção fixa de exceções relacionadas com a rede -- Visibilidade fixa do botão de ordenação do grupo no fragmento de subscrições +Fixed +• Fixed age restricted content setting not working +• Fixed certain kinds of reCAPTCHAs +• Fixed crash when opening bookmarks while playlist is `null` +• Fixed detection of network related exceptions +• Fixed visibility of group sort button in the subscriptions fragment -e mais +and more diff --git a/fastlane/metadata/android/pt-BR/changelogs/954.txt b/fastlane/metadata/android/pt-BR/changelogs/954.txt index cd131c162..0ba384b57 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/954.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/954.txt @@ -1,7 +1,7 @@ -• Novo recurso: veja vídeos na página de detalhes, deslize para baixo para minimizar o vídeo -• Notificações MediaStyle: ações personalizáveis em notificações, melhorias de desempenho -• redimensionamento básico ao usar NewPipe como aplicativo de computador -• diálogo com opções abertas se URL não for suportado -• Melhor experiência de sugestão de pesquisa quando não pode ser buscada +• Novidade: toque mídia na página de detalhes e deslize para baixo para minimizar o reprodutor. +• Notificações de mídia: ações personalizáveis nas e melhorias de desempenho +• Redimensionar ao usar o NewPipe como aplicativo de computador +• Diálogo com opções extras se a URL não for suportada +• Melhor experiência de sugestão de pesquisa quando ocorrer erro de interpretação do servidor • Maior qualidade do vídeo padrão para 720p60 no reprodutor interno e 480p no Pop-up -• correções de falhas e mais (?) +• Correções de falhas etc diff --git a/fastlane/metadata/android/pt-BR/changelogs/964.txt b/fastlane/metadata/android/pt-BR/changelogs/964.txt index f27426074..1238eb876 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/964.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/964.txt @@ -1,8 +1,8 @@ -• Suporte para capítulos adicionado nos controles do player -• [PeerTube] Busca Sépia adicionada -• Botão de compartilhamento adicionado novamente na visualização de detalhes do vídeo e descrição da transmissão movida para o layout de abas -• Desativação da restauração do brilho se o gesto de brilho estiver desativado -• Item de lista adicionado para reproduzir vídeo no Kodi -• Travamento corrigido quando nenhum navegador padrão está definido em alguns dispositivos e diálogos de compartilhamento aprimorados -• Alternar reprodução/pausa com o botão de espaço físico no player em tela cheia -• [media.ccc.de] Diversas correções e melhorias +• Added support for chapters in player controls +• [PeerTube] Added Sepia search +• Re-added share button in video detail view and moved stream description into the tab layout +• Disable restoring brightness if brightness gesture is disabled +• Added list item to play video on kodi +• Fixed crash when no default browser is set on some devices and improve share dialogs +• Toggle play/pause with hardware space button in fullscreen player +• [media.ccc.de] Various fixes and improvements diff --git a/fastlane/metadata/android/pt-BR/changelogs/966.txt b/fastlane/metadata/android/pt-BR/changelogs/966.txt index 13722dc34..b7fdc182f 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/966.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/966.txt @@ -1,14 +1,14 @@ -Novo: -- Acrescentado um novo serviço: Bandcamp +New: +• Add a new service: Bandcamp -Melhorado: -- Adicionada uma opção para que a aplicação siga o tema do dispositivo -- Previne alguns travamentos mostrando um painel de erros melhorado -- Mostra mais informações sobre as causas da indisponibilidade do conteúdo -- A tecla de espaço de hardware ativa play/pausa -- Mostra "Download iniciado" +Improved: +• Add an option to have the app follow the device theme +• Prevent some crashes by showing an improved error panel +• Show more information on why content in unavailable +• Hardware space button triggers play/pause +• Show "Download started" toast -Resolvido: -- Miniaturas muito pequenas em detalhes de vídeo enquanto se reproduz em fundo -- Corrige título vazio em tocador minimizado -- O último modo de redimensionamento do tamanho não estava sendo restaurado corretamente +Fixed: +• Fix very small thumbnail in video details while playing in the background +• Fix empty title in minimized player +• Fix last resize mode not being restored correctly diff --git a/fastlane/metadata/android/pt-BR/changelogs/968.txt b/fastlane/metadata/android/pt-BR/changelogs/968.txt new file mode 100644 index 000000000..0e2026fad --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/968.txt @@ -0,0 +1,9 @@ +# Melhorias +* Detalhes do canal adicionados ao menu de toque longo. +* Agora é possível renomear playlists diretamente pela interface. +* Permite pausar o vídeo mesmo durante o carregamento (buffering). +* Refinamentos e polimento no tema claro. +# Correções +* Correção de fontes sobrepostas ao usar tamanhos de letra maiores. +* Correção da ausência de vídeo nos aparelhos Formuler e Zephier. +* Correção de diversos erros de fechamento (crashes). diff --git a/fastlane/metadata/android/pt-BR/changelogs/969.txt b/fastlane/metadata/android/pt-BR/changelogs/969.txt new file mode 100644 index 000000000..ab881f8d3 --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/969.txt @@ -0,0 +1,10 @@ +# Melhorias +Instalação em armazenamento externo (SD). +[Bandcamp] Exibe os 3 primeiros comentários. +Aviso de download aparece apenas ao iniciar. +Sem cookies reCaptcha desnecessários. +[Player] Melhor cache e fluidez. +Correções +[Player] Início automático corrigido. +Fecha avisos antigos ao excluir downloads. +Erro ao excluir item inexistente corrigido. diff --git a/fastlane/metadata/android/pt-BR/changelogs/971.txt b/fastlane/metadata/android/pt-BR/changelogs/971.txt new file mode 100644 index 000000000..6683d26ec --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/971.txt @@ -0,0 +1,3 @@ +Correção rápida +• Aumentado o buffer para reprodução após rebuffer +• Corrigido travamento em tablets e TVs ao clicar no ícone da fila de reprodução no player diff --git a/fastlane/metadata/android/pt-BR/changelogs/973.txt b/fastlane/metadata/android/pt-BR/changelogs/973.txt new file mode 100644 index 000000000..7c052c5e0 --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/973.txt @@ -0,0 +1,4 @@ +Correção rápida +• Corrigidos miniaturas e títulos sendo cortados no layout em grade, devido a um cálculo errado de quantos vídeos cabem em uma linha +• Corrigido diálogo de download desaparecendo sem fazer nada se aberto pelo menu de compartilhamento +• Atualizada uma biblioteca relacionada à abertura de atividades externas, como o seletor de arquivos do Storage Access Framework diff --git a/fastlane/metadata/android/pt-BR/changelogs/974.txt b/fastlane/metadata/android/pt-BR/changelogs/974.txt new file mode 100644 index 000000000..a5c24f0cc --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/974.txt @@ -0,0 +1,5 @@ +Correção rápida +• Corrigidos problemas de buffer causados pelo throttling do YouTube +• Corrigida extração de comentários do YouTube e travamentos com comentários desativados +• Corrigida a busca de músicas no YouTube +• Corrigidas transmissões ao vivo no PeerTube diff --git a/fastlane/metadata/android/pt-BR/changelogs/976.txt b/fastlane/metadata/android/pt-BR/changelogs/976.txt new file mode 100644 index 000000000..8560f3f1a --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/976.txt @@ -0,0 +1,9 @@ +• Foi adicionada a opção de abrir o reprodutor em tela cheia sem clicar novamente. +• Você pode escolher quais sugestões de pesquisa exibir. +• Tema escuro e tela de abertura com preto AMOLED. +• Arquivos incompatíveis aparecem como cinza. +• Importação de inscrições do YouTube corrigida. +• O botão de repetir o vídeo exige apenas um toque. +• Sessão de áudio fecha corretamente. +• [Android TV] Saltos na barra de pesquisa pelo controle remoto corrigidos. +Confira as alterações na aba de links abaixo. diff --git a/fastlane/metadata/android/pt-BR/changelogs/995.txt b/fastlane/metadata/android/pt-BR/changelogs/995.txt index 943b842b0..45f55c2ff 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/995.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/995.txt @@ -1,14 +1,16 @@ -Novidades -• Suporta abas de canal -• Seleção da qualidade da imagem -• Obtém os URL para todas as imagens +New +• Support channel tabs +• Select image quality +• Get URLs to all images -Melhorias -• Acessibilidade das interfaces do reprodutor -• Pode adicionar nome da lista de reprodução e de vídeo para compartilhamento do conteúdo -• Melhorias internas (?) e atualizações de dependências +Improved +• Accessibility of player interfaces +• Better audio selection for video-only downloads +• Option to include playlist and video names to shared playlist content -Corrigido -• Seleção de idiomas errados ao selecionar -• O foco do áudio do reprodutor não respeitava o mudo -• Adicionar itens para listas de reprodução não funcionava em casos específicos +Fixed +• [YouTube] Fix getting like count +• Fix player not responding popups and crashes +• Selection of wrong languages in language picker +• Player audio focus was not respecting mute +• Playlist item addition occasionally not working diff --git a/fastlane/metadata/android/pt-BR/changelogs/998.txt b/fastlane/metadata/android/pt-BR/changelogs/998.txt index 59fc6a5cd..65e30eb45 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/998.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/998.txt @@ -1 +1,4 @@ -Corrigido YouTube não reproduzir qualquer transmissão +Corrigido o YouTube por não reproduzir nenhum vídeo devido a erros HTTP 403. + +Erros HTTP 403 ocasionais no meio de um vídeo do YouTube ainda não foram corrigidos. +Esse problema será resolvido em outra versão de hotfix assim que possível. diff --git a/fastlane/metadata/android/pt-BR/changelogs/999.txt b/fastlane/metadata/android/pt-BR/changelogs/999.txt index 59fc6a5cd..b2dac8187 100644 --- a/fastlane/metadata/android/pt-BR/changelogs/999.txt +++ b/fastlane/metadata/android/pt-BR/changelogs/999.txt @@ -1 +1,12 @@ -Corrigido YouTube não reproduzir qualquer transmissão +Esta versão de correção corrige erros HTTP 403 no meio dos vídeos do YouTube. + +Novo +• [SoundCloud] Adicionado suporte para URLs on.soundcloud.com + +Melhorado +• [Bandcamp] Exibição de informações adicionais no quiosque de rádio + +Corrigido +• [YouTube] Correção de erros HTTP 403 ocasionais no início ou no meio dos vídeos +• [YouTube] Extração de avatar e banner de mais tipos de cabeçalhos de canal +• [Bandcamp] Correção de vários bugs e uso exclusivo de HTTPS diff --git a/fastlane/metadata/android/zh-Hans/changelogs/972.txt b/fastlane/metadata/android/zh-Hans/changelogs/972.txt index b7c28ef83..90cb87149 100644 --- a/fastlane/metadata/android/zh-Hans/changelogs/972.txt +++ b/fastlane/metadata/android/zh-Hans/changelogs/972.txt @@ -1,12 +1,14 @@ 新增 在简介文本中识别时间戳和井号标签 增加手动开启平板模式的设置选项 -允许在订阅中隐藏已播放项目 +允许在订阅源中隐藏已播放项目 + 改进 正确支持存储访问框架 (SAF) 改进不可用和已删号的频道的错误处理 对于Android 10+用户的分享页面现在支持显示内容标题 更新 Invidious 实例 (instances) 并支持 Piped 链接 + 修复 [YouTube]年龄限制内容 打开选择对话框时防止窗口内存泄露异常 From 5b009453f21d3d5d29e8f4a0d6f43b880bc4d5ea Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Wed, 4 Feb 2026 16:36:12 +0800 Subject: [PATCH 35/56] Address non-final resource IDs warnings Signed-off-by: Aayush Gupta --- .../java/org/schabi/newpipe/MainActivity.java | 34 +-- .../org/schabi/newpipe/QueueItemMenuUtil.java | 86 +++--- .../newpipe/download/DownloadDialog.java | 260 ++++++++---------- .../list/channel/ChannelFragment.java | 51 ++-- .../list/playlist/PlaylistFragment.java | 53 ++-- .../newpipe/player/PlayQueueActivity.java | 64 ++--- .../giga/ui/adapter/MissionAdapter.java | 170 ++++++------ .../giga/ui/fragment/MissionsFragment.java | 33 +-- gradle.properties | 1 - 9 files changed, 357 insertions(+), 395 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 8dac39682..3c0018d99 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -309,25 +309,21 @@ public class MainActivity extends AppCompatActivity { } private boolean drawerItemSelected(final MenuItem item) { - switch (item.getGroupId()) { - case R.id.menu_services_group: - changeService(item); - break; - case R.id.menu_tabs_group: - tabSelected(item); - break; - case R.id.menu_kiosks_group: - try { - kioskSelected(item); - } catch (final Exception e) { - ErrorUtil.showUiErrorSnackbar(this, "Selecting drawer kiosk", e); - } - break; - case R.id.menu_options_about_group: - optionsAboutSelected(item); - break; - default: - return false; + final int groupId = item.getGroupId(); + if (groupId == R.id.menu_services_group) { + changeService(item); + } else if (groupId == R.id.menu_tabs_group) { + tabSelected(item); + } else if (groupId == R.id.menu_kiosks_group) { + try { + kioskSelected(item); + } catch (final Exception e) { + ErrorUtil.showUiErrorSnackbar(this, "Selecting drawer kiosk", e); + } + } else if (groupId == R.id.menu_options_about_group) { + optionsAboutSelected(item); + } else { + return false; } mainBinding.getRoot().closeDrawers(); diff --git a/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java b/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java index e6177f6a3..3eeb912c8 100644 --- a/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java +++ b/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java @@ -41,50 +41,50 @@ public final class QueueItemMenuUtil { } popupMenu.setOnMenuItemClickListener(menuItem -> { - switch (menuItem.getItemId()) { - case R.id.menu_item_remove: - final int index = playQueue.indexOf(item); - playQueue.remove(index); - return true; - case R.id.menu_item_details: - // playQueue is null since we don't want any queue change - NavigationHelper.openVideoDetail(context, item.getServiceId(), - item.getUrl(), item.getTitle(), null, - false); - return true; - case R.id.menu_item_append_playlist: - PlaylistDialog.createCorrespondingDialog( - context, - List.of(new StreamEntity(item)), - dialog -> dialog.show( - fragmentManager, - "QueueItemMenuUtil@append_playlist" - ) - ); + final int itemId = menuItem.getItemId(); + if (itemId == R.id.menu_item_remove) { + final int index = playQueue.indexOf(item); + playQueue.remove(index); + return true; + } else if (itemId == R.id.menu_item_details) { + // playQueue is null since we don't want any queue change + NavigationHelper.openVideoDetail(context, item.getServiceId(), + item.getUrl(), item.getTitle(), null, + false); + return true; + } else if (itemId == R.id.menu_item_append_playlist) { + PlaylistDialog.createCorrespondingDialog( + context, + List.of(new StreamEntity(item)), + dialog -> dialog.show( + fragmentManager, + "QueueItemMenuUtil@append_playlist" + ) + ); - return true; - case R.id.menu_item_channel_details: - SparseItemUtil.fetchUploaderUrlIfSparse(context, item.getServiceId(), - item.getUrl(), item.getUploaderUrl(), - // An intent must be used here. - // Opening with FragmentManager transactions is not working, - // as PlayQueueActivity doesn't use fragments. - uploaderUrl -> NavigationHelper.openChannelFragmentUsingIntent( - context, item.getServiceId(), uploaderUrl, item.getUploader() - )); - return true; - case R.id.menu_item_share: - shareText(context, item.getTitle(), item.getUrl(), - item.getThumbnails()); - return true; - case R.id.menu_item_download: - fetchStreamInfoAndSaveToDatabase(context, item.getServiceId(), item.getUrl(), - info -> { - final DownloadDialog downloadDialog = new DownloadDialog(context, - info); - downloadDialog.show(fragmentManager, "downloadDialog"); - }); - return true; + return true; + } else if (itemId == R.id.menu_item_channel_details) { + SparseItemUtil.fetchUploaderUrlIfSparse(context, item.getServiceId(), + item.getUrl(), item.getUploaderUrl(), + // An intent must be used here. + // Opening with FragmentManager transactions is not working, + // as PlayQueueActivity doesn't use fragments. + uploaderUrl -> NavigationHelper.openChannelFragmentUsingIntent( + context, item.getServiceId(), uploaderUrl, item.getUploader() + )); + return true; + } else if (itemId == R.id.menu_item_share) { + shareText(context, item.getTitle(), item.getUrl(), + item.getThumbnails()); + return true; + } else if (itemId == R.id.menu_item_download) { + fetchStreamInfoAndSaveToDatabase(context, item.getServiceId(), item.getUrl(), + info -> { + final DownloadDialog downloadDialog = new DownloadDialog(context, + info); + downloadDialog.show(fragmentManager, "downloadDialog"); + }); + return true; } return false; }); 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 741bda246..d7cd75054 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java @@ -558,17 +558,13 @@ public class DownloadDialog extends DialogFragment } boolean flag = true; - switch (checkedId) { - case R.id.audio_button: - setupAudioSpinner(); - break; - case R.id.video_button: - setupVideoSpinner(); - break; - case R.id.subtitle_button: - setupSubtitleSpinner(); - flag = false; - break; + if (checkedId == R.id.audio_button) { + setupAudioSpinner(); + } else if (checkedId == R.id.video_button) { + setupVideoSpinner(); + } else if (checkedId == R.id.subtitle_button) { + setupSubtitleSpinner(); + flag = false; } dialogBinding.threads.setEnabled(flag); @@ -585,29 +581,26 @@ public class DownloadDialog extends DialogFragment + "position = [" + position + "], id = [" + id + "]"); } - switch (parent.getId()) { - case R.id.quality_spinner: - switch (dialogBinding.videoAudioGroup.getCheckedRadioButtonId()) { - case R.id.video_button: - selectedVideoIndex = position; - onVideoStreamSelected(); - break; - case R.id.subtitle_button: - selectedSubtitleIndex = position; - break; - } - onItemSelectedSetFileName(); - break; - case R.id.audio_track_spinner: - final boolean trackChanged = selectedAudioTrackIndex != position; - selectedAudioTrackIndex = position; - if (trackChanged) { - updateSecondaryStreams(); - fetchStreamsSize(); - } - break; - case R.id.audio_stream_spinner: - selectedAudioIndex = position; + final int parentId = parent.getId(); + if (parentId == R.id.quality_spinner) { + final int checkedRadioButtonId = dialogBinding.videoAudioGroup + .getCheckedRadioButtonId(); + if (checkedRadioButtonId == R.id.video_button) { + selectedVideoIndex = position; + onVideoStreamSelected(); + } else if (checkedRadioButtonId == R.id.subtitle_button) { + selectedSubtitleIndex = position; + } + onItemSelectedSetFileName(); + } else if (parentId == R.id.audio_track_spinner) { + final boolean trackChanged = selectedAudioTrackIndex != position; + selectedAudioTrackIndex = position; + if (trackChanged) { + updateSecondaryStreams(); + fetchStreamsSize(); + } + } else if (parentId == R.id.audio_stream_spinner) { + selectedAudioIndex = position; } } @@ -622,23 +615,20 @@ public class DownloadDialog extends DialogFragment || prevFileName.startsWith(getString(R.string.caption_file_name, fileName, ""))) { // only update the file name field if it was not edited by the user - switch (dialogBinding.videoAudioGroup.getCheckedRadioButtonId()) { - case R.id.audio_button: - case R.id.video_button: - if (!prevFileName.equals(fileName)) { - // since the user might have switched between audio and video, the correct - // text might already be in place, so avoid resetting the cursor position - dialogBinding.fileName.setText(fileName); - } - break; - - case R.id.subtitle_button: - final String setSubtitleLanguageCode = subtitleStreamsAdapter - .getItem(selectedSubtitleIndex).getLanguageTag(); - // this will reset the cursor position, which is bad UX, but it can't be avoided - dialogBinding.fileName.setText(getString( - R.string.caption_file_name, fileName, setSubtitleLanguageCode)); - break; + final int radioButtonId = dialogBinding.videoAudioGroup + .getCheckedRadioButtonId(); + if (radioButtonId == R.id.audio_button || radioButtonId == R.id.video_button) { + if (!prevFileName.equals(fileName)) { + // since the user might have switched between audio and video, the correct + // text might already be in place, so avoid resetting the cursor position + dialogBinding.fileName.setText(fileName); + } + } else if (radioButtonId == R.id.subtitle_button) { + final String setSubtitleLanguageCode = subtitleStreamsAdapter + .getItem(selectedSubtitleIndex).getLanguageTag(); + // this will reset the cursor position, which is bad UX, but it can't be avoided + dialogBinding.fileName.setText(getString( + R.string.caption_file_name, fileName, setSubtitleLanguageCode)); } } } @@ -770,47 +760,44 @@ public class DownloadDialog extends DialogFragment filenameTmp = getNameEditText().concat("."); - switch (dialogBinding.videoAudioGroup.getCheckedRadioButtonId()) { - case R.id.audio_button: - selectedMediaType = getString(R.string.last_download_type_audio_key); - mainStorage = mainStorageAudio; - format = audioStreamsAdapter.getItem(selectedAudioIndex).getFormat(); - size = getWrappedAudioStreams().getSizeInBytes(selectedAudioIndex); - if (format == MediaFormat.WEBMA_OPUS) { - mimeTmp = "audio/ogg"; - filenameTmp += "opus"; - } else if (format != null) { - mimeTmp = format.mimeType; - filenameTmp += format.getSuffix(); - } - break; - case R.id.video_button: - selectedMediaType = getString(R.string.last_download_type_video_key); - mainStorage = mainStorageVideo; - format = videoStreamsAdapter.getItem(selectedVideoIndex).getFormat(); - size = wrappedVideoStreams.getSizeInBytes(selectedVideoIndex); - if (format != null) { - mimeTmp = format.mimeType; - filenameTmp += format.getSuffix(); - } - break; - case R.id.subtitle_button: - selectedMediaType = getString(R.string.last_download_type_subtitle_key); - mainStorage = mainStorageVideo; // subtitle & video files go together - format = subtitleStreamsAdapter.getItem(selectedSubtitleIndex).getFormat(); - size = wrappedSubtitleStreams.getSizeInBytes(selectedSubtitleIndex); - if (format != null) { - mimeTmp = format.mimeType; - } + final int checkedRadioButtonId = dialogBinding.videoAudioGroup.getCheckedRadioButtonId(); + if (checkedRadioButtonId == R.id.audio_button) { + selectedMediaType = getString(R.string.last_download_type_audio_key); + mainStorage = mainStorageAudio; + format = audioStreamsAdapter.getItem(selectedAudioIndex).getFormat(); + size = getWrappedAudioStreams().getSizeInBytes(selectedAudioIndex); + if (format == MediaFormat.WEBMA_OPUS) { + mimeTmp = "audio/ogg"; + filenameTmp += "opus"; + } else if (format != null) { + mimeTmp = format.mimeType; + filenameTmp += format.getSuffix(); + } + } else if (checkedRadioButtonId == R.id.video_button) { + selectedMediaType = getString(R.string.last_download_type_video_key); + mainStorage = mainStorageVideo; + format = videoStreamsAdapter.getItem(selectedVideoIndex).getFormat(); + size = wrappedVideoStreams.getSizeInBytes(selectedVideoIndex); + if (format != null) { + mimeTmp = format.mimeType; + filenameTmp += format.getSuffix(); + } + } else if (checkedRadioButtonId == R.id.subtitle_button) { + selectedMediaType = getString(R.string.last_download_type_subtitle_key); + mainStorage = mainStorageVideo; // subtitle & video files go together + format = subtitleStreamsAdapter.getItem(selectedSubtitleIndex).getFormat(); + size = wrappedSubtitleStreams.getSizeInBytes(selectedSubtitleIndex); + if (format != null) { + mimeTmp = format.mimeType; + } - if (format == MediaFormat.TTML) { - filenameTmp += MediaFormat.SRT.getSuffix(); - } else if (format != null) { - filenameTmp += format.getSuffix(); - } - break; - default: - throw new RuntimeException("No stream selected"); + if (format == MediaFormat.TTML) { + filenameTmp += MediaFormat.SRT.getSuffix(); + } else if (format != null) { + filenameTmp += format.getSuffix(); + } + } else { + throw new RuntimeException("No stream selected"); } if (!askForSavePath && (mainStorage == null @@ -1057,59 +1044,56 @@ public class DownloadDialog extends DialogFragment long nearLength = 0; // more download logic: select muxer, subtitle converter, etc. - switch (dialogBinding.videoAudioGroup.getCheckedRadioButtonId()) { - case R.id.audio_button: - kind = 'a'; - selectedStream = audioStreamsAdapter.getItem(selectedAudioIndex); + final int checkedRadioButtonId = dialogBinding.videoAudioGroup.getCheckedRadioButtonId(); + if (checkedRadioButtonId == R.id.audio_button) { + kind = 'a'; + selectedStream = audioStreamsAdapter.getItem(selectedAudioIndex); - if (selectedStream.getFormat() == MediaFormat.M4A) { - psName = Postprocessing.ALGORITHM_M4A_NO_DASH; - } else if (selectedStream.getFormat() == MediaFormat.WEBMA_OPUS) { - psName = Postprocessing.ALGORITHM_OGG_FROM_WEBM_DEMUXER; + if (selectedStream.getFormat() == MediaFormat.M4A) { + psName = Postprocessing.ALGORITHM_M4A_NO_DASH; + } else if (selectedStream.getFormat() == MediaFormat.WEBMA_OPUS) { + psName = Postprocessing.ALGORITHM_OGG_FROM_WEBM_DEMUXER; + } + } else if (checkedRadioButtonId == R.id.video_button) { + kind = 'v'; + selectedStream = videoStreamsAdapter.getItem(selectedVideoIndex); + + final SecondaryStreamHelper secondary = videoStreamsAdapter + .getAllSecondary() + .get(wrappedVideoStreams.getStreamsList().indexOf(selectedStream)); + + if (secondary != null) { + secondaryStream = secondary.getStream(); + + if (selectedStream.getFormat() == MediaFormat.MPEG_4) { + psName = Postprocessing.ALGORITHM_MP4_FROM_DASH_MUXER; + } else { + psName = Postprocessing.ALGORITHM_WEBM_MUXER; } - break; - case R.id.video_button: - kind = 'v'; - selectedStream = videoStreamsAdapter.getItem(selectedVideoIndex); - final SecondaryStreamHelper secondary = videoStreamsAdapter - .getAllSecondary() - .get(wrappedVideoStreams.getStreamsList().indexOf(selectedStream)); + final long videoSize = wrappedVideoStreams.getSizeInBytes( + (VideoStream) selectedStream); - if (secondary != null) { - secondaryStream = secondary.getStream(); - - if (selectedStream.getFormat() == MediaFormat.MPEG_4) { - psName = Postprocessing.ALGORITHM_MP4_FROM_DASH_MUXER; - } else { - psName = Postprocessing.ALGORITHM_WEBM_MUXER; - } - - final long videoSize = wrappedVideoStreams.getSizeInBytes( - (VideoStream) selectedStream); - - // set nearLength, only, if both sizes are fetched or known. This probably - // does not work on slow networks but is later updated in the downloader - if (secondary.getSizeInBytes() > 0 && videoSize > 0) { - nearLength = secondary.getSizeInBytes() + videoSize; - } + // set nearLength, only, if both sizes are fetched or known. This probably + // does not work on slow networks but is later updated in the downloader + if (secondary.getSizeInBytes() > 0 && videoSize > 0) { + nearLength = secondary.getSizeInBytes() + videoSize; } - break; - case R.id.subtitle_button: - threads = 1; // use unique thread for subtitles due small file size - kind = 's'; - selectedStream = subtitleStreamsAdapter.getItem(selectedSubtitleIndex); + } + } else if (checkedRadioButtonId == R.id.subtitle_button) { + threads = 1; // use unique thread for subtitles due small file size + kind = 's'; + selectedStream = subtitleStreamsAdapter.getItem(selectedSubtitleIndex); - if (selectedStream.getFormat() == MediaFormat.TTML) { - psName = Postprocessing.ALGORITHM_TTML_CONVERTER; - psArgs = new String[] { - selectedStream.getFormat().getSuffix(), - "false" // ignore empty frames - }; - } - break; - default: - return; + if (selectedStream.getFormat() == MediaFormat.TTML) { + psName = Postprocessing.ALGORITHM_TTML_CONVERTER; + psArgs = new String[]{ + selectedStream.getFormat().getSuffix(), + "false" // ignore empty frames + }; + } + } else { + return; } if (secondaryStream == null) { 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 d75d14b4a..878ceb139 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 @@ -160,34 +160,29 @@ public class ChannelFragment extends BaseStateFragment @Override public boolean onMenuItemSelected(@NonNull final MenuItem item) { - switch (item.getItemId()) { - case R.id.menu_item_notify: - final boolean value = !item.isChecked(); - item.setEnabled(false); - setNotify(value); - break; - case R.id.action_settings: - NavigationHelper.openSettings(requireContext()); - break; - case R.id.menu_item_rss: - if (currentInfo != null) { - ShareUtils.openUrlInApp(requireContext(), currentInfo.getFeedUrl()); - } - break; - case R.id.menu_item_openInBrowser: - if (currentInfo != null) { - ShareUtils.openUrlInBrowser(requireContext(), - currentInfo.getOriginalUrl()); - } - break; - case R.id.menu_item_share: - if (currentInfo != null) { - ShareUtils.shareText(requireContext(), name, - currentInfo.getOriginalUrl(), currentInfo.getAvatars()); - } - break; - default: - return false; + final int itemId = item.getItemId(); + if (itemId == R.id.menu_item_notify) { + final boolean value = !item.isChecked(); + item.setEnabled(false); + setNotify(value); + } else if (itemId == R.id.action_settings) { + NavigationHelper.openSettings(requireContext()); + } else if (itemId == R.id.menu_item_rss) { + if (currentInfo != null) { + ShareUtils.openUrlInApp(requireContext(), currentInfo.getFeedUrl()); + } + } else if (itemId == R.id.menu_item_openInBrowser) { + if (currentInfo != null) { + ShareUtils.openUrlInBrowser(requireContext(), + currentInfo.getOriginalUrl()); + } + } else if (itemId == R.id.menu_item_share) { + if (currentInfo != null) { + ShareUtils.shareText(requireContext(), name, + currentInfo.getOriginalUrl(), currentInfo.getAvatars()); + } + } else { + return false; } return true; } 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 6410fb9ee..ee6a0922c 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 @@ -232,35 +232,30 @@ public class PlaylistFragment extends BaseListInfoFragment dialog.show(getFM(), TAG) - )); - } - break; - default: - return super.onOptionsItemSelected(item); + final int itemId = item.getItemId(); + if (itemId == R.id.action_settings) { + NavigationHelper.openSettings(requireContext()); + } else if (itemId == R.id.menu_item_openInBrowser) { + ShareUtils.openUrlInBrowser(requireContext(), url); + } else if (itemId == R.id.menu_item_share) { + ShareUtils.shareText(requireContext(), name, url, + currentInfo == null ? List.of() : currentInfo.getThumbnails()); + } else if (itemId == R.id.menu_item_bookmark) { + onBookmarkClicked(); + } else if (itemId == R.id.menu_item_append_playlist) { + if (currentInfo != null) { + disposables.add(PlaylistDialog.createCorrespondingDialog( + getContext(), + getPlayQueue() + .getStreams() + .stream() + .map(StreamEntity::new) + .collect(Collectors.toList()), + dialog -> dialog.show(getFM(), TAG) + )); + } + } else { + return super.onOptionsItemSelected(item); } return true; } diff --git a/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java b/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java index 06b33f861..b6bb84ec6 100644 --- a/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java +++ b/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java @@ -127,39 +127,39 @@ public final class PlayQueueActivity extends AppCompatActivity @Override public boolean onOptionsItemSelected(final MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - finish(); - return true; - case R.id.action_settings: - NavigationHelper.openSettings(this); - return true; - case R.id.action_append_playlist: - PlaylistDialog.showForPlayQueue(player, getSupportFragmentManager()); - return true; - case R.id.action_playback_speed: - openPlaybackParameterDialog(); - return true; - case R.id.action_mute: - player.toggleMute(); - return true; - case R.id.action_system_audio: - startActivity(new Intent(Settings.ACTION_SOUND_SETTINGS)); - return true; - case R.id.action_switch_main: + final int itemId = item.getItemId(); + if (itemId == android.R.id.home) { + finish(); + return true; + } else if (itemId == R.id.action_settings) { + NavigationHelper.openSettings(this); + return true; + } else if (itemId == R.id.action_append_playlist) { + PlaylistDialog.showForPlayQueue(player, getSupportFragmentManager()); + return true; + } else if (itemId == R.id.action_playback_speed) { + openPlaybackParameterDialog(); + return true; + } else if (itemId == R.id.action_mute) { + player.toggleMute(); + return true; + } else if (itemId == R.id.action_system_audio) { + startActivity(new Intent(Settings.ACTION_SOUND_SETTINGS)); + return true; + } else if (itemId == R.id.action_switch_main) { + this.player.setRecovery(); + NavigationHelper.playOnMainPlayer(this, player.getPlayQueue(), true); + return true; + } else if (itemId == R.id.action_switch_popup) { + if (PermissionHelper.isPopupEnabledElseAsk(this)) { this.player.setRecovery(); - NavigationHelper.playOnMainPlayer(this, player.getPlayQueue(), true); - return true; - case R.id.action_switch_popup: - if (PermissionHelper.isPopupEnabledElseAsk(this)) { - this.player.setRecovery(); - NavigationHelper.playOnPopupPlayer(this, player.getPlayQueue(), true); - } - return true; - case R.id.action_switch_background: - this.player.setRecovery(); - NavigationHelper.playOnBackgroundPlayer(this, player.getPlayQueue(), true); - return true; + NavigationHelper.playOnPopupPlayer(this, player.getPlayQueue(), true); + } + return true; + } else if (itemId == R.id.action_switch_background) { + this.player.setRecovery(); + NavigationHelper.playOnBackgroundPlayer(this, player.getPlayQueue(), true); + return true; } if (item.getGroupId() == MENU_ID_AUDIO_TRACK) { 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 54ae2cfa4..45ffcb331 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 @@ -632,103 +632,95 @@ public class MissionAdapter extends Adapter implements Handler.Callb DownloadMission mission = h.item.mission instanceof DownloadMission ? (DownloadMission) h.item.mission : null; if (mission != null) { - switch (id) { - case R.id.start: - h.status.setText(UNDEFINED_PROGRESS); - mDownloadManager.resumeMission(mission); - return true; - case R.id.pause: - mDownloadManager.pauseMission(mission); - return true; - case R.id.error_message_view: - showError(mission); - return true; - case R.id.queue: - boolean flag = !h.queue.isChecked(); - h.queue.setChecked(flag); - mission.setEnqueued(flag); - updateProgress(h); - return true; - case R.id.retry: - if (mission.isPsRunning()) { - mission.psContinue(true); - } else { - mDownloadManager.tryRecover(mission); - if (mission.storage.isInvalid()) - mRecover.tryRecover(mission); - else - recoverMission(mission); - } - return true; - case R.id.cancel: - mission.psContinue(false); - return false; + if (id == R.id.start) { + h.status.setText(UNDEFINED_PROGRESS); + mDownloadManager.resumeMission(mission); + return true; + } else if (id == R.id.pause) { + mDownloadManager.pauseMission(mission); + return true; + } else if (id == R.id.error_message_view) { + showError(mission); + return true; + } else if (id == R.id.queue) { + boolean flag = !h.queue.isChecked(); + h.queue.setChecked(flag); + mission.setEnqueued(flag); + updateProgress(h); + return true; + } else if (id == R.id.retry) { + if (mission.isPsRunning()) { + mission.psContinue(true); + } else { + mDownloadManager.tryRecover(mission); + if (mission.storage.isInvalid()) + mRecover.tryRecover(mission); + else + recoverMission(mission); + } + return true; + } else if (id == R.id.cancel) { + mission.psContinue(false); + return false; } } - switch (id) { - case R.id.menu_item_share: - shareFile(h.item.mission); - return true; - case R.id.delete: - // delete the entry and the file + if (id == R.id.menu_item_share) { + shareFile(h.item.mission); + return true; + } else if (id == R.id.delete) {// delete the entry and the file + mDeleter.append(h.item.mission, true); + applyChanges(); + checkMasterButtonsVisibility(); + return true; + } else if (id == R.id.delete_entry) {// just delete the entry + mDeleter.append(h.item.mission, false); + applyChanges(); + checkMasterButtonsVisibility(); + return true; + } else if (id == R.id.md5 || id == R.id.sha1) { + final StoredFileHelper storage = h.item.mission.storage; + if (!storage.existsAsFile()) { + Toast.makeText(mContext, R.string.missing_file, Toast.LENGTH_SHORT).show(); mDeleter.append(h.item.mission, true); applyChanges(); - checkMasterButtonsVisibility(); return true; - case R.id.delete_entry: - // just delete the entry - mDeleter.append(h.item.mission, false); - applyChanges(); - checkMasterButtonsVisibility(); - return true; - case R.id.md5: - case R.id.sha1: - final StoredFileHelper storage = h.item.mission.storage; - if (!storage.existsAsFile()) { - Toast.makeText(mContext, R.string.missing_file, Toast.LENGTH_SHORT).show(); - mDeleter.append(h.item.mission, true); - applyChanges(); - return true; - } - final NotificationManager notificationManager - = ContextCompat.getSystemService(mContext, NotificationManager.class); - final NotificationCompat.Builder progressNotificationBuilder - = new NotificationCompat.Builder(mContext, - mContext.getString(R.string.hash_channel_id)) - .setPriority(NotificationCompat.PRIORITY_HIGH) - .setSmallIcon(R.drawable.ic_newpipe_triangle_white) - .setContentTitle(mContext.getString(R.string.msg_calculating_hash)) - .setContentText(mContext.getString(R.string.msg_wait)) - .setProgress(0, 0, true) - .setOngoing(true); + } + final NotificationManager notificationManager + = ContextCompat.getSystemService(mContext, NotificationManager.class); + final NotificationCompat.Builder progressNotificationBuilder + = new NotificationCompat.Builder(mContext, + mContext.getString(R.string.hash_channel_id)) + .setPriority(NotificationCompat.PRIORITY_HIGH) + .setSmallIcon(R.drawable.ic_newpipe_triangle_white) + .setContentTitle(mContext.getString(R.string.msg_calculating_hash)) + .setContentText(mContext.getString(R.string.msg_wait)) + .setProgress(0, 0, true) + .setOngoing(true); - notificationManager.notify(HASH_NOTIFICATION_ID, progressNotificationBuilder - .build()); - compositeDisposable.add( - Observable.fromCallable(() -> Utility.checksum(storage, id)) - .subscribeOn(Schedulers.computation()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(result -> { - ShareUtils.copyToClipboard(mContext, result); - notificationManager.cancel(HASH_NOTIFICATION_ID); - }) - ); - return true; - case R.id.source: - /*Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(h.item.mission.source)); - mContext.startActivity(intent);*/ - try { - Intent intent = NavigationHelper.getIntentByLink(mContext, h.item.mission.source); - intent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); - mContext.startActivity(intent); - } catch (Exception e) { - Log.w(TAG, "Selected item has a invalid source", e); - } - return true; - default: - return false; + notificationManager.notify(HASH_NOTIFICATION_ID, progressNotificationBuilder + .build()); + compositeDisposable.add( + Observable.fromCallable(() -> Utility.checksum(storage, id)) + .subscribeOn(Schedulers.computation()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(result -> { + ShareUtils.copyToClipboard(mContext, result); + notificationManager.cancel(HASH_NOTIFICATION_ID); + }) + ); + return true; + } else if (id == R.id.source) { + try { + Intent intent = NavigationHelper.getIntentByLink(mContext, h.item.mission.source); + intent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); + mContext.startActivity(intent); + } catch (Exception e) { + Log.w(TAG, "Selected item has a invalid source", e); + } + return true; } + return false; } public void applyChanges() { 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 690ed4a97..ddd9ba426 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 @@ -186,23 +186,24 @@ public class MissionsFragment extends Fragment { @Override public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.switch_mode: - mLinear = !mLinear; - updateList(); - return true; - case R.id.clear_list: - showClearDownloadHistoryPrompt(); - return true; - case R.id.start_downloads: - mBinder.getDownloadManager().startAllMissions(); - return true; - case R.id.pause_downloads: - mBinder.getDownloadManager().pauseAllMissions(false); - mAdapter.refreshMissionItems();// update items view - default: - return super.onOptionsItemSelected(item); + int itemId = item.getItemId(); + if (itemId == R.id.switch_mode) { + mLinear = !mLinear; + updateList(); + return true; + } else if (itemId == R.id.clear_list) { + showClearDownloadHistoryPrompt(); + return true; + } else if (itemId == R.id.start_downloads) { + mBinder.getDownloadManager().startAllMissions(); + return true; + } else if (itemId == R.id.pause_downloads) { + mBinder.getDownloadManager().pauseAllMissions(false); + mAdapter.refreshMissionItems();// update items view + + return super.onOptionsItemSelected(item); } + return super.onOptionsItemSelected(item); } public void showClearDownloadHistoryPrompt() { diff --git a/gradle.properties b/gradle.properties index a529a42c8..1a8297ddf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,3 @@ -android.nonFinalResIds=false android.useAndroidX=true org.gradle.jvmargs=-Xmx2048M --add-opens jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED systemProp.file.encoding=utf-8 From 8c016c95d296b778d64d6ab4e4f54bdf30e364c6 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Wed, 4 Feb 2026 16:39:30 +0800 Subject: [PATCH 36/56] Enable resources shrinking AGP 9.0.0 has introduced additional resource shrinking tasks. Its better to enable and fix this. Signed-off-by: Aayush Gupta --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index af0a5171b..e2fa9dfdb 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -79,7 +79,7 @@ configure { resValue("string", "app_name", "NewPipe $suffix") } isMinifyEnabled = true - isShrinkResources = false // disabled to fix F-Droid"s reproducible build + isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" From 89cb87b2a9b9f08a7224b550759e3981a4b7bc94 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Wed, 4 Feb 2026 16:46:36 +0800 Subject: [PATCH 37/56] Introduce lint configuration and enable checks Supress missing translation errors as they are done by volunteers Signed-off-by: Aayush Gupta --- app/build.gradle.kts | 8 ++------ app/lint.xml | 8 ++++++++ 2 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 app/lint.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e2fa9dfdb..e72fcfcfc 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -88,13 +88,9 @@ configure { } lint { - checkReleaseBuilds = false - // Or, if you prefer, you can continue to check for errors in release builds, - // but continue the build even when errors are found: + lintConfig = file("lint.xml") + // Continue the debug build even when errors are found abortOnError = false - // suppress false warning ("Resource IDs will be non-final in Android Gradle Plugin version - // 5.0, avoid using them in switch case statements"), which affects only library projects - disable += "NonConstantResourceId" } compileOptions { diff --git a/app/lint.xml b/app/lint.xml new file mode 100644 index 000000000..d07ece5ea --- /dev/null +++ b/app/lint.xml @@ -0,0 +1,8 @@ + + + + + From 582f852e7adcdecc2d493e05f943b01dd5941b65 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Thu, 5 Feb 2026 12:56:37 +0800 Subject: [PATCH 38/56] Add missing permission checks for notifications Notifications can be disabled manually even after permission has been granted once. Always check if they are enabled before notifying the user. Signed-off-by: Aayush Gupta --- .../org/schabi/newpipe/NewVersionWorker.kt | 4 +++- .../org/schabi/newpipe/error/ErrorUtil.kt | 7 +++++-- .../feed/notifications/NotificationHelper.kt | 21 ++++++++++++------- .../local/feed/service/FeedLoadService.kt | 4 +++- .../services/BaseImportExportService.java | 9 ++++++-- .../player/notification/NotificationUtil.java | 8 +++++-- 6 files changed, 38 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/NewVersionWorker.kt b/app/src/main/java/org/schabi/newpipe/NewVersionWorker.kt index fb48d3f70..4cdcc6c69 100644 --- a/app/src/main/java/org/schabi/newpipe/NewVersionWorker.kt +++ b/app/src/main/java/org/schabi/newpipe/NewVersionWorker.kt @@ -82,7 +82,9 @@ class NewVersionWorker( ) val notificationManager = NotificationManagerCompat.from(applicationContext) - notificationManager.notify(2000, notificationBuilder.build()) + if (notificationManager.areNotificationsEnabled()) { + notificationManager.notify(2000, notificationBuilder.build()) + } } @Throws(IOException::class, ReCaptchaException::class) 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 7facb5d85..0fa302623 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt @@ -134,8 +134,11 @@ class ErrorUtil { ) ) - NotificationManagerCompat.from(context) - .notify(ERROR_REPORT_NOTIFICATION_ID, notificationBuilder.build()) + val notificationManager = NotificationManagerCompat.from(context) + if (notificationManager.areNotificationsEnabled()) { + notificationManager + .notify(ERROR_REPORT_NOTIFICATION_ID, notificationBuilder.build()) + } ContextCompat.getMainExecutor(context).execute { // since the notification is silent, also show a toast, otherwise the user is confused diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationHelper.kt b/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationHelper.kt index d2d16a755..aa03aafc5 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationHelper.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationHelper.kt @@ -92,8 +92,10 @@ class NotificationHelper(val context: Context) { // Show individual stream notifications, set channel icon only if there is actually // one showStreamNotifications(newStreams, data.serviceId, data.url, bitmap) - // Show summary notification - manager.notify(data.pseudoId, summaryBuilder.build()) + // Show summary notification if enabled + if (manager.areNotificationsEnabled()) { + manager.notify(data.pseudoId, summaryBuilder.build()) + } iconLoadingTargets.remove(this) // allow it to be garbage-collected } @@ -101,8 +103,10 @@ class NotificationHelper(val context: Context) { override fun onBitmapFailed(e: Exception, errorDrawable: Drawable) { // Show individual stream notifications showStreamNotifications(newStreams, data.serviceId, data.url, null) - // Show summary notification - manager.notify(data.pseudoId, summaryBuilder.build()) + // Show summary notification if enabled + if (manager.areNotificationsEnabled()) { + manager.notify(data.pseudoId, summaryBuilder.build()) + } iconLoadingTargets.remove(this) // allow it to be garbage-collected } @@ -124,9 +128,12 @@ class NotificationHelper(val context: Context) { channelUrl: String, channelIcon: Bitmap? ) { - for (stream in newStreams) { - val notification = createStreamNotification(stream, serviceId, channelUrl, channelIcon) - manager.notify(stream.url.hashCode(), notification) + if (manager.areNotificationsEnabled()) { + newStreams.forEach { stream -> + val notification = + createStreamNotification(stream, serviceId, channelUrl, channelIcon) + manager.notify(stream.url.hashCode(), notification) + } } } 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 48ad5df94..bd128b3bc 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 @@ -185,7 +185,9 @@ class FeedLoadService : Service() { } } - notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build()) + if (notificationManager.areNotificationsEnabled()) { + notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build()) + } } // ///////////////////////////////////////////////////////////////////////// diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/services/BaseImportExportService.java b/app/src/main/java/org/schabi/newpipe/local/subscription/services/BaseImportExportService.java index b7c11b160..850409e25 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/services/BaseImportExportService.java +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/services/BaseImportExportService.java @@ -144,7 +144,9 @@ public abstract class BaseImportExportService extends Service { notificationBuilder.setContentText(text); } - notificationManager.notify(getNotificationId(), notificationBuilder.build()); + if (notificationManager.areNotificationsEnabled()) { + notificationManager.notify(getNotificationId(), notificationBuilder.build()); + } } protected void stopService() { @@ -174,7 +176,10 @@ public abstract class BaseImportExportService extends Service { .setContentTitle(title) .setStyle(new NotificationCompat.BigTextStyle().bigText(textOrEmpty)) .setContentText(textOrEmpty); - notificationManager.notify(getNotificationId(), notificationBuilder.build()); + + if (notificationManager.areNotificationsEnabled()) { + notificationManager.notify(getNotificationId(), notificationBuilder.build()); + } } protected NotificationCompat.Builder createNotification() { diff --git a/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java b/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java index 9b9c47b0e..be98abb7a 100644 --- a/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java +++ b/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java @@ -72,7 +72,9 @@ public final class NotificationUtil { notificationBuilder = createNotification(); } updateNotification(); - notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build()); + if (notificationManager.areNotificationsEnabled()) { + notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build()); + } } public synchronized void updateThumbnail() { @@ -84,7 +86,9 @@ public final class NotificationUtil { } setLargeIcon(notificationBuilder); - notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build()); + if (notificationManager.areNotificationsEnabled()) { + notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build()); + } } } From 2f3a993f8e4549d382872a36dadf89e22575edfa Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Thu, 5 Feb 2026 12:58:14 +0800 Subject: [PATCH 39/56] ReCaptchaActivity: Supress lint error for missing super call saveCookiesAndFinish method handles back navigation Signed-off-by: Aayush Gupta --- .../main/java/org/schabi/newpipe/error/ReCaptchaActivity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/org/schabi/newpipe/error/ReCaptchaActivity.java b/app/src/main/java/org/schabi/newpipe/error/ReCaptchaActivity.java index 51a0ff1e6..811671039 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ReCaptchaActivity.java +++ b/app/src/main/java/org/schabi/newpipe/error/ReCaptchaActivity.java @@ -126,6 +126,7 @@ public class ReCaptchaActivity extends AppCompatActivity { } @Override + @SuppressLint("MissingSuperCall") // saveCookiesAndFinish method handles back navigation public void onBackPressed() { saveCookiesAndFinish(); } From deb6b4230d4b2a41aaf8e4d155a2312e9ec349ee Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Thu, 5 Feb 2026 13:03:13 +0800 Subject: [PATCH 40/56] FinishedMIssionStore: Throw exception if column is missing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ../../src/main/java/us/shandian/giga/get/sqlite/FinishedMissionStore.java:105: Value must be ≥ 0 but getColumnIndex can be -1 Signed-off-by: Aayush Gupta --- .../giga/get/sqlite/FinishedMissionStore.java | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/us/shandian/giga/get/sqlite/FinishedMissionStore.java b/app/src/main/java/us/shandian/giga/get/sqlite/FinishedMissionStore.java index 704385212..215a6553b 100644 --- a/app/src/main/java/us/shandian/giga/get/sqlite/FinishedMissionStore.java +++ b/app/src/main/java/us/shandian/giga/get/sqlite/FinishedMissionStore.java @@ -102,14 +102,23 @@ public class FinishedMissionStore extends SQLiteOpenHelper { db.beginTransaction(); while (cursor.moveToNext()) { ContentValues values = new ContentValues(); - values.put(KEY_SOURCE, cursor.getString(cursor.getColumnIndex(KEY_SOURCE))); - values.put(KEY_DONE, cursor.getString(cursor.getColumnIndex(KEY_DONE))); - values.put(KEY_TIMESTAMP, cursor.getLong(cursor.getColumnIndex(KEY_TIMESTAMP))); - values.put(KEY_KIND, cursor.getString(cursor.getColumnIndex(KEY_KIND))); + values.put( + KEY_SOURCE, + cursor.getString(cursor.getColumnIndexOrThrow(KEY_SOURCE)) + ); + values.put( + KEY_DONE, + cursor.getString(cursor.getColumnIndexOrThrow(KEY_DONE)) + ); + values.put( + KEY_TIMESTAMP, + cursor.getLong(cursor.getColumnIndexOrThrow(KEY_TIMESTAMP)) + ); + values.put(KEY_KIND, cursor.getString(cursor.getColumnIndexOrThrow(KEY_KIND))); values.put(KEY_PATH, Uri.fromFile( new File( - cursor.getString(cursor.getColumnIndex(KEY_LOCATION)), - cursor.getString(cursor.getColumnIndex(KEY_NAME)) + cursor.getString(cursor.getColumnIndexOrThrow(KEY_LOCATION)), + cursor.getString(cursor.getColumnIndexOrThrow(KEY_NAME)) ) ).toString()); @@ -141,7 +150,8 @@ public class FinishedMissionStore extends SQLiteOpenHelper { } private FinishedMission getMissionFromCursor(Cursor cursor) { - String kind = Objects.requireNonNull(cursor).getString(cursor.getColumnIndex(KEY_KIND)); + String kind = Objects.requireNonNull(cursor) + .getString(cursor.getColumnIndexOrThrow(KEY_KIND)); if (kind == null || kind.isEmpty()) kind = "?"; String path = cursor.getString(cursor.getColumnIndexOrThrow(KEY_PATH)); From b3f4cb81140638c10dda55101bfcdaf25c8702f2 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Thu, 5 Feb 2026 13:05:05 +0800 Subject: [PATCH 41/56] Use requireContext() instead of asserting non-null context Signed-off-by: Aayush Gupta --- app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt index ac076f1b8..89b89a800 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt @@ -255,7 +255,7 @@ class FeedFragment : BaseStateFragment() { viewModel.getShowFutureItemsFromPreferences() ) - AlertDialog.Builder(context!!) + AlertDialog.Builder(requireContext()) .setTitle(R.string.feed_hide_streams_title) .setMultiChoiceItems(dialogItems, checkedDialogItems) { _, which, isChecked -> checkedDialogItems[which] = isChecked From 2182ff12b7d08ad0f6b2f77310fcac6fea4409d4 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Thu, 5 Feb 2026 13:08:56 +0800 Subject: [PATCH 42/56] Use correct constant for hiding keyboard ../../src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt:509: Must be one or more of: InputMethodManager.HIDE_IMPLICIT_ONLY, InputMethodManager.HIDE_NOT_ALWAYS Signed-off-by: Aayush Gupta --- .../newpipe/local/subscription/dialog/FeedGroupDialog.kt | 4 ++-- app/src/main/java/org/schabi/newpipe/util/KeyboardUtil.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt index 7a256c166..b0ccaa3c5 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt @@ -506,7 +506,7 @@ class FeedGroupDialog : DialogFragment(), BackPressable { private fun hideKeyboardSearch() { inputMethodManager.hideSoftInputFromWindow( searchLayoutBinding.toolbarSearchEditText.windowToken, - InputMethodManager.RESULT_UNCHANGED_SHOWN + InputMethodManager.HIDE_NOT_ALWAYS ) searchLayoutBinding.toolbarSearchEditText.clearFocus() } @@ -523,7 +523,7 @@ class FeedGroupDialog : DialogFragment(), BackPressable { private fun hideKeyboard() { inputMethodManager.hideSoftInputFromWindow( feedGroupCreateBinding.groupNameInput.windowToken, - InputMethodManager.RESULT_UNCHANGED_SHOWN + InputMethodManager.HIDE_NOT_ALWAYS ) feedGroupCreateBinding.groupNameInput.clearFocus() } diff --git a/app/src/main/java/org/schabi/newpipe/util/KeyboardUtil.java b/app/src/main/java/org/schabi/newpipe/util/KeyboardUtil.java index a709dc32e..679f3e042 100644 --- a/app/src/main/java/org/schabi/newpipe/util/KeyboardUtil.java +++ b/app/src/main/java/org/schabi/newpipe/util/KeyboardUtil.java @@ -48,7 +48,7 @@ public final class KeyboardUtil { final InputMethodManager imm = ContextCompat.getSystemService(activity, InputMethodManager.class); imm.hideSoftInputFromWindow(editText.getWindowToken(), - InputMethodManager.RESULT_UNCHANGED_SHOWN); + InputMethodManager.HIDE_NOT_ALWAYS); editText.clearFocus(); } From f64e40e9584051fedc393ba5b4d069e5554c4b7b Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Thu, 5 Feb 2026 14:46:28 +0800 Subject: [PATCH 43/56] DownloadRunnableFallback: Fix error with log tag being too long Abbreviate Download -> DL Signed-off-by: Aayush Gupta --- .../java/us/shandian/giga/get/DownloadRunnableFallback.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/us/shandian/giga/get/DownloadRunnableFallback.java b/app/src/main/java/us/shandian/giga/get/DownloadRunnableFallback.java index 1d2483e79..b79ff59c3 100644 --- a/app/src/main/java/us/shandian/giga/get/DownloadRunnableFallback.java +++ b/app/src/main/java/us/shandian/giga/get/DownloadRunnableFallback.java @@ -21,7 +21,7 @@ import static us.shandian.giga.get.DownloadMission.ERROR_HTTP_FORBIDDEN; * Single-threaded fallback mode */ public class DownloadRunnableFallback extends Thread { - private static final String TAG = "DownloadRunnableFallback"; + private static final String TAG = "DLRunnableFallback"; private final DownloadMission mMission; From 3d43e52afb897812b3ebb42bb98c0e00960bac6f Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Thu, 5 Feb 2026 14:47:36 +0800 Subject: [PATCH 44/56] activity_player_queue_control: Switch to app:tint instead of android:tint ../../src/main/res/layout/activity_player_queue_control.xml:208: Must use app:tint instead of android:tint Signed-off-by: Aayush Gupta --- .../activity_player_queue_control.xml | 20 +++++++++---------- .../layout/activity_player_queue_control.xml | 10 +++++----- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/app/src/main/res/layout-land/activity_player_queue_control.xml b/app/src/main/res/layout-land/activity_player_queue_control.xml index a5df5e566..ad2655380 100644 --- a/app/src/main/res/layout-land/activity_player_queue_control.xml +++ b/app/src/main/res/layout-land/activity_player_queue_control.xml @@ -122,8 +122,8 @@ android:focusable="true" android:scaleType="fitCenter" android:src="@drawable/exo_controls_rewind" - android:tint="?attr/colorAccent" - android:contentDescription="@string/rewind" /> + android:contentDescription="@string/rewind" + app:tint="?attr/colorAccent" /> + android:contentDescription="@string/pause" + app:tint="?attr/colorAccent" /> + android:contentDescription="@string/forward" + app:tint="?attr/colorAccent" /> + android:contentDescription="@string/notification_action_repeat" + app:tint="?attr/colorAccent" /> + android:contentDescription="@string/notification_action_shuffle" + app:tint="?attr/colorAccent" /> + app:tint="?attr/colorAccent" /> + app:tint="?attr/colorAccent" /> From 10b943f37e2a5bb2e0029b857045407eb21a1371 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Thu, 5 Feb 2026 15:02:28 +0800 Subject: [PATCH 45/56] DownloadDialog: Avoid using restricted API for menuitem Signed-off-by: Aayush Gupta --- .../main/java/org/schabi/newpipe/download/DownloadDialog.java | 4 ++-- 1 file changed, 2 insertions(+), 2 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 d7cd75054..91fac7d7b 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java @@ -16,6 +16,7 @@ import android.os.IBinder; import android.provider.Settings; import android.util.Log; import android.view.LayoutInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; @@ -31,7 +32,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.StringRes; import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.view.menu.ActionMenuItemView; import androidx.appcompat.widget.Toolbar; import androidx.collection.SparseArrayCompat; import androidx.documentfile.provider.DocumentFile; @@ -113,7 +113,7 @@ public class DownloadDialog extends DialogFragment private StoredDirectoryHelper mainStorageAudio = null; private StoredDirectoryHelper mainStorageVideo = null; private DownloadManager downloadManager = null; - private ActionMenuItemView okButton = null; + private MenuItem okButton = null; private Context context = null; private boolean askForSavePath; From 15829c882ba1a4185e0b5deef5e8e5967f816be0 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Thu, 5 Feb 2026 15:24:12 +0800 Subject: [PATCH 46/56] lint: Supress more translation related errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They should be fixed by translators or weblate in general. ../../src/main/res/values-lt/strings.xml:87: For locale "lt" (Lithuanian) the following quantity should also be defined: many (e.g. "1.1 obuolio") ../../src/main/res/values-is/strings.xml:318: The quantity 'one' matches more than one specific number in this locale (1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, …), but the message did not include a formatting argument (such as %d). This is usually an internationalization error. See full issue explanation for more. Signed-off-by: Aayush Gupta --- app/lint.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/lint.xml b/app/lint.xml index d07ece5ea..9497c22ca 100644 --- a/app/lint.xml +++ b/app/lint.xml @@ -5,4 +5,6 @@ --> + + From 5eb5f7533d134d98708ad27ed17711c11aea200e Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Thu, 5 Feb 2026 15:51:29 +0800 Subject: [PATCH 47/56] ic_smart_display: Fix invalid vector path on older devices Signed-off-by: Aayush Gupta --- app/src/main/res/drawable/ic_smart_display.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/drawable/ic_smart_display.xml b/app/src/main/res/drawable/ic_smart_display.xml index d666a3b37..93d73aee5 100644 --- a/app/src/main/res/drawable/ic_smart_display.xml +++ b/app/src/main/res/drawable/ic_smart_display.xml @@ -5,6 +5,6 @@ android:viewportWidth="24" android:tint="@color/defaultIconTint"> From 653b33bdb9f3cae3bfdfb6c0b0dfa25743a03c1d Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Thu, 5 Feb 2026 16:12:09 +0800 Subject: [PATCH 48/56] FocusOverlayView: Avoid accessing restricted API Signed-off-by: Aayush Gupta --- .../newpipe/views/FocusOverlayView.java | 3 +- .../newpipe/views/SimpleWindowCallback.kt | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/views/SimpleWindowCallback.kt diff --git a/app/src/main/java/org/schabi/newpipe/views/FocusOverlayView.java b/app/src/main/java/org/schabi/newpipe/views/FocusOverlayView.java index 29c38511c..9e06211f2 100644 --- a/app/src/main/java/org/schabi/newpipe/views/FocusOverlayView.java +++ b/app/src/main/java/org/schabi/newpipe/views/FocusOverlayView.java @@ -40,7 +40,6 @@ import android.view.Window; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; -import androidx.appcompat.view.WindowCallbackWrapper; import org.schabi.newpipe.R; @@ -232,7 +231,7 @@ public final class FocusOverlayView extends Drawable implements // Unfortunately many such forms of "scrolling" do not count as scrolling for purpose // of dispatching ViewTreeObserver callbacks, so we have to intercept them by directly // receiving keys from Window. - window.setCallback(new WindowCallbackWrapper(window.getCallback()) { + window.setCallback(new SimpleWindowCallback(window.getCallback()) { @Override public boolean dispatchKeyEvent(final KeyEvent event) { final boolean res = super.dispatchKeyEvent(event); diff --git a/app/src/main/java/org/schabi/newpipe/views/SimpleWindowCallback.kt b/app/src/main/java/org/schabi/newpipe/views/SimpleWindowCallback.kt new file mode 100644 index 000000000..46f58d24c --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/views/SimpleWindowCallback.kt @@ -0,0 +1,39 @@ +/* + * SPDX-FileCopyrightText: 2026 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.views + +import android.os.Build +import android.view.KeyEvent +import android.view.KeyboardShortcutGroup +import android.view.Menu +import android.view.Window +import androidx.annotation.RequiresApi + +/** + * Simple window callback class to allow intercepting key events + * @see FocusOverlayView.setupOverlay + */ +open class SimpleWindowCallback(private val baseCallback: Window.Callback) : + Window.Callback by baseCallback { + + override fun dispatchKeyEvent(event: KeyEvent?): Boolean { + return baseCallback.dispatchKeyEvent(event) + } + + @RequiresApi(Build.VERSION_CODES.O) + override fun onPointerCaptureChanged(hasCapture: Boolean) { + baseCallback.onPointerCaptureChanged(hasCapture) + } + + @RequiresApi(Build.VERSION_CODES.N) + override fun onProvideKeyboardShortcuts( + data: List?, + menu: Menu?, + deviceId: Int + ) { + baseCallback.onProvideKeyboardShortcuts(data, menu, deviceId) + } +} From 273b09a3e87d663ac958d2e9ae418728497a9571 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Sat, 21 Feb 2026 00:06:12 +0800 Subject: [PATCH 49/56] App: Migrate from Java to Kotlin Based on changes from refactor branch for code parity Signed-off-by: Aayush Gupta --- app/src/main/java/org/schabi/newpipe/App.java | 285 ------------------ app/src/main/java/org/schabi/newpipe/App.kt | 285 ++++++++++++++++++ .../java/org/schabi/newpipe/MainActivity.java | 4 +- .../info_list/dialog/InfoItemDialog.java | 2 +- .../newpipe/local/feed/FeedViewModel.kt | 2 +- .../newpipe/player/helper/PlayerHolder.java | 2 +- .../newpipe/settings/NewPipeSettings.java | 2 +- .../settings/migration/SettingMigrations.java | 2 +- .../org/schabi/newpipe/util/DeviceUtils.java | 4 +- .../schabi/newpipe/util/PermissionHelper.java | 4 +- .../schabi/newpipe/util/ReleaseVersionUtil.kt | 2 +- .../util/potoken/PoTokenProviderImpl.kt | 2 +- 12 files changed, 298 insertions(+), 298 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/App.java create mode 100644 app/src/main/java/org/schabi/newpipe/App.kt diff --git a/app/src/main/java/org/schabi/newpipe/App.java b/app/src/main/java/org/schabi/newpipe/App.java deleted file mode 100644 index cf41aad46..000000000 --- a/app/src/main/java/org/schabi/newpipe/App.java +++ /dev/null @@ -1,285 +0,0 @@ -package org.schabi.newpipe; - -import android.app.Application; -import android.content.Context; -import android.content.SharedPreferences; -import android.util.Log; - -import androidx.annotation.NonNull; -import androidx.core.app.NotificationChannelCompat; -import androidx.core.app.NotificationManagerCompat; -import androidx.preference.PreferenceManager; - -import com.jakewharton.processphoenix.ProcessPhoenix; - -import org.acra.ACRA; -import org.acra.config.CoreConfigurationBuilder; -import org.schabi.newpipe.error.ReCaptchaActivity; -import org.schabi.newpipe.extractor.NewPipe; -import org.schabi.newpipe.extractor.downloader.Downloader; -import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor; -import org.schabi.newpipe.ktx.ExceptionUtils; -import org.schabi.newpipe.settings.NewPipeSettings; -import org.schabi.newpipe.util.BridgeStateSaverInitializer; -import org.schabi.newpipe.util.Localization; -import org.schabi.newpipe.util.ServiceHelper; -import org.schabi.newpipe.util.StateSaver; -import org.schabi.newpipe.util.image.ImageStrategy; -import org.schabi.newpipe.util.image.PicassoHelper; -import org.schabi.newpipe.util.image.PreferredImageQuality; -import org.schabi.newpipe.util.potoken.PoTokenProviderImpl; - -import java.io.IOException; -import java.io.InterruptedIOException; -import java.net.SocketException; -import java.util.List; -import java.util.Objects; - -import io.reactivex.rxjava3.exceptions.CompositeException; -import io.reactivex.rxjava3.exceptions.MissingBackpressureException; -import io.reactivex.rxjava3.exceptions.OnErrorNotImplementedException; -import io.reactivex.rxjava3.exceptions.UndeliverableException; -import io.reactivex.rxjava3.functions.Consumer; -import io.reactivex.rxjava3.plugins.RxJavaPlugins; - -/* - * Copyright (C) Hans-Christoph Steiner 2016 - * App.java is part of NewPipe. - * - * NewPipe is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * NewPipe is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with NewPipe. If not, see . - */ - -public class App extends Application { - public static final String PACKAGE_NAME = BuildConfig.APPLICATION_ID; - private static final String TAG = App.class.toString(); - - private boolean isFirstRun = false; - private boolean notificationsRequested = false; - - private static App app; - - @NonNull - public static App getApp() { - return app; - } - - public boolean getNotificationsRequested() { - return notificationsRequested; - } - - public void setNotificationsRequested() { - notificationsRequested = true; - } - - @Override - protected void attachBaseContext(final Context base) { - super.attachBaseContext(base); - initACRA(); - } - - @Override - public void onCreate() { - super.onCreate(); - - app = this; - - if (ProcessPhoenix.isPhoenixProcess(this)) { - Log.i(TAG, "This is a phoenix process! " - + "Aborting initialization of App[onCreate]"); - return; - } - - // check if the last used preference version is set - // to determine whether this is the first app run - final int lastUsedPrefVersion = PreferenceManager.getDefaultSharedPreferences(this) - .getInt(getString(R.string.last_used_preferences_version), -1); - isFirstRun = lastUsedPrefVersion == -1; - - // Initialize settings first because other initializations can use its values - NewPipeSettings.initSettings(this); - - NewPipe.init(getDownloader(), - Localization.getPreferredLocalization(this), - Localization.getPreferredContentCountry(this)); - Localization.initPrettyTime(Localization.resolvePrettyTime()); - - BridgeStateSaverInitializer.init(this); - StateSaver.init(this); - initNotificationChannels(); - - ServiceHelper.initServices(this); - - // Initialize image loader - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - PicassoHelper.init(this); - ImageStrategy.setPreferredImageQuality(PreferredImageQuality.fromPreferenceKey(this, - prefs.getString(getString(R.string.image_quality_key), - getString(R.string.image_quality_default)))); - PicassoHelper.setIndicatorsEnabled(MainActivity.DEBUG - && prefs.getBoolean(getString(R.string.show_image_indicators_key), false)); - - configureRxJavaErrorHandler(); - - YoutubeStreamExtractor.setPoTokenProvider(PoTokenProviderImpl.INSTANCE); - } - - @Override - public void onTerminate() { - super.onTerminate(); - PicassoHelper.terminate(); - } - - protected Downloader getDownloader() { - final DownloaderImpl downloader = DownloaderImpl.init(null); - setCookiesToDownloader(downloader); - return downloader; - } - - protected void setCookiesToDownloader(final DownloaderImpl downloader) { - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences( - getApplicationContext()); - final String key = getApplicationContext().getString(R.string.recaptcha_cookies_key); - downloader.setCookie(ReCaptchaActivity.RECAPTCHA_COOKIES_KEY, prefs.getString(key, null)); - downloader.updateYoutubeRestrictedModeCookies(getApplicationContext()); - } - - private void configureRxJavaErrorHandler() { - // https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling - RxJavaPlugins.setErrorHandler(new Consumer() { - @Override - public void accept(@NonNull final Throwable throwable) { - Log.e(TAG, "RxJavaPlugins.ErrorHandler called with -> : " - + "throwable = [" + throwable.getClass().getName() + "]"); - - final Throwable actualThrowable; - if (throwable instanceof UndeliverableException) { - // As UndeliverableException is a wrapper, - // get the cause of it to get the "real" exception - actualThrowable = Objects.requireNonNull(throwable.getCause()); - } else { - actualThrowable = throwable; - } - - final List errors; - if (actualThrowable instanceof CompositeException) { - errors = ((CompositeException) actualThrowable).getExceptions(); - } else { - errors = List.of(actualThrowable); - } - - for (final Throwable error : errors) { - if (isThrowableIgnored(error)) { - return; - } - if (isThrowableCritical(error)) { - reportException(error); - return; - } - } - - // Out-of-lifecycle exceptions should only be reported if a debug user wishes so, - // When exception is not reported, log it - if (isDisposedRxExceptionsReported()) { - reportException(actualThrowable); - } else { - Log.e(TAG, "RxJavaPlugin: Undeliverable Exception received: ", actualThrowable); - } - } - - private boolean isThrowableIgnored(@NonNull final Throwable throwable) { - // Don't crash the application over a simple network problem - return ExceptionUtils.hasAssignableCause(throwable, - // network api cancellation - IOException.class, SocketException.class, - // blocking code disposed - InterruptedException.class, InterruptedIOException.class); - } - - private boolean isThrowableCritical(@NonNull final Throwable throwable) { - // Though these exceptions cannot be ignored - return ExceptionUtils.hasAssignableCause(throwable, - NullPointerException.class, IllegalArgumentException.class, // bug in app - OnErrorNotImplementedException.class, MissingBackpressureException.class, - IllegalStateException.class); // bug in operator - } - - private void reportException(@NonNull final Throwable throwable) { - // Throw uncaught exception that will trigger the report system - Thread.currentThread().getUncaughtExceptionHandler() - .uncaughtException(Thread.currentThread(), throwable); - } - }); - } - - /** - * Called in {@link #attachBaseContext(Context)} after calling the {@code super} method. - * Should be overridden if MultiDex is enabled, since it has to be initialized before ACRA. - */ - protected void initACRA() { - if (ACRA.isACRASenderServiceProcess()) { - return; - } - - final CoreConfigurationBuilder acraConfig = new CoreConfigurationBuilder() - .withBuildConfigClass(BuildConfig.class); - ACRA.init(this, acraConfig); - } - - private void initNotificationChannels() { - // Keep the importance below DEFAULT to avoid making noise on every notification update for - // the main and update channels - final List notificationChannelCompats = List.of( - new NotificationChannelCompat.Builder(getString(R.string.notification_channel_id), - NotificationManagerCompat.IMPORTANCE_LOW) - .setName(getString(R.string.notification_channel_name)) - .setDescription(getString(R.string.notification_channel_description)) - .build(), - new NotificationChannelCompat - .Builder(getString(R.string.app_update_notification_channel_id), - NotificationManagerCompat.IMPORTANCE_LOW) - .setName(getString(R.string.app_update_notification_channel_name)) - .setDescription( - getString(R.string.app_update_notification_channel_description)) - .build(), - new NotificationChannelCompat.Builder(getString(R.string.hash_channel_id), - NotificationManagerCompat.IMPORTANCE_HIGH) - .setName(getString(R.string.hash_channel_name)) - .setDescription(getString(R.string.hash_channel_description)) - .build(), - 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(), - new NotificationChannelCompat - .Builder(getString(R.string.streams_notification_channel_id), - NotificationManagerCompat.IMPORTANCE_DEFAULT) - .setName(getString(R.string.streams_notification_channel_name)) - .setDescription( - getString(R.string.streams_notification_channel_description)) - .build() - ); - - final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); - notificationManager.createNotificationChannelsCompat(notificationChannelCompats); - } - - protected boolean isDisposedRxExceptionsReported() { - return false; - } - - public boolean isFirstRun() { - return isFirstRun; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/App.kt b/app/src/main/java/org/schabi/newpipe/App.kt new file mode 100644 index 000000000..ad6b82435 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/App.kt @@ -0,0 +1,285 @@ +package org.schabi.newpipe + +import android.app.Application +import android.content.Context +import android.util.Log +import androidx.core.app.NotificationChannelCompat +import androidx.core.app.NotificationManagerCompat +import androidx.preference.PreferenceManager +import com.jakewharton.processphoenix.ProcessPhoenix +import io.reactivex.rxjava3.exceptions.CompositeException +import io.reactivex.rxjava3.exceptions.MissingBackpressureException +import io.reactivex.rxjava3.exceptions.OnErrorNotImplementedException +import io.reactivex.rxjava3.exceptions.UndeliverableException +import io.reactivex.rxjava3.functions.Consumer +import io.reactivex.rxjava3.plugins.RxJavaPlugins +import java.io.IOException +import java.io.InterruptedIOException +import java.net.SocketException +import org.acra.ACRA.init +import org.acra.ACRA.isACRASenderServiceProcess +import org.acra.config.CoreConfigurationBuilder +import org.schabi.newpipe.error.ReCaptchaActivity +import org.schabi.newpipe.extractor.NewPipe +import org.schabi.newpipe.extractor.downloader.Downloader +import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor +import org.schabi.newpipe.ktx.hasAssignableCause +import org.schabi.newpipe.settings.NewPipeSettings +import org.schabi.newpipe.util.BridgeStateSaverInitializer +import org.schabi.newpipe.util.Localization +import org.schabi.newpipe.util.ServiceHelper +import org.schabi.newpipe.util.StateSaver +import org.schabi.newpipe.util.image.ImageStrategy.setPreferredImageQuality +import org.schabi.newpipe.util.image.PicassoHelper +import org.schabi.newpipe.util.image.PreferredImageQuality.Companion.fromPreferenceKey +import org.schabi.newpipe.util.potoken.PoTokenProviderImpl + +/* + * Copyright (C) Hans-Christoph Steiner 2016 + * App.kt is part of NewPipe. + * + * NewPipe is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * NewPipe is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NewPipe. If not, see . + */ +open class App : Application() { + var isFirstRun = false + private set + var notificationsRequested = false + private set + + fun setNotificationsRequested() { + notificationsRequested = true + } + + override fun attachBaseContext(base: Context?) { + super.attachBaseContext(base) + initACRA() + } + + override fun onCreate() { + super.onCreate() + + instance = this + + if (ProcessPhoenix.isPhoenixProcess(this)) { + Log.i(TAG, "This is a phoenix process! Aborting initialization of App[onCreate]") + return + } + + // check if the last used preference version is set + // to determine whether this is the first app run + val lastUsedPrefVersion = + PreferenceManager + .getDefaultSharedPreferences(this) + .getInt(getString(R.string.last_used_preferences_version), -1) + isFirstRun = lastUsedPrefVersion == -1 + + // Initialize settings first because other initializations can use its values + NewPipeSettings.initSettings(this) + + NewPipe.init( + getDownloader(), + Localization.getPreferredLocalization(this), + Localization.getPreferredContentCountry(this) + ) + Localization.initPrettyTime(Localization.resolvePrettyTime()) + + BridgeStateSaverInitializer.init(this) + StateSaver.init(this) + initNotificationChannels() + + ServiceHelper.initServices(this) + + // Initialize image loader + val prefs = PreferenceManager.getDefaultSharedPreferences(this) + PicassoHelper.init(this) + setPreferredImageQuality( + fromPreferenceKey( + this, + prefs.getString( + getString(R.string.image_quality_key), + getString(R.string.image_quality_default) + ) + ) + ) + PicassoHelper.setIndicatorsEnabled( + MainActivity.DEBUG && + prefs.getBoolean(getString(R.string.show_image_indicators_key), false) + ) + + configureRxJavaErrorHandler() + + YoutubeStreamExtractor.setPoTokenProvider(PoTokenProviderImpl) + } + + override fun onTerminate() { + super.onTerminate() + PicassoHelper.terminate() + } + + protected open fun getDownloader(): Downloader { + val downloader = DownloaderImpl.init(null) + setCookiesToDownloader(downloader) + return downloader + } + + protected fun setCookiesToDownloader(downloader: DownloaderImpl) { + val prefs = PreferenceManager.getDefaultSharedPreferences(this) + val key = getString(R.string.recaptcha_cookies_key) + downloader.setCookie(ReCaptchaActivity.RECAPTCHA_COOKIES_KEY, prefs.getString(key, null)) + downloader.updateYoutubeRestrictedModeCookies(this) + } + + private fun configureRxJavaErrorHandler() { + // https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling + RxJavaPlugins.setErrorHandler( + object : Consumer { + override fun accept(throwable: Throwable) { + Log.e(TAG, "RxJavaPlugins.ErrorHandler called with -> : throwable = [${throwable.javaClass.getName()}]") + + // As UndeliverableException is a wrapper, + // get the cause of it to get the "real" exception + val actualThrowable = (throwable as? UndeliverableException)?.cause ?: throwable + + val errors = (actualThrowable as? CompositeException)?.exceptions ?: listOf(actualThrowable) + + for (error in errors) { + if (isThrowableIgnored(error)) { + return + } + if (isThrowableCritical(error)) { + reportException(error) + return + } + } + + // Out-of-lifecycle exceptions should only be reported if a debug user wishes so, + // When exception is not reported, log it + if (isDisposedRxExceptionsReported()) { + reportException(actualThrowable) + } else { + Log.e(TAG, "RxJavaPlugin: Undeliverable Exception received: ", actualThrowable) + } + } + + fun isThrowableIgnored(throwable: Throwable): Boolean { + // Don't crash the application over a simple network problem + return throwable // network api cancellation + .hasAssignableCause( + IOException::class.java, + SocketException::class.java, // blocking code disposed + InterruptedException::class.java, + InterruptedIOException::class.java + ) + } + + fun isThrowableCritical(throwable: Throwable): Boolean { + // Though these exceptions cannot be ignored + return throwable + .hasAssignableCause( + // bug in app + NullPointerException::class.java, + IllegalArgumentException::class.java, + OnErrorNotImplementedException::class.java, + MissingBackpressureException::class.java, + // bug in operator + IllegalStateException::class.java + ) + } + + fun reportException(throwable: Throwable) { + // Throw uncaught exception that will trigger the report system + Thread + .currentThread() + .uncaughtExceptionHandler + .uncaughtException(Thread.currentThread(), throwable) + } + } + ) + } + + /** + * Called in [.attachBaseContext] after calling the `super` method. + * Should be overridden if MultiDex is enabled, since it has to be initialized before ACRA. + */ + protected fun initACRA() { + if (isACRASenderServiceProcess()) { + return + } + + val acraConfig = + CoreConfigurationBuilder() + .withBuildConfigClass(BuildConfig::class.java) + init(this, acraConfig) + } + + private fun initNotificationChannels() { + // Keep the importance below DEFAULT to avoid making noise on every notification update for + // the main and update channels + val mainChannel = + NotificationChannelCompat + .Builder( + getString(R.string.notification_channel_id), + NotificationManagerCompat.IMPORTANCE_LOW + ).setName(getString(R.string.notification_channel_name)) + .setDescription(getString(R.string.notification_channel_description)) + .build() + val appUpdateChannel = + NotificationChannelCompat + .Builder( + getString(R.string.app_update_notification_channel_id), + NotificationManagerCompat.IMPORTANCE_LOW + ).setName(getString(R.string.app_update_notification_channel_name)) + .setDescription(getString(R.string.app_update_notification_channel_description)) + .build() + val hashChannel = + NotificationChannelCompat + .Builder( + getString(R.string.hash_channel_id), + NotificationManagerCompat.IMPORTANCE_HIGH + ).setName(getString(R.string.hash_channel_name)) + .setDescription(getString(R.string.hash_channel_description)) + .build() + val errorReportChannel = + 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() + val newStreamChannel = + NotificationChannelCompat + .Builder( + getString(R.string.streams_notification_channel_id), + NotificationManagerCompat.IMPORTANCE_DEFAULT + ).setName(getString(R.string.streams_notification_channel_name)) + .setDescription(getString(R.string.streams_notification_channel_description)) + .build() + + val channels = listOf(mainChannel, appUpdateChannel, hashChannel, errorReportChannel, newStreamChannel) + + NotificationManagerCompat.from(this).createNotificationChannelsCompat(channels) + } + + protected open fun isDisposedRxExceptionsReported(): Boolean = false + + companion object { + const val PACKAGE_NAME: String = BuildConfig.APPLICATION_ID + private val TAG = App::class.java.toString() + + @JvmStatic + lateinit var instance: App + private set + } +} diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 3c0018d99..e4f4b5b8a 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -191,7 +191,7 @@ public class MainActivity extends AppCompatActivity { NotificationWorker.initialize(this); } if (!UpdateSettingsFragment.wasUserAskedForConsent(this) - && !App.getApp().isFirstRun() + && !App.getInstance().isFirstRun() && ReleaseVersionUtil.INSTANCE.isReleaseApk()) { UpdateSettingsFragment.askForConsentToUpdateChecks(this); } @@ -203,7 +203,7 @@ public class MainActivity extends AppCompatActivity { protected void onPostCreate(final Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); - final App app = App.getApp(); + final App app = App.getInstance(); if (sharedPreferences.getBoolean(app.getString(R.string.update_app_key), false) && sharedPreferences diff --git a/app/src/main/java/org/schabi/newpipe/info_list/dialog/InfoItemDialog.java b/app/src/main/java/org/schabi/newpipe/info_list/dialog/InfoItemDialog.java index 0c69557bf..dcf01e190 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/dialog/InfoItemDialog.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/dialog/InfoItemDialog.java @@ -346,7 +346,7 @@ public final class InfoItemDialog { public static void reportErrorDuringInitialization(final Throwable throwable, final InfoItem item) { - ErrorUtil.showSnackbar(App.getApp().getBaseContext(), new ErrorInfo( + ErrorUtil.showSnackbar(App.getInstance().getBaseContext(), new ErrorInfo( throwable, UserAction.OPEN_INFO_ITEM_DIALOG, "none", diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt index 58ec818f3..19adf6eaa 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt @@ -166,7 +166,7 @@ class FeedViewModel( fun getFactory(context: Context, groupId: Long) = viewModelFactory { initializer { FeedViewModel( - App.getApp(), + App.instance, groupId, // Read initial value from preferences getShowPlayedItemsFromPreferences(context.applicationContext), 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 9edfc804a..daae6d54e 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 @@ -117,7 +117,7 @@ public final class PlayerHolder { // helper to handle context in common place as using the same // context to bind/unbind a service is crucial private Context getCommonContext() { - return App.getApp(); + return App.getInstance(); } public void startService(final boolean playAfterConnect, diff --git a/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java b/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java index 7cb1564b3..3cc29afee 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java +++ b/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java @@ -157,7 +157,7 @@ public final class NewPipeSettings { prefs.getInt(disabledTunnelingAutomaticallyKey, -1) == 0 && !prefs.getBoolean(disabledTunnelingKey, false); - if (App.getApp().isFirstRun() + if (App.getInstance().isFirstRun() || (wasDeviceBlacklistUpdated && !wasMediaTunnelingEnabledByUser)) { setMediaTunneling(context); } diff --git a/app/src/main/java/org/schabi/newpipe/settings/migration/SettingMigrations.java b/app/src/main/java/org/schabi/newpipe/settings/migration/SettingMigrations.java index 67944075d..92520ec7e 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/migration/SettingMigrations.java +++ b/app/src/main/java/org/schabi/newpipe/settings/migration/SettingMigrations.java @@ -251,7 +251,7 @@ public final class SettingMigrations { final int lastPrefVersion = sp.getInt(lastPrefVersionKey, 0); // no migration to run, already up to date - if (App.getApp().isFirstRun()) { + if (App.getInstance().isFirstRun()) { sp.edit().putInt(lastPrefVersionKey, VERSION).apply(); return; } else if (lastPrefVersion == VERSION) { 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 9eb9fab37..83152a36d 100644 --- a/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java +++ b/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java @@ -131,7 +131,7 @@ public final class DeviceUtils { } isFireTV = - App.getApp().getPackageManager().hasSystemFeature(AMAZON_FEATURE_FIRE_TV); + App.getInstance().getPackageManager().hasSystemFeature(AMAZON_FEATURE_FIRE_TV); return isFireTV; } @@ -140,7 +140,7 @@ public final class DeviceUtils { return isTV; } - final PackageManager pm = App.getApp().getPackageManager(); + final PackageManager pm = App.getInstance().getPackageManager(); // from doc: https://developer.android.com/training/tv/start/hardware.html#runtime-check boolean isTv = ContextCompat.getSystemService(context, UiModeManager.class) diff --git a/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java b/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java index 969d787d7..2defbdc5b 100644 --- a/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java @@ -90,10 +90,10 @@ public final class PermissionHelper { && ContextCompat.checkSelfPermission(activity, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { - if (!App.getApp().getNotificationsRequested()) { + if (!App.getInstance().getNotificationsRequested()) { ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.POST_NOTIFICATIONS}, requestCode); - App.getApp().setNotificationsRequested(); + App.getInstance().setNotificationsRequested(); return false; } } diff --git a/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.kt b/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.kt index bc3849384..31d42d751 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.kt +++ b/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.kt @@ -21,7 +21,7 @@ object ReleaseVersionUtil { val certificates = mapOf( RELEASE_CERT_PUBLIC_KEY_SHA256.hexToByteArray() to PackageManager.CERT_INPUT_SHA256 ) - val app = App.getApp() + val app = App.instance try { PackageInfoCompat.hasSignatures(app.packageManager, app.packageName, certificates, false) } catch (e: PackageManager.NameNotFoundException) { diff --git a/app/src/main/java/org/schabi/newpipe/util/potoken/PoTokenProviderImpl.kt b/app/src/main/java/org/schabi/newpipe/util/potoken/PoTokenProviderImpl.kt index 12fadb68d..53ae04a3c 100644 --- a/app/src/main/java/org/schabi/newpipe/util/potoken/PoTokenProviderImpl.kt +++ b/app/src/main/java/org/schabi/newpipe/util/potoken/PoTokenProviderImpl.kt @@ -78,7 +78,7 @@ object PoTokenProviderImpl : PoTokenProvider { // create a new webPoTokenGenerator webPoTokenGenerator = PoTokenWebView - .newPoTokenGenerator(App.getApp()).blockingGet() + .newPoTokenGenerator(App.instance).blockingGet() // The streaming poToken needs to be generated exactly once before generating // any other (player) tokens. From 57364109f4f357e32e0669ae9b87978422322244 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Sat, 21 Feb 2026 16:38:35 +0800 Subject: [PATCH 50/56] Migrate from Picasso to Coil Based on changes from refactor Signed-off-by: Aayush Gupta --- app/build.gradle.kts | 3 +- app/src/main/java/org/schabi/newpipe/App.kt | 38 +-- .../org/schabi/newpipe/DownloaderImpl.java | 5 + .../org/schabi/newpipe/about/AboutActivity.kt | 8 +- .../fragments/detail/VideoDetailFragment.java | 29 +-- .../list/channel/ChannelFragment.java | 18 +- .../list/comments/CommentRepliesFragment.java | 4 +- .../list/playlist/PlaylistFragment.java | 11 +- .../newpipe/info_list/StreamSegmentItem.kt | 44 ++-- .../holder/ChannelMiniInfoItemHolder.java | 4 +- .../holder/CommentInfoItemHolder.java | 8 +- .../holder/PlaylistMiniInfoItemHolder.java | 4 +- .../holder/StreamMiniInfoItemHolder.java | 4 +- .../java/org/schabi/newpipe/ktx/Bitmap.kt | 13 + .../newpipe/local/feed/item/StreamItem.kt | 4 +- .../feed/notifications/NotificationHelper.kt | 68 ++---- .../local/holder/LocalPlaylistItemHolder.java | 7 +- .../holder/LocalPlaylistStreamItemHolder.java | 6 +- .../LocalStatisticStreamItemHolder.java | 6 +- .../holder/RemotePlaylistItemHolder.java | 7 +- .../local/subscription/item/ChannelItem.kt | 4 +- .../item/PickerSubscriptionItem.kt | 4 +- .../org/schabi/newpipe/player/Player.java | 93 +++----- .../playqueue/PlayQueueItemBuilder.java | 4 +- .../SeekbarPreviewThumbnailHolder.java | 7 +- .../settings/ContentSettingsFragment.java | 16 +- .../settings/DebugSettingsFragment.java | 8 - .../settings/SelectChannelFragment.java | 4 +- .../settings/SelectPlaylistFragment.java | 18 +- .../external_communication/ShareUtils.java | 72 +++--- .../schabi/newpipe/util/image/CoilHelper.kt | 185 +++++++++++++++ .../newpipe/util/image/PicassoHelper.java | 224 ------------------ app/src/main/res/values/settings_keys.xml | 1 - app/src/main/res/xml/debug_settings.xml | 7 - gradle/libs.versions.toml | 6 +- 35 files changed, 432 insertions(+), 512 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/ktx/Bitmap.kt create mode 100644 app/src/main/java/org/schabi/newpipe/util/image/CoilHelper.kt delete mode 100644 app/src/main/java/org/schabi/newpipe/util/image/PicassoHelper.java diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e72fcfcfc..e18826c16 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -272,7 +272,8 @@ dependencies { implementation(libs.lisawray.groupie.viewbinding) // Image loading - implementation(libs.squareup.picasso) + implementation(libs.coil.compose) + implementation(libs.coil.network.okhttp) // Markdown library for Android implementation(libs.noties.markwon.core) diff --git a/app/src/main/java/org/schabi/newpipe/App.kt b/app/src/main/java/org/schabi/newpipe/App.kt index ad6b82435..3ca259528 100644 --- a/app/src/main/java/org/schabi/newpipe/App.kt +++ b/app/src/main/java/org/schabi/newpipe/App.kt @@ -1,11 +1,19 @@ package org.schabi.newpipe +import android.app.ActivityManager import android.app.Application import android.content.Context import android.util.Log import androidx.core.app.NotificationChannelCompat import androidx.core.app.NotificationManagerCompat +import androidx.core.content.getSystemService import androidx.preference.PreferenceManager +import coil3.ImageLoader +import coil3.SingletonImageLoader +import coil3.network.okhttp.OkHttpNetworkFetcherFactory +import coil3.request.allowRgb565 +import coil3.request.crossfade +import coil3.util.DebugLogger import com.jakewharton.processphoenix.ProcessPhoenix import io.reactivex.rxjava3.exceptions.CompositeException import io.reactivex.rxjava3.exceptions.MissingBackpressureException @@ -29,9 +37,8 @@ import org.schabi.newpipe.util.BridgeStateSaverInitializer import org.schabi.newpipe.util.Localization import org.schabi.newpipe.util.ServiceHelper import org.schabi.newpipe.util.StateSaver -import org.schabi.newpipe.util.image.ImageStrategy.setPreferredImageQuality -import org.schabi.newpipe.util.image.PicassoHelper -import org.schabi.newpipe.util.image.PreferredImageQuality.Companion.fromPreferenceKey +import org.schabi.newpipe.util.image.ImageStrategy +import org.schabi.newpipe.util.image.PreferredImageQuality import org.schabi.newpipe.util.potoken.PoTokenProviderImpl /* @@ -51,7 +58,9 @@ import org.schabi.newpipe.util.potoken.PoTokenProviderImpl * You should have received a copy of the GNU General Public License * along with NewPipe. If not, see . */ -open class App : Application() { +open class App : + Application(), + SingletonImageLoader.Factory { var isFirstRun = false private set var notificationsRequested = false @@ -102,9 +111,8 @@ open class App : Application() { // Initialize image loader val prefs = PreferenceManager.getDefaultSharedPreferences(this) - PicassoHelper.init(this) - setPreferredImageQuality( - fromPreferenceKey( + ImageStrategy.setPreferredImageQuality( + PreferredImageQuality.fromPreferenceKey( this, prefs.getString( getString(R.string.image_quality_key), @@ -112,20 +120,20 @@ open class App : Application() { ) ) ) - PicassoHelper.setIndicatorsEnabled( - MainActivity.DEBUG && - prefs.getBoolean(getString(R.string.show_image_indicators_key), false) - ) configureRxJavaErrorHandler() YoutubeStreamExtractor.setPoTokenProvider(PoTokenProviderImpl) } - override fun onTerminate() { - super.onTerminate() - PicassoHelper.terminate() - } + override fun newImageLoader(context: Context): ImageLoader = ImageLoader + .Builder(this) + .logger(if (BuildConfig.DEBUG) DebugLogger() else null) + .allowRgb565(getSystemService()!!.isLowRamDevice) + .crossfade(true) + .components { + add(OkHttpNetworkFetcherFactory(callFactory = DownloaderImpl.getInstance().client)) + }.build() protected open fun getDownloader(): Downloader { val downloader = DownloaderImpl.init(null) diff --git a/app/src/main/java/org/schabi/newpipe/DownloaderImpl.java b/app/src/main/java/org/schabi/newpipe/DownloaderImpl.java index 041e91396..74a2cab51 100644 --- a/app/src/main/java/org/schabi/newpipe/DownloaderImpl.java +++ b/app/src/main/java/org/schabi/newpipe/DownloaderImpl.java @@ -48,6 +48,11 @@ public final class DownloaderImpl extends Downloader { this.mCookies = new HashMap<>(); } + @NonNull + public OkHttpClient getClient() { + return client; + } + /** * It's recommended to call exactly once in the entire lifetime of the application. * diff --git a/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt b/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt index 94bde796b..ed5951f04 100644 --- a/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt +++ b/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt @@ -207,10 +207,10 @@ class AboutActivity : AppCompatActivity() { StandardLicenses.APACHE2 ), SoftwareComponent( - "Picasso", - "2013", - "Square, Inc.", - "https://square.github.io/picasso/", + "Coil", + "2023", + "Coil Contributors", + "https://coil-kt.github.io/coil/", StandardLicenses.APACHE2 ), SoftwareComponent( 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 31a496711..c97d12ba2 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 @@ -118,7 +118,7 @@ import org.schabi.newpipe.util.StreamTypeUtil; import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.external_communication.KoreUtils; import org.schabi.newpipe.util.external_communication.ShareUtils; -import org.schabi.newpipe.util.image.PicassoHelper; +import org.schabi.newpipe.util.image.CoilHelper; import java.util.ArrayList; import java.util.Iterator; @@ -129,6 +129,7 @@ import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; +import coil3.util.CoilUtils; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.disposables.CompositeDisposable; import io.reactivex.rxjava3.disposables.Disposable; @@ -160,8 +161,6 @@ public final class VideoDetailFragment private static final String DESCRIPTION_TAB_TAG = "DESCRIPTION TAB"; private static final String EMPTY_TAB_TAG = "EMPTY TAB"; - private static final String PICASSO_VIDEO_DETAILS_TAG = "PICASSO_VIDEO_DETAILS_TAG"; - // tabs private boolean showComments; private boolean showRelatedItems; @@ -1499,7 +1498,10 @@ public final class VideoDetailFragment } } - PicassoHelper.cancelTag(PICASSO_VIDEO_DETAILS_TAG); + CoilUtils.dispose(binding.detailThumbnailImageView); + CoilUtils.dispose(binding.detailSubChannelThumbnailView); + CoilUtils.dispose(binding.overlayThumbnail); + CoilUtils.dispose(binding.detailUploaderThumbnailView); binding.detailThumbnailImageView.setImageBitmap(null); binding.detailSubChannelThumbnailView.setImageBitmap(null); } @@ -1590,8 +1592,8 @@ public final class VideoDetailFragment binding.detailSecondaryControlPanel.setVisibility(View.GONE); checkUpdateProgressInfo(info); - PicassoHelper.loadDetailsThumbnail(info.getThumbnails()).tag(PICASSO_VIDEO_DETAILS_TAG) - .into(binding.detailThumbnailImageView); + CoilHelper.INSTANCE.loadDetailsThumbnail(binding.detailThumbnailImageView, + info.getThumbnails()); showMetaInfoInTextView(info.getMetaInfo(), binding.detailMetaInfoTextView, binding.detailMetaInfoSeparator, disposables); @@ -1641,8 +1643,8 @@ public final class VideoDetailFragment binding.detailUploaderTextView.setVisibility(View.GONE); } - PicassoHelper.loadAvatar(info.getUploaderAvatars()).tag(PICASSO_VIDEO_DETAILS_TAG) - .into(binding.detailSubChannelThumbnailView); + CoilHelper.INSTANCE.loadAvatar(binding.detailSubChannelThumbnailView, + info.getUploaderAvatars()); binding.detailSubChannelThumbnailView.setVisibility(View.VISIBLE); binding.detailUploaderThumbnailView.setVisibility(View.GONE); } @@ -1673,11 +1675,11 @@ public final class VideoDetailFragment binding.detailUploaderTextView.setVisibility(View.GONE); } - PicassoHelper.loadAvatar(info.getSubChannelAvatars()).tag(PICASSO_VIDEO_DETAILS_TAG) - .into(binding.detailSubChannelThumbnailView); + CoilHelper.INSTANCE.loadAvatar(binding.detailSubChannelThumbnailView, + info.getSubChannelAvatars()); binding.detailSubChannelThumbnailView.setVisibility(View.VISIBLE); - PicassoHelper.loadAvatar(info.getUploaderAvatars()).tag(PICASSO_VIDEO_DETAILS_TAG) - .into(binding.detailUploaderThumbnailView); + CoilHelper.INSTANCE.loadAvatar(binding.detailUploaderThumbnailView, + info.getUploaderAvatars()); binding.detailUploaderThumbnailView.setVisibility(View.VISIBLE); } @@ -2435,8 +2437,7 @@ public final class VideoDetailFragment binding.overlayTitleTextView.setText(isEmpty(overlayTitle) ? "" : overlayTitle); binding.overlayChannelTextView.setText(isEmpty(uploader) ? "" : uploader); binding.overlayThumbnail.setImageDrawable(null); - PicassoHelper.loadDetailsThumbnail(thumbnails).tag(PICASSO_VIDEO_DETAILS_TAG) - .into(binding.overlayThumbnail); + CoilHelper.INSTANCE.loadDetailsThumbnail(binding.overlayThumbnail, thumbnails); } private void setOverlayPlayPauseImage(final boolean playerIsPlaying) { 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 878ceb139..97481f25b 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 @@ -53,13 +53,14 @@ import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.StateSaver; import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.external_communication.ShareUtils; +import org.schabi.newpipe.util.image.CoilHelper; import org.schabi.newpipe.util.image.ImageStrategy; -import org.schabi.newpipe.util.image.PicassoHelper; import java.util.List; import java.util.Queue; import java.util.concurrent.TimeUnit; +import coil3.util.CoilUtils; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.disposables.CompositeDisposable; @@ -73,7 +74,6 @@ public class ChannelFragment extends BaseStateFragment implements StateSaver.WriteRead { private static final int BUTTON_DEBOUNCE_INTERVAL = 100; - private static final String PICASSO_CHANNEL_TAG = "PICASSO_CHANNEL_TAG"; @State protected int serviceId = Constants.NO_SERVICE_ID; @@ -578,7 +578,9 @@ public class ChannelFragment extends BaseStateFragment @Override public void showLoading() { super.showLoading(); - PicassoHelper.cancelTag(PICASSO_CHANNEL_TAG); + CoilUtils.dispose(binding.channelAvatarView); + CoilUtils.dispose(binding.channelBannerImage); + CoilUtils.dispose(binding.subChannelAvatarView); animate(binding.channelSubscribeButton, false, 100); } @@ -589,17 +591,15 @@ public class ChannelFragment extends BaseStateFragment setInitialData(result.getServiceId(), result.getOriginalUrl(), result.getName()); if (ImageStrategy.shouldLoadImages() && !result.getBanners().isEmpty()) { - PicassoHelper.loadBanner(result.getBanners()).tag(PICASSO_CHANNEL_TAG) - .into(binding.channelBannerImage); + CoilHelper.INSTANCE.loadBanner(binding.channelBannerImage, result.getBanners()); } else { // do not waste space for the banner, if the user disabled images or there is not one binding.channelBannerImage.setImageDrawable(null); } - PicassoHelper.loadAvatar(result.getAvatars()).tag(PICASSO_CHANNEL_TAG) - .into(binding.channelAvatarView); - PicassoHelper.loadAvatar(result.getParentChannelAvatars()).tag(PICASSO_CHANNEL_TAG) - .into(binding.subChannelAvatarView); + CoilHelper.INSTANCE.loadAvatar(binding.channelAvatarView, result.getAvatars()); + CoilHelper.INSTANCE.loadAvatar(binding.subChannelAvatarView, + result.getParentChannelAvatars()); binding.channelTitleView.setText(result.getName()); binding.channelSubscriberView.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentRepliesFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentRepliesFragment.java index ce52c029d..ed7dd5a8c 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentRepliesFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentRepliesFragment.java @@ -25,8 +25,8 @@ import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.NavigationHelper; +import org.schabi.newpipe.util.image.CoilHelper; import org.schabi.newpipe.util.image.ImageStrategy; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.text.TextLinkifier; import org.schabi.newpipe.util.text.LongPressLinkMovementMethod; @@ -84,7 +84,7 @@ public final class CommentRepliesFragment final CommentsInfoItem item = commentsInfoItem; // load the author avatar - PicassoHelper.loadAvatar(item.getUploaderAvatars()).into(binding.authorAvatar); + CoilHelper.INSTANCE.loadAvatar(binding.authorAvatar, item.getUploaderAvatars()); binding.authorAvatar.setVisibility(ImageStrategy.shouldLoadImages() ? View.VISIBLE : View.GONE); 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 ee6a0922c..8f0c3ac98 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 @@ -53,7 +53,7 @@ import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.PlayButtonHelper; import org.schabi.newpipe.util.external_communication.ShareUtils; -import org.schabi.newpipe.util.image.PicassoHelper; +import org.schabi.newpipe.util.image.CoilHelper; import org.schabi.newpipe.util.text.TextEllipsizer; import java.util.ArrayList; @@ -62,6 +62,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; import java.util.stream.Collectors; +import coil3.util.CoilUtils; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.core.Flowable; import io.reactivex.rxjava3.core.Single; @@ -71,8 +72,6 @@ import io.reactivex.rxjava3.disposables.Disposable; public class PlaylistFragment extends BaseListInfoFragment implements PlaylistControlViewHolder { - private static final String PICASSO_PLAYLIST_TAG = "PICASSO_PLAYLIST_TAG"; - private CompositeDisposable disposables; private Subscription bookmarkReactor; private AtomicBoolean isBookmarkButtonReady; @@ -271,7 +270,7 @@ public class PlaylistFragment extends BaseListInfoFragment() { +) : BindableItem() { companion object { const val PAYLOAD_SELECT = 1 @@ -21,34 +20,35 @@ class StreamSegmentItem( var isSelected = false - override fun bind(viewHolder: GroupieViewHolder, position: Int) { - item.previewUrl?.let { - PicassoHelper.loadThumbnail(it) - .into(viewHolder.root.findViewById(R.id.previewImage)) - } - viewHolder.root.findViewById(R.id.textViewTitle).text = item.title + override fun bind(viewBinding: ItemStreamSegmentBinding, position: Int) { + CoilHelper.loadThumbnail(viewBinding.previewImage, item.previewUrl) + viewBinding.textViewTitle.text = item.title if (item.channelName == null) { - viewHolder.root.findViewById(R.id.textViewChannel).visibility = View.GONE + viewBinding.textViewChannel.visibility = View.GONE // When the channel name is displayed there is less space // and thus the segment title needs to be only one line height. // But when there is no channel name displayed, the title can be two lines long. // The default maxLines value is set to 1 to display all elements in the AS preview, - viewHolder.root.findViewById(R.id.textViewTitle).maxLines = 2 + viewBinding.textViewTitle.maxLines = 2 } else { - viewHolder.root.findViewById(R.id.textViewChannel).text = item.channelName - viewHolder.root.findViewById(R.id.textViewChannel).visibility = View.VISIBLE + viewBinding.textViewChannel.text = item.channelName + viewBinding.textViewChannel.visibility = View.VISIBLE } - viewHolder.root.findViewById(R.id.textViewStartSeconds).text = + viewBinding.textViewStartSeconds.text = Localization.getDurationString(item.startTimeSeconds.toLong()) - viewHolder.root.setOnClickListener { onClick.onItemClick(this, item.startTimeSeconds) } - viewHolder.root.setOnLongClickListener { + viewBinding.root.setOnClickListener { onClick.onItemClick(this, item.startTimeSeconds) } + viewBinding.root.setOnLongClickListener { onClick.onItemLongClick(this, item.startTimeSeconds) true } - viewHolder.root.isSelected = isSelected + viewBinding.root.isSelected = isSelected } - override fun bind(viewHolder: GroupieViewHolder, position: Int, payloads: MutableList) { + override fun bind( + viewHolder: GroupieViewHolder, + position: Int, + payloads: MutableList + ) { if (payloads.contains(PAYLOAD_SELECT)) { viewHolder.root.isSelected = isSelected return @@ -57,4 +57,6 @@ class StreamSegmentItem( } override fun getLayout() = R.layout.item_stream_segment + + override fun initializeViewBinding(view: View) = ItemStreamSegmentBinding.bind(view) } diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java index 7afc05c6c..92a5054e1 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java @@ -13,8 +13,8 @@ import org.schabi.newpipe.extractor.channel.ChannelInfoItem; import org.schabi.newpipe.extractor.utils.Utils; import org.schabi.newpipe.info_list.InfoItemBuilder; import org.schabi.newpipe.local.history.HistoryRecordManager; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.Localization; +import org.schabi.newpipe.util.image.CoilHelper; public class ChannelMiniInfoItemHolder extends InfoItemHolder { private final ImageView itemThumbnailView; @@ -56,7 +56,7 @@ public class ChannelMiniInfoItemHolder extends InfoItemHolder { itemAdditionalDetailView.setText(getDetailLine(item)); } - PicassoHelper.loadAvatar(item.getThumbnails()).into(itemThumbnailView); + CoilHelper.INSTANCE.loadAvatar(itemThumbnailView, item.getThumbnails()); itemView.setOnClickListener(view -> { if (itemBuilder.getOnChannelSelectedListener() != null) { diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentInfoItemHolder.java index a19831cc7..5dee128eb 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentInfoItemHolder.java @@ -27,8 +27,8 @@ import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.external_communication.ShareUtils; +import org.schabi.newpipe.util.image.CoilHelper; import org.schabi.newpipe.util.image.ImageStrategy; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.text.TextEllipsizer; public class CommentInfoItemHolder extends InfoItemHolder { @@ -82,14 +82,12 @@ public class CommentInfoItemHolder extends InfoItemHolder { @Override public void updateFromItem(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { - if (!(infoItem instanceof CommentsInfoItem)) { + if (!(infoItem instanceof CommentsInfoItem item)) { return; } - final CommentsInfoItem item = (CommentsInfoItem) infoItem; - // load the author avatar - PicassoHelper.loadAvatar(item.getUploaderAvatars()).into(itemThumbnailView); + CoilHelper.INSTANCE.loadAvatar(itemThumbnailView, item.getUploaderAvatars()); if (ImageStrategy.shouldLoadImages()) { itemThumbnailView.setVisibility(View.VISIBLE); itemRoot.setPadding(commentVerticalPadding, commentVerticalPadding, diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistMiniInfoItemHolder.java index c9216d9a9..b7949318d 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistMiniInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistMiniInfoItemHolder.java @@ -9,8 +9,8 @@ import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem; import org.schabi.newpipe.info_list.InfoItemBuilder; import org.schabi.newpipe.local.history.HistoryRecordManager; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.Localization; +import org.schabi.newpipe.util.image.CoilHelper; public class PlaylistMiniInfoItemHolder extends InfoItemHolder { public final ImageView itemThumbnailView; @@ -46,7 +46,7 @@ public class PlaylistMiniInfoItemHolder extends InfoItemHolder { .localizeStreamCountMini(itemStreamCountView.getContext(), item.getStreamCount())); itemUploaderView.setText(item.getUploaderName()); - PicassoHelper.loadPlaylistThumbnail(item.getThumbnails()).into(itemThumbnailView); + CoilHelper.INSTANCE.loadPlaylistThumbnail(itemThumbnailView, item.getThumbnails()); itemView.setOnClickListener(view -> { if (itemBuilder.getOnPlaylistSelectedListener() != null) { diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java index 01f3be6b3..32fa8bf60 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java @@ -16,8 +16,8 @@ import org.schabi.newpipe.ktx.ViewUtils; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.DependentPreferenceHelper; import org.schabi.newpipe.util.Localization; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.StreamTypeUtil; +import org.schabi.newpipe.util.image.CoilHelper; import org.schabi.newpipe.views.AnimatedProgressBar; import java.util.concurrent.TimeUnit; @@ -87,7 +87,7 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder { } // Default thumbnail is shown on error, while loading and if the url is empty - PicassoHelper.loadThumbnail(item.getThumbnails()).into(itemThumbnailView); + CoilHelper.INSTANCE.loadThumbnail(itemThumbnailView, item.getThumbnails()); itemView.setOnClickListener(view -> { if (itemBuilder.getOnStreamSelectedListener() != null) { diff --git a/app/src/main/java/org/schabi/newpipe/ktx/Bitmap.kt b/app/src/main/java/org/schabi/newpipe/ktx/Bitmap.kt new file mode 100644 index 000000000..140351b0d --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/ktx/Bitmap.kt @@ -0,0 +1,13 @@ +package org.schabi.newpipe.ktx + +import android.graphics.Bitmap +import android.graphics.Rect +import androidx.core.graphics.BitmapCompat + +@Suppress("NOTHING_TO_INLINE") +inline fun Bitmap.scale( + width: Int, + height: Int, + srcRect: Rect? = null, + scaleInLinearSpace: Boolean = true +) = BitmapCompat.createScaledBitmap(this, width, height, srcRect, scaleInLinearSpace) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt b/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt index e367961f1..258a67a4c 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt @@ -21,7 +21,7 @@ import org.schabi.newpipe.extractor.stream.StreamType.POST_LIVE_STREAM import org.schabi.newpipe.extractor.stream.StreamType.VIDEO_STREAM import org.schabi.newpipe.util.Localization import org.schabi.newpipe.util.StreamTypeUtil -import org.schabi.newpipe.util.image.PicassoHelper +import org.schabi.newpipe.util.image.CoilHelper data class StreamItem( val streamWithState: StreamWithState, @@ -101,7 +101,7 @@ data class StreamItem( viewBinding.itemProgressView.visibility = View.GONE } - PicassoHelper.loadThumbnail(stream.thumbnailUrl).into(viewBinding.itemThumbnailView) + CoilHelper.loadThumbnail(viewBinding.itemThumbnailView, stream.thumbnailUrl) if (itemVersion != ItemVersion.MINI) { viewBinding.itemAdditionalDetails.text = diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationHelper.kt b/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationHelper.kt index aa03aafc5..11be80f2a 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationHelper.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationHelper.kt @@ -6,7 +6,6 @@ import android.app.PendingIntent import android.content.Context import android.content.Intent import android.graphics.Bitmap -import android.graphics.drawable.Drawable import android.net.Uri import android.os.Build import android.provider.Settings @@ -17,20 +16,17 @@ import androidx.core.content.ContextCompat import androidx.core.content.getSystemService import androidx.core.net.toUri import androidx.preference.PreferenceManager -import com.squareup.picasso.Picasso -import com.squareup.picasso.Target import org.schabi.newpipe.R import org.schabi.newpipe.extractor.stream.StreamInfoItem import org.schabi.newpipe.local.feed.service.FeedUpdateInfo import org.schabi.newpipe.util.NavigationHelper -import org.schabi.newpipe.util.image.PicassoHelper +import org.schabi.newpipe.util.image.CoilHelper /** * Helper for everything related to show notifications about new streams to the user. */ class NotificationHelper(val context: Context) { private val manager = NotificationManagerCompat.from(context) - private val iconLoadingTargets = ArrayList() /** * Show notifications for new streams from a single channel. The individual notifications are @@ -71,67 +67,34 @@ class NotificationHelper(val context: Context) { summaryBuilder.setStyle(style) // open the channel page when clicking on the summary notification + val intent = NavigationHelper + .getChannelIntent(context, data.serviceId, data.url) + .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) summaryBuilder.setContentIntent( - PendingIntentCompat.getActivity( - context, - data.pseudoId, - NavigationHelper - .getChannelIntent(context, data.serviceId, data.url) - .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), - 0, - false - ) + PendingIntentCompat.getActivity(context, data.pseudoId, intent, 0, false) ) - // a Target is like a listener for image loading events - val target = object : Target { - override fun onBitmapLoaded(bitmap: Bitmap, from: Picasso.LoadedFrom) { - // set channel icon only if there is actually one (for Android versions < 7.0) - summaryBuilder.setLargeIcon(bitmap) + val avatarIcon = + CoilHelper.loadBitmapBlocking(context, data.avatarUrl, R.drawable.ic_newpipe_triangle_white) + summaryBuilder.setLargeIcon(avatarIcon) - // Show individual stream notifications, set channel icon only if there is actually - // one - showStreamNotifications(newStreams, data.serviceId, data.url, bitmap) - // Show summary notification if enabled - if (manager.areNotificationsEnabled()) { - manager.notify(data.pseudoId, summaryBuilder.build()) - } - - iconLoadingTargets.remove(this) // allow it to be garbage-collected - } - - override fun onBitmapFailed(e: Exception, errorDrawable: Drawable) { - // Show individual stream notifications - showStreamNotifications(newStreams, data.serviceId, data.url, null) - // Show summary notification if enabled - if (manager.areNotificationsEnabled()) { - manager.notify(data.pseudoId, summaryBuilder.build()) - } - iconLoadingTargets.remove(this) // allow it to be garbage-collected - } - - override fun onPrepareLoad(placeHolderDrawable: Drawable) { - // Nothing to do - } + // Show individual stream notifications, set channel icon only if there is actually one + showStreamNotifications(newStreams, data.serviceId, avatarIcon) + // Show summary notification + if (manager.areNotificationsEnabled()) { + manager.notify(data.pseudoId, summaryBuilder.build()) } - - // add the target to the list to hold a strong reference and prevent it from being garbage - // collected, since Picasso only holds weak references to targets - iconLoadingTargets.add(target) - - PicassoHelper.loadNotificationIcon(data.avatarUrl).into(target) } private fun showStreamNotifications( newStreams: List, serviceId: Int, - channelUrl: String, channelIcon: Bitmap? ) { if (manager.areNotificationsEnabled()) { newStreams.forEach { stream -> val notification = - createStreamNotification(stream, serviceId, channelUrl, channelIcon) + createStreamNotification(stream, serviceId, channelIcon) manager.notify(stream.url.hashCode(), notification) } } @@ -140,7 +103,6 @@ class NotificationHelper(val context: Context) { private fun createStreamNotification( item: StreamInfoItem, serviceId: Int, - channelUrl: String, channelIcon: Bitmap? ): Notification { return NotificationCompat.Builder( @@ -151,7 +113,7 @@ class NotificationHelper(val context: Context) { .setLargeIcon(channelIcon) .setContentTitle(item.name) .setContentText(item.uploaderName) - .setGroup(channelUrl) + .setGroup(item.uploaderUrl) .setColor(ContextCompat.getColor(context, R.color.ic_launcher_background)) .setColorized(true) .setAutoCancel(true) diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java index 528275d75..518fb3553 100644 --- a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java @@ -8,8 +8,8 @@ import org.schabi.newpipe.database.playlist.PlaylistDuplicatesEntry; import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry; import org.schabi.newpipe.local.LocalItemBuilder; import org.schabi.newpipe.local.history.HistoryRecordManager; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.Localization; +import org.schabi.newpipe.util.image.CoilHelper; import java.time.format.DateTimeFormatter; @@ -30,17 +30,16 @@ public class LocalPlaylistItemHolder extends PlaylistItemHolder { public void updateFromItem(final LocalItem localItem, final HistoryRecordManager historyRecordManager, final DateTimeFormatter dateTimeFormatter) { - if (!(localItem instanceof PlaylistMetadataEntry)) { + if (!(localItem instanceof PlaylistMetadataEntry item)) { return; } - final PlaylistMetadataEntry item = (PlaylistMetadataEntry) localItem; itemTitleView.setText(item.getOrderingName()); itemStreamCountView.setText(Localization.localizeStreamCountMini( itemStreamCountView.getContext(), item.getStreamCount())); itemUploaderView.setVisibility(View.INVISIBLE); - PicassoHelper.loadPlaylistThumbnail(item.getThumbnailUrl()).into(itemThumbnailView); + CoilHelper.INSTANCE.loadPlaylistThumbnail(itemThumbnailView, item.getThumbnailUrl()); if (item instanceof PlaylistDuplicatesEntry && ((PlaylistDuplicatesEntry) item).getTimesStreamIsContained() > 0) { diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistStreamItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistStreamItemHolder.java index 89a714fd7..7dc71bfb4 100644 --- a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistStreamItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistStreamItemHolder.java @@ -16,8 +16,8 @@ import org.schabi.newpipe.local.LocalItemBuilder; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.DependentPreferenceHelper; import org.schabi.newpipe.util.Localization; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.ServiceHelper; +import org.schabi.newpipe.util.image.CoilHelper; import org.schabi.newpipe.views.AnimatedProgressBar; import java.time.format.DateTimeFormatter; @@ -83,8 +83,8 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder { } // Default thumbnail is shown on error, while loading and if the url is empty - PicassoHelper.loadThumbnail(item.getStreamEntity().getThumbnailUrl()) - .into(itemThumbnailView); + CoilHelper.INSTANCE.loadThumbnail(itemThumbnailView, + item.getStreamEntity().getThumbnailUrl()); itemView.setOnClickListener(view -> { if (itemBuilder.getOnItemSelectedListener() != null) { diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java index 150a35eb5..f26a76ad9 100644 --- a/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java @@ -16,8 +16,8 @@ import org.schabi.newpipe.local.LocalItemBuilder; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.DependentPreferenceHelper; import org.schabi.newpipe.util.Localization; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.ServiceHelper; +import org.schabi.newpipe.util.image.CoilHelper; import org.schabi.newpipe.views.AnimatedProgressBar; import java.time.format.DateTimeFormatter; @@ -117,8 +117,8 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder { } // Default thumbnail is shown on error, while loading and if the url is empty - PicassoHelper.loadThumbnail(item.getStreamEntity().getThumbnailUrl()) - .into(itemThumbnailView); + CoilHelper.INSTANCE.loadThumbnail(itemThumbnailView, + item.getStreamEntity().getThumbnailUrl()); itemView.setOnClickListener(view -> { if (itemBuilder.getOnItemSelectedListener() != null) { diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java index 3a339aec8..1eb97a59e 100644 --- a/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java @@ -8,8 +8,8 @@ import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity; import org.schabi.newpipe.local.LocalItemBuilder; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.Localization; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.ServiceHelper; +import org.schabi.newpipe.util.image.CoilHelper; import java.time.format.DateTimeFormatter; @@ -29,10 +29,9 @@ public class RemotePlaylistItemHolder extends PlaylistItemHolder { public void updateFromItem(final LocalItem localItem, final HistoryRecordManager historyRecordManager, final DateTimeFormatter dateTimeFormatter) { - if (!(localItem instanceof PlaylistRemoteEntity)) { + if (!(localItem instanceof PlaylistRemoteEntity item)) { return; } - final PlaylistRemoteEntity item = (PlaylistRemoteEntity) localItem; itemTitleView.setText(item.getOrderingName()); itemStreamCountView.setText(Localization.localizeStreamCountMini( @@ -45,7 +44,7 @@ public class RemotePlaylistItemHolder extends PlaylistItemHolder { itemUploaderView.setText(ServiceHelper.getNameOfServiceById(item.getServiceId())); } - PicassoHelper.loadPlaylistThumbnail(item.getThumbnailUrl()).into(itemThumbnailView); + CoilHelper.INSTANCE.loadPlaylistThumbnail(itemThumbnailView, item.getThumbnailUrl()); super.updateFromItem(localItem, historyRecordManager, dateTimeFormatter); } 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 7946de693..7687a7d6d 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 @@ -9,7 +9,7 @@ import org.schabi.newpipe.R import org.schabi.newpipe.extractor.channel.ChannelInfoItem import org.schabi.newpipe.util.Localization import org.schabi.newpipe.util.OnClickGesture -import org.schabi.newpipe.util.image.PicassoHelper +import org.schabi.newpipe.util.image.CoilHelper class ChannelItem( private val infoItem: ChannelInfoItem, @@ -39,7 +39,7 @@ class ChannelItem( itemChannelDescriptionView.text = infoItem.description } - PicassoHelper.loadAvatar(infoItem.thumbnails).into(itemThumbnailView) + CoilHelper.loadAvatar(itemThumbnailView, infoItem.thumbnails) gesturesListener?.run { viewHolder.root.setOnClickListener { selected(infoItem) } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/PickerSubscriptionItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/PickerSubscriptionItem.kt index 3a4c6e41b..da35447e3 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/PickerSubscriptionItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/PickerSubscriptionItem.kt @@ -10,7 +10,7 @@ import org.schabi.newpipe.database.subscription.SubscriptionEntity import org.schabi.newpipe.databinding.PickerSubscriptionItemBinding import org.schabi.newpipe.ktx.AnimationType import org.schabi.newpipe.ktx.animate -import org.schabi.newpipe.util.image.PicassoHelper +import org.schabi.newpipe.util.image.CoilHelper data class PickerSubscriptionItem( val subscriptionEntity: SubscriptionEntity, @@ -21,7 +21,7 @@ data class PickerSubscriptionItem( override fun getSpanSize(spanCount: Int, position: Int): Int = 1 override fun bind(viewBinding: PickerSubscriptionItemBinding, position: Int) { - PicassoHelper.loadAvatar(subscriptionEntity.avatarUrl).into(viewBinding.thumbnailView) + CoilHelper.loadAvatar(viewBinding.thumbnailView, subscriptionEntity.avatarUrl) viewBinding.titleView.text = subscriptionEntity.name viewBinding.selectedHighlight.isVisible = isSelected } 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 b07b15a45..159ecbd6e 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -46,13 +46,14 @@ import static org.schabi.newpipe.util.ListHelper.getPopupResolutionIndex; import static org.schabi.newpipe.util.ListHelper.getResolutionIndex; import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static coil3.Image_androidKt.toBitmap; + import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.graphics.Bitmap; -import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.support.v4.media.session.MediaSessionCompat; import android.util.Log; @@ -80,8 +81,6 @@ import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.MappingTrackSelector; import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; import com.google.android.exoplayer2.video.VideoSize; -import com.squareup.picasso.Picasso; -import com.squareup.picasso.Target; import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; @@ -126,13 +125,14 @@ import org.schabi.newpipe.util.ListHelper; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.SerializedCache; import org.schabi.newpipe.util.StreamTypeUtil; -import org.schabi.newpipe.util.image.PicassoHelper; +import org.schabi.newpipe.util.image.CoilHelper; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.stream.IntStream; +import coil3.target.Target; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.Single; @@ -181,7 +181,6 @@ public final class Player implements PlaybackListener, Listener { //////////////////////////////////////////////////////////////////////////*/ public static final int RENDERER_UNAVAILABLE = -1; - private static final String PICASSO_PLAYER_THUMBNAIL_TAG = "PICASSO_PLAYER_THUMBNAIL_TAG"; /*////////////////////////////////////////////////////////////////////////// // Playback @@ -200,6 +199,8 @@ public final class Player implements PlaybackListener, Listener { private MediaItemTag currentMetadata; @Nullable private Bitmap currentThumbnail; + @Nullable + private coil3.request.Disposable thumbnailDisposable; /*////////////////////////////////////////////////////////////////////////// // Player @@ -255,12 +256,6 @@ public final class Player implements PlaybackListener, Listener { @NonNull private final CompositeDisposable streamItemDisposable = new CompositeDisposable(); - // This is the only listener we need for thumbnail loading, since there is always at most only - // one thumbnail being loaded at a time. This field is also here to maintain a strong reference, - // which would otherwise be garbage collected since Picasso holds weak references to targets. - @NonNull - private final Target currentThumbnailTarget; - /*////////////////////////////////////////////////////////////////////////// // Utils //////////////////////////////////////////////////////////////////////////*/ @@ -314,8 +309,6 @@ public final class Player implements PlaybackListener, Listener { videoResolver = new VideoPlaybackResolver(context, dataSource, getQualityResolver()); audioResolver = new AudioPlaybackResolver(context, dataSource); - currentThumbnailTarget = getCurrentThumbnailTarget(); - // The UIs added here should always be present. They will be initialized when the player // reaches the initialization step. Make sure the media session ui is before the // notification ui in the UIs list, since the notification depends on the media session in @@ -704,7 +697,6 @@ public final class Player implements PlaybackListener, Listener { databaseUpdateDisposable.clear(); progressUpdateDisposable.set(null); streamItemDisposable.clear(); - cancelLoadingCurrentThumbnail(); UIs.destroyAll(Object.class); // destroy every UI: obviously every UI extends Object } @@ -884,67 +876,58 @@ public final class Player implements PlaybackListener, Listener { //////////////////////////////////////////////////////////////////////////*/ //region Thumbnail loading - private Target getCurrentThumbnailTarget() { - // a Picasso target is just a listener for thumbnail loading events - return new Target() { - @Override - public void onBitmapLoaded(final Bitmap bitmap, final Picasso.LoadedFrom from) { - if (DEBUG) { - Log.d(TAG, "Thumbnail - onBitmapLoaded() called with: bitmap = [" + bitmap - + " -> " + bitmap.getWidth() + "x" + bitmap.getHeight() + "], from = [" - + from + "]"); - } - // there is a new thumbnail, so e.g. the end screen thumbnail needs to change, too. - onThumbnailLoaded(bitmap); - } - - @Override - public void onBitmapFailed(final Exception e, final Drawable errorDrawable) { - Log.e(TAG, "Thumbnail - onBitmapFailed() called", e); - // there is a new thumbnail, so e.g. the end screen thumbnail needs to change, too. - onThumbnailLoaded(null); - } - - @Override - public void onPrepareLoad(final Drawable placeHolderDrawable) { - if (DEBUG) { - Log.d(TAG, "Thumbnail - onPrepareLoad() called"); - } - } - }; - } - private void loadCurrentThumbnail(final List thumbnails) { if (DEBUG) { Log.d(TAG, "Thumbnail - loadCurrentThumbnail() called with thumbnails = [" + thumbnails.size() + "]"); } - // first cancel any previous loading - cancelLoadingCurrentThumbnail(); + // Cancel any ongoing image loading + if (thumbnailDisposable != null) { + thumbnailDisposable.dispose(); + } // Unset currentThumbnail, since it is now outdated. This ensures it is not used in media - // session metadata while the new thumbnail is being loaded by Picasso. + // session metadata while the new thumbnail is being loaded by Coil. onThumbnailLoaded(null); if (thumbnails.isEmpty()) { return; } // scale down the notification thumbnail for performance - PicassoHelper.loadScaledDownThumbnail(context, thumbnails) - .tag(PICASSO_PLAYER_THUMBNAIL_TAG) - .into(currentThumbnailTarget); + final var thumbnailTarget = new Target() { + @Override + public void onError(@Nullable final coil3.Image error) { + Log.e(TAG, "Thumbnail - onError() called"); + // there is a new thumbnail, so e.g. the end screen thumbnail needs to change, too. + onThumbnailLoaded(null); + } + + @Override + public void onStart(@Nullable final coil3.Image placeholder) { + if (DEBUG) { + Log.d(TAG, "Thumbnail - onStart() called"); + } + } + + @Override + public void onSuccess(@NonNull final coil3.Image result) { + if (DEBUG) { + Log.d(TAG, "Thumbnail - onSuccess() called with: drawable = [" + result + "]"); + } + // there is a new thumbnail, so e.g. the end screen thumbnail needs to change, too. + onThumbnailLoaded(toBitmap(result)); + } + }; + thumbnailDisposable = CoilHelper.INSTANCE + .loadScaledDownThumbnail(context, thumbnails, thumbnailTarget); } - private void cancelLoadingCurrentThumbnail() { - // cancel the Picasso job associated with the player thumbnail, if any - PicassoHelper.cancelTag(PICASSO_PLAYER_THUMBNAIL_TAG); - } private void onThumbnailLoaded(@Nullable final Bitmap bitmap) { // Avoid useless thumbnail updates, if the thumbnail has not actually changed. Based on the // thumbnail loading code, this if would be skipped only when both bitmaps are `null`, since - // onThumbnailLoaded won't be called twice with the same nonnull bitmap by Picasso's target. + // onThumbnailLoaded won't be called twice with the same nonnull bitmap by Coil's target. if (currentThumbnail != bitmap) { currentThumbnail = bitmap; UIs.call(playerUi -> playerUi.onThumbnailLoaded(bitmap)); diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemBuilder.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemBuilder.java index 066f92c26..8994aef79 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemBuilder.java +++ b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemBuilder.java @@ -6,8 +6,8 @@ import android.view.MotionEvent; import android.view.View; import org.schabi.newpipe.util.Localization; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.ServiceHelper; +import org.schabi.newpipe.util.image.CoilHelper; public class PlayQueueItemBuilder { private static final String TAG = PlayQueueItemBuilder.class.toString(); @@ -33,7 +33,7 @@ public class PlayQueueItemBuilder { holder.itemDurationView.setVisibility(View.GONE); } - PicassoHelper.loadThumbnail(item.getThumbnails()).into(holder.itemThumbnailView); + CoilHelper.INSTANCE.loadThumbnail(holder.itemThumbnailView, item.getThumbnails()); holder.itemRoot.setOnClickListener(view -> { if (onItemClickListener != null) { diff --git a/app/src/main/java/org/schabi/newpipe/player/seekbarpreview/SeekbarPreviewThumbnailHolder.java b/app/src/main/java/org/schabi/newpipe/player/seekbarpreview/SeekbarPreviewThumbnailHolder.java index 09c61b8b3..d9e25fe8b 100644 --- a/app/src/main/java/org/schabi/newpipe/player/seekbarpreview/SeekbarPreviewThumbnailHolder.java +++ b/app/src/main/java/org/schabi/newpipe/player/seekbarpreview/SeekbarPreviewThumbnailHolder.java @@ -13,8 +13,9 @@ import androidx.collection.SparseArrayCompat; import com.google.common.base.Stopwatch; +import org.schabi.newpipe.App; import org.schabi.newpipe.extractor.stream.Frameset; -import org.schabi.newpipe.util.image.PicassoHelper; +import org.schabi.newpipe.util.image.CoilHelper; import java.util.Comparator; import java.util.List; @@ -207,8 +208,8 @@ public class SeekbarPreviewThumbnailHolder { Log.d(TAG, "Downloading bitmap for seekbarPreview from '" + url + "'"); // Gets the bitmap within the timeout of 15 seconds imposed by default by OkHttpClient - // Ensure that your are not running on the main-Thread this will otherwise hang - final Bitmap bitmap = PicassoHelper.loadSeekbarThumbnailPreview(url).get(); + // Ensure that you are not running on the main thread, otherwise this will hang + final var bitmap = CoilHelper.INSTANCE.loadBitmapBlocking(App.getInstance(), url); if (sw != null) { Log.d(TAG, "Download of bitmap for seekbarPreview from '" + url + "' took " 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 b855f7c38..85ee97853 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java @@ -19,12 +19,12 @@ import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.player.helper.PlayerHelper; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.image.ImageStrategy; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.image.PreferredImageQuality; -import java.io.IOException; import java.util.Locale; +import coil3.SingletonImageLoader; + public class ContentSettingsFragment extends BasePreferenceFragment { private String youtubeRestrictedModeEnabledKey; @@ -74,14 +74,12 @@ public class ContentSettingsFragment extends BasePreferenceFragment { (preference, newValue) -> { ImageStrategy.setPreferredImageQuality(PreferredImageQuality .fromPreferenceKey(requireContext(), (String) newValue)); - try { - PicassoHelper.clearCache(preference.getContext()); - Toast.makeText(preference.getContext(), - R.string.thumbnail_cache_wipe_complete_notice, Toast.LENGTH_SHORT) + final var loader = SingletonImageLoader.get(preference.getContext()); + loader.getMemoryCache().clear(); + loader.getDiskCache().clear(); + Toast.makeText(preference.getContext(), + R.string.thumbnail_cache_wipe_complete_notice, Toast.LENGTH_SHORT) .show(); - } catch (final IOException e) { - Log.e(TAG, "Unable to clear Picasso cache", e); - } return true; }); } diff --git a/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java index 82f2f5bb6..229de7005 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java @@ -10,7 +10,6 @@ import org.schabi.newpipe.error.ErrorInfo; import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.local.feed.notifications.NotificationWorker; -import org.schabi.newpipe.util.image.PicassoHelper; import java.util.Optional; @@ -25,8 +24,6 @@ public class DebugSettingsFragment extends BasePreferenceFragment { requirePreference(R.string.allow_heap_dumping_key); final Preference showMemoryLeaksPreference = requirePreference(R.string.show_memory_leaks_key); - final Preference showImageIndicatorsPreference = - requirePreference(R.string.show_image_indicators_key); final Preference checkNewStreamsPreference = requirePreference(R.string.check_new_streams_key); final Preference crashTheAppPreference = @@ -54,11 +51,6 @@ public class DebugSettingsFragment extends BasePreferenceFragment { showMemoryLeaksPreference.setSummary(R.string.leak_canary_not_available); } - showImageIndicatorsPreference.setOnPreferenceChangeListener((preference, newValue) -> { - PicassoHelper.setIndicatorsEnabled((Boolean) newValue); - return true; - }); - checkNewStreamsPreference.setOnPreferenceClickListener(preference -> { NotificationWorker.runNow(preference.getContext()); return true; 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 18e0816bb..25d6b3a0f 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java @@ -19,8 +19,8 @@ import org.schabi.newpipe.R; import org.schabi.newpipe.database.subscription.SubscriptionEntity; import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.local.subscription.SubscriptionManager; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.ThemeHelper; +import org.schabi.newpipe.util.image.CoilHelper; import java.util.List; import java.util.Vector; @@ -190,7 +190,7 @@ public class SelectChannelFragment extends DialogFragment { final SubscriptionEntity entry = subscriptions.get(position); holder.titleView.setText(entry.getName()); holder.view.setOnClickListener(view -> clickedItem(position)); - PicassoHelper.loadAvatar(entry.getAvatarUrl()).into(holder.thumbnailView); + CoilHelper.INSTANCE.loadAvatar(holder.thumbnailView, entry.getAvatarUrl()); } @Override 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 880cbb282..ea475cb4f 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SelectPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SelectPlaylistFragment.java @@ -27,7 +27,7 @@ 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; -import org.schabi.newpipe.util.image.PicassoHelper; +import org.schabi.newpipe.util.image.CoilHelper; import java.util.List; import java.util.Vector; @@ -154,21 +154,17 @@ public class SelectPlaylistFragment extends DialogFragment { final int position) { final PlaylistLocalItem selectedItem = playlists.get(position); - if (selectedItem instanceof PlaylistMetadataEntry) { - final PlaylistMetadataEntry entry = ((PlaylistMetadataEntry) selectedItem); - + if (selectedItem instanceof PlaylistMetadataEntry entry) { holder.titleView.setText(entry.getOrderingName()); holder.view.setOnClickListener(view -> clickedItem(position)); - PicassoHelper.loadPlaylistThumbnail(entry.getThumbnailUrl()) - .into(holder.thumbnailView); - - } else if (selectedItem instanceof PlaylistRemoteEntity) { - final PlaylistRemoteEntity entry = ((PlaylistRemoteEntity) selectedItem); + CoilHelper.INSTANCE.loadPlaylistThumbnail(holder.thumbnailView, + entry.getThumbnailUrl()); + } else if (selectedItem instanceof PlaylistRemoteEntity entry) { holder.titleView.setText(entry.getOrderingName()); holder.view.setOnClickListener(view -> clickedItem(position)); - PicassoHelper.loadPlaylistThumbnail(entry.getThumbnailUrl()) - .into(holder.thumbnailView); + CoilHelper.INSTANCE.loadPlaylistThumbnail(holder.thumbnailView, + entry.getThumbnailUrl()); } } diff --git a/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java b/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java index 9fe351b4b..d56362105 100644 --- a/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java +++ b/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java @@ -1,6 +1,7 @@ package org.schabi.newpipe.util.external_communication; import static org.schabi.newpipe.MainActivity.DEBUG; +import static coil3.Image_androidKt.toBitmap; import android.content.ActivityNotFoundException; import android.content.ClipData; @@ -9,6 +10,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Build; import android.text.TextUtils; @@ -25,12 +27,15 @@ import org.schabi.newpipe.R; import org.schabi.newpipe.RouterActivity; import org.schabi.newpipe.extractor.Image; import org.schabi.newpipe.util.image.ImageStrategy; -import org.schabi.newpipe.util.image.PicassoHelper; -import java.io.File; -import java.io.FileOutputStream; +import java.nio.file.Files; +import java.util.Collections; import java.util.List; +import coil3.SingletonImageLoader; +import coil3.disk.DiskCache; +import coil3.memory.MemoryCache; + public final class ShareUtils { private static final String TAG = ShareUtils.class.getSimpleName(); @@ -273,7 +278,7 @@ public final class ShareUtils { * @param content the content to share * @param images a set of possible {@link Image}s of the subject, among which to choose with * {@link ImageStrategy#choosePreferredImage(List)} since that's likely to - * provide an image that is in Picasso's cache + * provide an image that is in Coil's cache */ public static void shareText(@NonNull final Context context, @NonNull final String title, @@ -334,11 +339,9 @@ public final class ShareUtils { * *

* In order not to worry about network issues (timeouts, DNS issues, low connection speed, ...) - * when sharing a content, only images in the {@link com.squareup.picasso.LruCache LruCache} - * used by the Picasso library inside {@link PicassoHelper} are used as preview images. If the - * thumbnail image is not in the cache, no {@link ClipData} will be generated and {@code null} - * will be returned. - *

+ * when sharing a content, only images in the {@link MemoryCache} or {@link DiskCache} + * used by the Coil library are used as preview images. If the thumbnail image is not in the + * cache, no {@link ClipData} will be generated and {@code null} will be returned. * *

* In order to display the image in the content preview of the Android share sheet, an URI of @@ -354,12 +357,6 @@ public final class ShareUtils { *

* *

- * This method will call {@link PicassoHelper#getImageFromCacheIfPresent(String)} to get the - * thumbnail of the content in the {@link com.squareup.picasso.LruCache LruCache} used by - * the Picasso library inside {@link PicassoHelper}. - *

- * - *

* Using the result of this method when sharing has only an effect on the system share sheet (if * OEMs didn't change Android system standard behavior) on Android API 29 and higher. *

@@ -373,33 +370,46 @@ public final class ShareUtils { @NonNull final Context context, @NonNull final String thumbnailUrl) { try { - final Bitmap bitmap = PicassoHelper.getImageFromCacheIfPresent(thumbnailUrl); - if (bitmap == null) { - return null; - } - // Save the image in memory to the application's cache because we need a URI to the // image to generate a ClipData which will show the share sheet, and so an image file final Context applicationContext = context.getApplicationContext(); - final String appFolder = applicationContext.getCacheDir().getAbsolutePath(); - final File thumbnailPreviewFile = new File(appFolder - + "/android_share_sheet_image_preview.jpg"); + final var loader = SingletonImageLoader.get(context); + final var value = loader.getMemoryCache() + .get(new MemoryCache.Key(thumbnailUrl, Collections.emptyMap())); - // Any existing file will be overwritten with FileOutputStream - final FileOutputStream fileOutputStream = new FileOutputStream(thumbnailPreviewFile); - bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fileOutputStream); - fileOutputStream.close(); + final Bitmap cachedBitmap; + if (value != null) { + cachedBitmap = toBitmap(value.getImage()); + } else { + try (var snapshot = loader.getDiskCache().openSnapshot(thumbnailUrl)) { + if (snapshot != null) { + cachedBitmap = BitmapFactory.decodeFile(snapshot.getData().toString()); + } else { + cachedBitmap = null; + } + } + } + + if (cachedBitmap == null) { + return null; + } + + final var path = applicationContext.getCacheDir().toPath() + .resolve("android_share_sheet_image_preview.jpg"); + // Any existing file will be overwritten + try (var outputStream = Files.newOutputStream(path)) { + cachedBitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream); + } final ClipData clipData = ClipData.newUri(applicationContext.getContentResolver(), "", - FileProvider.getUriForFile(applicationContext, - BuildConfig.APPLICATION_ID + ".provider", - thumbnailPreviewFile)); + FileProvider.getUriForFile(applicationContext, + BuildConfig.APPLICATION_ID + ".provider", + path.toFile())); if (DEBUG) { Log.d(TAG, "ClipData successfully generated for Android share sheet: " + clipData); } return clipData; - } catch (final Exception e) { Log.w(TAG, "Error when setting preview image for share sheet", e); return null; diff --git a/app/src/main/java/org/schabi/newpipe/util/image/CoilHelper.kt b/app/src/main/java/org/schabi/newpipe/util/image/CoilHelper.kt new file mode 100644 index 000000000..bd1c57f98 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/image/CoilHelper.kt @@ -0,0 +1,185 @@ +package org.schabi.newpipe.util.image + +import android.content.Context +import android.graphics.Bitmap +import android.util.Log +import android.widget.ImageView +import androidx.annotation.DrawableRes +import coil3.executeBlocking +import coil3.imageLoader +import coil3.request.Disposable +import coil3.request.ImageRequest +import coil3.request.error +import coil3.request.placeholder +import coil3.request.target +import coil3.request.transformations +import coil3.size.Size +import coil3.target.Target +import coil3.toBitmap +import coil3.transform.Transformation +import kotlin.math.min +import org.schabi.newpipe.MainActivity +import org.schabi.newpipe.R +import org.schabi.newpipe.extractor.Image +import org.schabi.newpipe.ktx.scale + +object CoilHelper { + private val TAG = CoilHelper::class.java.simpleName + + @JvmOverloads + fun loadBitmapBlocking( + context: Context, + url: String?, + @DrawableRes placeholderResId: Int = 0 + ): Bitmap? = context.imageLoader + .executeBlocking(getImageRequest(context, url, placeholderResId).build()) + .image + ?.toBitmap() + + fun loadAvatar( + target: ImageView, + images: List + ) { + loadImageDefault(target, images, R.drawable.placeholder_person) + } + + fun loadAvatar( + target: ImageView, + url: String? + ) { + loadImageDefault(target, url, R.drawable.placeholder_person) + } + + fun loadThumbnail( + target: ImageView, + images: List + ) { + loadImageDefault(target, images, R.drawable.placeholder_thumbnail_video) + } + + fun loadThumbnail( + target: ImageView, + url: String? + ) { + loadImageDefault(target, url, R.drawable.placeholder_thumbnail_video) + } + + fun loadScaledDownThumbnail( + context: Context, + images: List, + target: Target + ): Disposable { + val url = ImageStrategy.choosePreferredImage(images) + val request = + getImageRequest(context, url, R.drawable.placeholder_thumbnail_video) + .target(target) + .transformations( + object : Transformation() { + override val cacheKey = "COIL_PLAYER_THUMBNAIL_TRANSFORMATION_KEY" + + override suspend fun transform( + input: Bitmap, + size: Size + ): Bitmap { + if (MainActivity.DEBUG) { + Log.d(TAG, "Thumbnail - transform() called") + } + + val notificationThumbnailWidth = + min( + context.resources.getDimension(R.dimen.player_notification_thumbnail_width), + input.width.toFloat() + ).toInt() + + var newHeight = input.height / (input.width / notificationThumbnailWidth) + val result = input.scale(notificationThumbnailWidth, newHeight) + + return if (result == input || !result.isMutable) { + // create a new mutable bitmap to prevent strange crashes on some + // devices (see #4638) + newHeight = input.height / (input.width / (notificationThumbnailWidth - 1)) + input.scale(notificationThumbnailWidth, newHeight) + } else { + result + } + } + } + ).build() + + return context.imageLoader.enqueue(request) + } + + fun loadDetailsThumbnail( + target: ImageView, + images: List + ) { + val url = ImageStrategy.choosePreferredImage(images) + loadImageDefault(target, url, R.drawable.placeholder_thumbnail_video, false) + } + + fun loadBanner( + target: ImageView, + images: List + ) { + loadImageDefault(target, images, R.drawable.placeholder_channel_banner) + } + + fun loadPlaylistThumbnail( + target: ImageView, + images: List + ) { + loadImageDefault(target, images, R.drawable.placeholder_thumbnail_playlist) + } + + fun loadPlaylistThumbnail( + target: ImageView, + url: String? + ) { + loadImageDefault(target, url, R.drawable.placeholder_thumbnail_playlist) + } + + private fun loadImageDefault( + target: ImageView, + images: List, + @DrawableRes placeholderResId: Int + ) { + loadImageDefault(target, ImageStrategy.choosePreferredImage(images), placeholderResId) + } + + private fun loadImageDefault( + target: ImageView, + url: String?, + @DrawableRes placeholderResId: Int, + showPlaceholder: Boolean = true + ) { + val request = + getImageRequest(target.context, url, placeholderResId, showPlaceholder) + .target(target) + .build() + target.context.imageLoader.enqueue(request) + } + + private fun getImageRequest( + context: Context, + url: String?, + @DrawableRes placeholderResId: Int, + showPlaceholderWhileLoading: Boolean = true + ): ImageRequest.Builder { + // if the URL was chosen with `choosePreferredImage` it will be null, but check again + // `shouldLoadImages` in case the URL was chosen with `imageListToDbUrl` (which is the case + // for URLs stored in the database) + val takenUrl = url?.takeIf { it.isNotEmpty() && ImageStrategy.shouldLoadImages() } + + return ImageRequest + .Builder(context) + .data(takenUrl) + .error(placeholderResId) + .memoryCacheKey(takenUrl) + .diskCacheKey(takenUrl) + .apply { + if (takenUrl != null || showPlaceholderWhileLoading) { + placeholder(placeholderResId) + } + } + } +} diff --git a/app/src/main/java/org/schabi/newpipe/util/image/PicassoHelper.java b/app/src/main/java/org/schabi/newpipe/util/image/PicassoHelper.java deleted file mode 100644 index 4b116bdf9..000000000 --- a/app/src/main/java/org/schabi/newpipe/util/image/PicassoHelper.java +++ /dev/null @@ -1,224 +0,0 @@ -package org.schabi.newpipe.util.image; - -import static org.schabi.newpipe.MainActivity.DEBUG; -import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; -import static org.schabi.newpipe.util.image.ImageStrategy.choosePreferredImage; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.graphics.Bitmap; -import android.util.Log; - -import androidx.annotation.DrawableRes; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.core.graphics.BitmapCompat; - -import com.squareup.picasso.Cache; -import com.squareup.picasso.LruCache; -import com.squareup.picasso.OkHttp3Downloader; -import com.squareup.picasso.Picasso; -import com.squareup.picasso.RequestCreator; -import com.squareup.picasso.Transformation; - -import org.schabi.newpipe.R; -import org.schabi.newpipe.extractor.Image; - -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import okhttp3.OkHttpClient; - -public final class PicassoHelper { - private static final String TAG = PicassoHelper.class.getSimpleName(); - private static final String PLAYER_THUMBNAIL_TRANSFORMATION_KEY = - "PICASSO_PLAYER_THUMBNAIL_TRANSFORMATION_KEY"; - - private PicassoHelper() { - } - - private static Cache picassoCache; - private static OkHttpClient picassoDownloaderClient; - - // suppress because terminate() is called in App.onTerminate(), preventing leaks - @SuppressLint("StaticFieldLeak") - private static Picasso picassoInstance; - - - public static void init(final Context context) { - picassoCache = new LruCache(10 * 1024 * 1024); - picassoDownloaderClient = new OkHttpClient.Builder() - .cache(new okhttp3.Cache(new File(context.getExternalCacheDir(), "picasso"), - 50L * 1024L * 1024L)) - // this should already be the default timeout in OkHttp3, but just to be sure... - .callTimeout(15, TimeUnit.SECONDS) - .build(); - - picassoInstance = new Picasso.Builder(context) - .memoryCache(picassoCache) // memory cache - .downloader(new OkHttp3Downloader(picassoDownloaderClient)) // disk cache - .defaultBitmapConfig(Bitmap.Config.RGB_565) - .build(); - } - - public static void terminate() { - picassoCache = null; - picassoDownloaderClient = null; - - if (picassoInstance != null) { - picassoInstance.shutdown(); - picassoInstance = null; - } - } - - public static void clearCache(final Context context) throws IOException { - picassoInstance.shutdown(); - picassoCache.clear(); // clear memory cache - final okhttp3.Cache diskCache = picassoDownloaderClient.cache(); - if (diskCache != null) { - diskCache.delete(); // clear disk cache - } - init(context); - } - - public static void cancelTag(final Object tag) { - picassoInstance.cancelTag(tag); - } - - public static void setIndicatorsEnabled(final boolean enabled) { - picassoInstance.setIndicatorsEnabled(enabled); // useful for debugging - } - - - public static RequestCreator loadAvatar(@NonNull final List images) { - return loadImageDefault(images, R.drawable.placeholder_person); - } - - public static RequestCreator loadAvatar(@Nullable final String url) { - return loadImageDefault(url, R.drawable.placeholder_person); - } - - public static RequestCreator loadThumbnail(@NonNull final List images) { - return loadImageDefault(images, R.drawable.placeholder_thumbnail_video); - } - - public static RequestCreator loadThumbnail(@Nullable final String url) { - return loadImageDefault(url, R.drawable.placeholder_thumbnail_video); - } - - public static RequestCreator loadDetailsThumbnail(@NonNull final List images) { - return loadImageDefault(choosePreferredImage(images), - R.drawable.placeholder_thumbnail_video, false); - } - - public static RequestCreator loadBanner(@NonNull final List images) { - return loadImageDefault(images, R.drawable.placeholder_channel_banner); - } - - public static RequestCreator loadPlaylistThumbnail(@NonNull final List images) { - return loadImageDefault(images, R.drawable.placeholder_thumbnail_playlist); - } - - public static RequestCreator loadPlaylistThumbnail(@Nullable final String url) { - return loadImageDefault(url, R.drawable.placeholder_thumbnail_playlist); - } - - public static RequestCreator loadSeekbarThumbnailPreview(@Nullable final String url) { - return picassoInstance.load(url); - } - - public static RequestCreator loadNotificationIcon(@Nullable final String url) { - return loadImageDefault(url, R.drawable.ic_newpipe_triangle_white); - } - - - public static RequestCreator loadScaledDownThumbnail(final Context context, - @NonNull final List images) { - // scale down the notification thumbnail for performance - return PicassoHelper.loadThumbnail(images) - .transform(new Transformation() { - @Override - public Bitmap transform(final Bitmap source) { - if (DEBUG) { - Log.d(TAG, "Thumbnail - transform() called"); - } - - final float notificationThumbnailWidth = Math.min( - context.getResources() - .getDimension(R.dimen.player_notification_thumbnail_width), - source.getWidth()); - - final Bitmap result = BitmapCompat.createScaledBitmap( - source, - (int) notificationThumbnailWidth, - (int) (source.getHeight() - / (source.getWidth() / notificationThumbnailWidth)), - null, - true); - - if (result == source || !result.isMutable()) { - // create a new mutable bitmap to prevent strange crashes on some - // devices (see #4638) - final Bitmap copied = BitmapCompat.createScaledBitmap( - source, - (int) notificationThumbnailWidth - 1, - (int) (source.getHeight() / (source.getWidth() - / (notificationThumbnailWidth - 1))), - null, - true); - source.recycle(); - return copied; - } else { - source.recycle(); - return result; - } - } - - @Override - public String key() { - return PLAYER_THUMBNAIL_TRANSFORMATION_KEY; - } - }); - } - - @Nullable - public static Bitmap getImageFromCacheIfPresent(@NonNull final String imageUrl) { - // URLs in the internal cache finish with \n so we need to add \n to image URLs - return picassoCache.get(imageUrl + "\n"); - } - - - private static RequestCreator loadImageDefault(@NonNull final List images, - @DrawableRes final int placeholderResId) { - return loadImageDefault(choosePreferredImage(images), placeholderResId); - } - - private static RequestCreator loadImageDefault(@Nullable final String url, - @DrawableRes final int placeholderResId) { - return loadImageDefault(url, placeholderResId, true); - } - - private static RequestCreator loadImageDefault(@Nullable final String url, - @DrawableRes final int placeholderResId, - final boolean showPlaceholderWhileLoading) { - // if the URL was chosen with `choosePreferredImage` it will be null, but check again - // `shouldLoadImages` in case the URL was chosen with `imageListToDbUrl` (which is the case - // for URLs stored in the database) - if (isNullOrEmpty(url) || !ImageStrategy.shouldLoadImages()) { - return picassoInstance - .load((String) null) - .placeholder(placeholderResId) // show placeholder when no image should load - .error(placeholderResId); - } else { - final RequestCreator requestCreator = picassoInstance - .load(url) - .error(placeholderResId); - if (showPlaceholderWhileLoading) { - requestCreator.placeholder(placeholderResId); - } - return requestCreator; - } - } -} diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index ab6e9e345..d8592b905 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -241,7 +241,6 @@ show_memory_leaks_key allow_disposed_exceptions_key show_original_time_ago_key - show_image_indicators_key show_crash_the_player_key check_new_streams crash_the_app_key diff --git a/app/src/main/res/xml/debug_settings.xml b/app/src/main/res/xml/debug_settings.xml index 84bb281f3..d97c5aa1a 100644 --- a/app/src/main/res/xml/debug_settings.xml +++ b/app/src/main/res/xml/debug_settings.xml @@ -34,13 +34,6 @@ app:singleLineTitle="false" app:iconSpaceReserved="false" /> - - 2.8 is the last version, not 2.71828! -picasso = "2.8" preference = "1.2.1" prettytime = "5.0.8.Final" recyclerview = "1.4.0" @@ -91,6 +90,8 @@ androidx-webkit = { module = "androidx.webkit:webkit", version.ref = "webkit" } androidx-work-runtime = { module = "androidx.work:work-runtime", version.ref = "work" } androidx-work-rxjava3 = { module = "androidx.work:work-rxjava3", version.ref = "work" } assertj-core = { module = "org.assertj:assertj-core", version.ref = "assertj" } +coil-compose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coil" } +coil-network-okhttp = { module = "io.coil-kt.coil3:coil-network-okhttp", version.ref = "coil" } evernote-statesaver-compiler = { module = "com.evernote:android-state-processor", version.ref = "statesaver" } evernote-statesaver-core = { module = "com.evernote:android-state", version.ref = "statesaver" } facebook-stetho-core = { module = "com.facebook.stetho:stetho", version.ref = "stetho" } @@ -127,7 +128,6 @@ squareup-leakcanary-core = { module = "com.squareup.leakcanary:leakcanary-androi squareup-leakcanary-plumber = { module = "com.squareup.leakcanary:plumber-android", version.ref = "leakcanary" } squareup-leakcanary-watcher = { module = "com.squareup.leakcanary:leakcanary-object-watcher-android", version.ref = "leakcanary" } squareup-okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } -squareup-picasso = { module = "com.squareup.picasso:picasso", version.ref = "picasso" } zacsweers-autoservice-compiler = { module = "dev.zacsweers.autoservice:auto-service-ksp", version.ref = "autoservice-zacsweers" } [plugins] From 402a0aaaa383349a6091d3b65fc78e3f74a57cf9 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Sat, 21 Feb 2026 16:45:06 +0800 Subject: [PATCH 51/56] Delete unused preference title and summary Signed-off-by: Aayush Gupta --- app/src/main/res/values-ar-rLY/strings.xml | 2 -- app/src/main/res/values-ar/strings.xml | 2 -- app/src/main/res/values-az/strings.xml | 2 -- app/src/main/res/values-be/strings.xml | 2 -- app/src/main/res/values-bg/strings.xml | 2 -- app/src/main/res/values-bn/strings.xml | 1 - app/src/main/res/values-bs/strings.xml | 2 -- app/src/main/res/values-ca/strings.xml | 2 -- app/src/main/res/values-ckb/strings.xml | 2 -- app/src/main/res/values-cs/strings.xml | 2 -- app/src/main/res/values-da/strings.xml | 2 -- app/src/main/res/values-de/strings.xml | 2 -- app/src/main/res/values-el/strings.xml | 2 -- app/src/main/res/values-es/strings.xml | 2 -- app/src/main/res/values-et/strings.xml | 2 -- app/src/main/res/values-eu/strings.xml | 2 -- app/src/main/res/values-fa/strings.xml | 2 -- app/src/main/res/values-fi/strings.xml | 2 -- app/src/main/res/values-fr/strings.xml | 2 -- app/src/main/res/values-gl/strings.xml | 2 -- app/src/main/res/values-he/strings.xml | 2 -- app/src/main/res/values-hi/strings.xml | 2 -- app/src/main/res/values-hr/strings.xml | 2 -- app/src/main/res/values-hu/strings.xml | 2 -- app/src/main/res/values-in/strings.xml | 2 -- app/src/main/res/values-is/strings.xml | 2 -- app/src/main/res/values-it/strings.xml | 2 -- app/src/main/res/values-ja/strings.xml | 2 -- app/src/main/res/values-ka/strings.xml | 2 -- app/src/main/res/values-ko/strings.xml | 2 -- app/src/main/res/values-lt/strings.xml | 2 -- app/src/main/res/values-lv/strings.xml | 2 -- app/src/main/res/values-ml/strings.xml | 2 -- app/src/main/res/values-nb-rNO/strings.xml | 2 -- app/src/main/res/values-nl-rBE/strings.xml | 1 - app/src/main/res/values-nl/strings.xml | 2 -- app/src/main/res/values-nqo/strings.xml | 2 -- app/src/main/res/values-or/strings.xml | 2 -- app/src/main/res/values-pa/strings.xml | 2 -- app/src/main/res/values-pl/strings.xml | 2 -- app/src/main/res/values-pt-rBR/strings.xml | 2 -- app/src/main/res/values-pt-rPT/strings.xml | 2 -- app/src/main/res/values-pt/strings.xml | 2 -- app/src/main/res/values-ro/strings.xml | 2 -- app/src/main/res/values-ru/strings.xml | 2 -- app/src/main/res/values-ryu/strings.xml | 2 -- app/src/main/res/values-sat/strings.xml | 2 -- app/src/main/res/values-sc/strings.xml | 2 -- app/src/main/res/values-sk/strings.xml | 2 -- app/src/main/res/values-so/strings.xml | 2 -- app/src/main/res/values-sr/strings.xml | 2 -- app/src/main/res/values-sv/strings.xml | 2 -- app/src/main/res/values-ta/strings.xml | 2 -- app/src/main/res/values-te/strings.xml | 2 -- app/src/main/res/values-tr/strings.xml | 2 -- app/src/main/res/values-uk/strings.xml | 2 -- app/src/main/res/values-vi/strings.xml | 2 -- app/src/main/res/values-zh-rCN/strings.xml | 2 -- app/src/main/res/values-zh-rHK/strings.xml | 2 -- app/src/main/res/values-zh-rTW/strings.xml | 2 -- app/src/main/res/values/strings.xml | 2 -- 61 files changed, 120 deletions(-) diff --git a/app/src/main/res/values-ar-rLY/strings.xml b/app/src/main/res/values-ar-rLY/strings.xml index e481d6bf7..05e3813d5 100644 --- a/app/src/main/res/values-ar-rLY/strings.xml +++ b/app/src/main/res/values-ar-rLY/strings.xml @@ -299,7 +299,6 @@ %s مشارك جلب البيانات الوصفية… - إظهار مؤشرات الصور انقر للتنزيل %s تعطيل الوضع السريع , @@ -824,7 +823,6 @@ لقد اشتركت الآن في هذه القناة بدءًا من Android 10، يتم دعم \"Storage Access Framework\" فقط إنشاء اسم فريد - أظهر أشرطة ملونة لبيكاسو أعلى الصور تشير إلى مصدرها: الأحمر للشبكة والأزرق للقرص والأخضر للذاكرة فشل الاتصال الآمن يتوفر هذا الفيديو فقط لأعضاء YouTube Music Premium، لذلك لا يمكن بثه أو تنزيله من قبل NewPipe. البث السابق diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index d4e1847f3..8a840f828 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -668,8 +668,6 @@ معاينة مصغرة على شريط التمرير وضع علامة على تمت مشاهدته أُعجب بها منشئ المحتوى - أظهر أشرطة ملونة لبيكاسو أعلى الصور تشير إلى مصدرها: الأحمر للشبكة والأزرق للقرص والأخضر للذاكرة - إظهار مؤشرات الصور اقتراحات البحث عن بعد اقتراحات البحث المحلية اسحب العناصر لإزالتها diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index aec305e72..73ed98d7e 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -490,8 +490,6 @@ Məlumat əldə edilir… Elementlərdə orijinal, əvvəlki vaxtı göstər Yaşam dövrəsi xaricindəki xətaları bildir - Şəkil göstəricilərini göstər - Şəkillərin üzərində mənbəsini göstərən Picasso rəngli lentləri göstər: şəbəkə üçün qırmızı, disk üçün mavi və yaddaş üçün yaşıl Bəzi endirmələri dayandırmaq mümkün olmasa da, mobil dataya keçərkən faydalıdır Bağla Fayl silindiyi üçün irəliləyiş itirildi diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 530d700a7..16c940e6c 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -611,8 +611,6 @@ Перайсці на вэб-сайт Каб выдаліць элемент, змахніце яго ўбок Прыбраць пастаянную мініяцюру - Паказваць на відарысах указальнікі - Паказваць на відарысах каляровыя меткі Picasso, якія абазначаюць яго крыніцу: чырвоная — сетка, сіняя — дыск, зялёная — памяць Апрацоўка стужкі… Пры кожным спампоўванні вам будзе прапанавана выбраць месца захавання Загрузка канала… diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index 22f4b9685..87eee28d9 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -518,7 +518,6 @@ Това видео е с възрастова граница. \n \nВключете „%1$s“ в настройките ако искате да го пуснете. - Покажи цветни Picasso-панделки в горната част на изображенията като индикатор за техния произход (червен – от мрежата, син – от диска и червен – от паметта) Автоматична (тази на устройството) Мащабиране на миниатюрата в известието от 16:9 към 1:1 формат (възможни са изкривявания) Избете плейлист @@ -788,7 +787,6 @@ NewPipe откри грешка, докоснете, за да докладвате Няма потоци Деактивиране на медийното тунелиране - Покажи индикатори за изображения В очакване Неуспешна последваща обработка Прекъсване на мрежи с измерване diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index 9059bd4f5..0d4fbd99c 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -584,7 +584,6 @@ নতুন ধারা কম্পাঙ্ক দেখো পূর্বদর্শন রেখার মাধ্যমে প্রাকদর্শন - ছবিরূপ সূচক দেখাও দেখিও না যেকোনো নেটওয়ার্ক পরেরটা ক্রমে রাখা হয়েছে diff --git a/app/src/main/res/values-bs/strings.xml b/app/src/main/res/values-bs/strings.xml index 6c4b08a72..d422dbe91 100644 --- a/app/src/main/res/values-bs/strings.xml +++ b/app/src/main/res/values-bs/strings.xml @@ -449,8 +449,6 @@ Onemogući tuneliranje medija Onemogućite tuneliranje medija ako se pojavi crni ekran ili se prilikom reprodukcije videa pojavi prekid. Tuneliranje medija je onemogućeno prema zadanim postavkama na vašem uređaju jer je poznato da vaš model uređaja to ne podržava. - Prikaži indikatore slike - Prikažite Picasso obojene trake preko slika koje označavaju njihov izvor: crvena za mrežu, plava za disk i zelena za memoriju Prikaži \"Sruši plejer\" Prikazuje opciju pada sistema prilikom korištenja plejera Pokreni provjeru za nove tokove diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 88d5b2e65..64dd7a4a9 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -621,7 +621,6 @@ No mostris Baixa qualitat (més petit) Alta qualitat (més gran) - Mostra indicadors de la imatge Desactiva l\'entunelament del contingut si en reproduir el vídeos la pantalla se\'n va a negre o s\'entretallen. Mostra detalls del canal No s\'ha establert una carpeta de descàrregues, selecciona la carpeta per defecte ara @@ -665,7 +664,6 @@ Comentari fixat Mostra \"Força el tancament del reproductor\" Mostra una opció de fallada quan s\'utilitza el reproductor - Mostra les cintes de color Picasso a la part superior de les imatges que indiquen la seva font: vermell per a la xarxa, blau per al disc i verd per a la memòria El LeakCanary no està disponible Comprovant freqüència Es necesita una conexió a Internet diff --git a/app/src/main/res/values-ckb/strings.xml b/app/src/main/res/values-ckb/strings.xml index d168bbb37..23baa512c 100644 --- a/app/src/main/res/values-ckb/strings.xml +++ b/app/src/main/res/values-ckb/strings.xml @@ -625,8 +625,6 @@ پیشان نەدرێت کواڵێتی نزم (بچووکتر) کواڵێتی بەرز (گەورەتر) - پیشاندانی شریتە ڕەنگکراوەکانی پیکاسۆ لەسەرووی وێنەکانەوە بۆ بەدیار خستنی سەرچاوەکانیان : سوور بۆ تۆڕ ، شین بۆ دیسک و سەوز بۆ بیرگە - پیشاندانی دیارخەرەکانی وێنە پێشنیازکراوەکانی گەڕانی ڕیمۆت پێشنیازکراوەکانی گەڕانی نێوخۆیی دیارکردن وەک بینراو diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 37e8d70e5..283fb8a7d 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -648,8 +648,6 @@ %s stahování dokončena %s stahováních dokončeno - Zobrazit barevné pásky Picasso na obrázcích označujících jejich zdroj: červená pro síť, modrá pro disk a zelená pro paměť - Zobrazit indikátory obrázků Vzdálené návrhy vyhledávání Lokální návrhy vyhledávání Pokud je vypnuté automatické otáčení, nespouštět video v mini přehrávači, ale přepnout se přímo do režimu celé obrazovky. Do mini přehrávače se lze i nadále dostat ukončením režimu celé obrazovky diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 2be7c8bb8..7b14885e7 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -512,7 +512,6 @@ Behandler… Det kan tage et øjeblik Vis hukommelseslækager Deaktivér medietunneling - Vis billedindikatorer Netværkskrav Alle netværk Kontrolfrekvens @@ -689,7 +688,6 @@ Ofte stillede spørgsmål Hvis du har problemer med at bruge appen, bør du tjekke disse svar på almindelige spørgsmål! Se på hjemmesiden - Vis Picasso-farvede bånd oven på billeder, der angiver deres kilde: rød for netværk, blå for disk og grøn for hukommelse Du kører den nyeste version af NewPipe Grundet ExoPlayer-begrænsninger blev søgevarigheden sat til %d sekunder Vis kun ugrupperede abonnementer diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 6270c658a..b19314f93 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -631,8 +631,6 @@ Aus Als gesehen markieren Vom Ersteller mit Herz versehen - Farbige Picasso-Bänder über den Bildern anzeigen, die deren Quelle angeben: rot für Netzwerk, blau für Festplatte und grün für Speicher - Bildindikatoren anzeigen Entfernte Suchvorschläge Lokale Suchvorschläge diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index b8166905e..17edecb59 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -628,8 +628,6 @@ Προεπισκόπηση στην μπάρα αναζήτησης Σήμανση ως αναπαραχθέν Επισημάνθηκε από τον δημιουργό - Εμφάνιση χρωματιστής κορδέλας πάνω στις εικόνες, που δείχνει την πηγή τους: κόκκινη για δίκτυο, μπλε για δίσκο και πράσινο για μνήμη - Εμφάνιση δεικτών εικόνων Προτάσεις απομακρυσμένης αναζήτησης Προτάσεις τοπικής αναζήτησης diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 1841b6c09..051d90d34 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -631,8 +631,6 @@ Los comentarios están deshabilitados De corazón por el creador Marcar como visto - Mostrar cintas de colores Picasso encima de las imágenes indicando su origen: rojo para la red, azul para el disco y verde para la memoria - Mostrar indicadores de imagen Sugerencias de búsqueda remota Sugerencias de búsqueda local diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index 5d7e829f3..66c7a7151 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -614,8 +614,6 @@ Südamlik autor Kas sinu meelest on voo laadimine aeglane? Sel juhul proovi lubada kiire laadimine (seda saad muuta seadetes või vajutades allolevat nuppu). \n \nNewPipe pakub kahte voo laadimise strateegiat: \n• Tellitud kanali täielik, kuid aeglane hankimine. \n• Teenuse spetsiaalse otspunkti kasutamine, mis on kiire, kuid tavaliselt mittetäielik. \n \nErinevus nende kahe vahel seisneb selles, et kiirel puudub tavaliselt teave, näiteks üksuse pikkus või tüüp (ei saa eristada reaalajas videoid tavalistest) ja see võib tagastada vähem üksusi. \n \nYouTube on näide teenusest, mis pakub seda kiirmeetodit oma RSS-vooga. \n \nNii et valik taandub sellele, mida eelistad: kiirus või täpne teave. Märgi vaadatuks - Näita piltide kohal Picasso värvides riba, mis märgib pildi allikat: punane tähistab võrku, sinine kohalikku andmekandjat ja roheline kohalikku mälu - Näita piltide allikat Kaugotsingu soovitused Kohaliku otsingu soovitused Üksuse eemaldamiseks viipa diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index a34a050fa..f48835460 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -616,8 +616,6 @@ Deskarga amaituta %s deskarga amaituta - Irudien gainean Picasso koloretako zintak erakutsi, jatorria adieraziz: gorria sarerako, urdina diskorako eta berdea memoriarako - Erakutsi irudi-adierazleak Urruneko bilaketa-iradokizunak Tokiko bilaketa-iradokizunak Ikusitako gisa markatu diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index 09a01e0bd..70ea72938 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -592,7 +592,6 @@ رنگی کردن آگاهی گشودن با نشانه به عنوان دیده شده - نمایش روبان‌های رنگی پیکاسو در بالای تصویرها کهنشانگر منبعشان است: قرمز برای شبکه ، آبی برای دیسک و سبز برای حافظه درخواست از اندروید برای سفارشی‌سازی رنگ آگاهی براساس رنگ اصلی در بندانگشتی (توجّه داشته باشید که روی همهٔ افزاره‌ها در دسترس نیست) این ویدیو محدود به سن است. \n @@ -629,7 +628,6 @@ قلب‌شده به دست ایجادگر پیشنهادهای جست‌وجوی محلّی پیشنهادهای جست‌وجوی دوردست - نمایش نشانگرهای تصویر بارگیری پایان یافت %s بارگیری پایان یافتند diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 1ce4df009..ee470a3cc 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -628,8 +628,6 @@ Latauskansiota ei vielä asetettu, valitse ensin oletuslatauskansio Kommentit poistettu käytöstä Merkitse katsotuksi - Näytä Picasso-värjätyt nauhat kuvien päällä osoittaakseen lähteen: punainen tarkoittaa verkkoa, sininen tarkoittaa levytilaa ja vihreä tarkoittaa muistia - Näytä kuvailmaisimet Etähakuehdotukset Paikalliset hakuehdotukset Lisää seuraavaksi diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index f7459e409..85ec148de 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -640,10 +640,8 @@ Prévisualisation de la barre de progression sur la miniature Marquer comme visionné Apprécié par le créateur - Afficher les indicateurs d’image Suggestions de recherche distante Suggestions de recherche locale - Affiche les rubans colorés de Picasso au-dessus des images indiquant leur source : rouge pour le réseau, bleu pour le disque et vert pour la mémoire %1$s téléchargement supprimé %1$s téléchargements supprimés diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index bea6c2eb7..c3873c2a4 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -621,7 +621,6 @@ %s descargas finalizadas Miniatura na barra de busca - Mostrar indicadores de imaxe Desactive o túnel multimedia se experimentar unha pantalla en negro ou interrupcións na reprodución. Desactivar túnel multimedia Engadido á cola @@ -658,7 +657,6 @@ A partir do Android 10, só o \'Sistema de Acceso ao Almacenamento\' está soportado Procesando... Pode devagar un momento Crear unha notificación de erro - Amosar fitas coloridas de Picasso na cima das imaxes que indican a súa fonte: vermello para a rede, azul para o disco e verde para a memoria Novos elementos Predefinido do ExoPlayer Amosar \"Travar o reprodutor\" diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index 3d630394f..cfcf05e6d 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -648,8 +648,6 @@ תמונה מוקטנת בסרגל הנגינה סומן בלב על ידי היוצר סימון כנצפה - הצגת סרטים בסגנון פיקאסו בראש התמונות לציון המקור שלהם: אדום זה מהרשת, כחול מהכונן וירוק מהזיכרון - הצגת מחווני תמונות הצעות חיפוש מרוחקות הצעות חיפוש מקומיות diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 3a5cda8c9..eb04149c6 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -566,7 +566,6 @@ कतारबद्ध हुआ स्ट्रीम विवरण लोड हो रहे हैं… प्रोसेस हो रहा है… कुछ समय लग सकता है - छवि संकेतक दिखाएं प्लेयर का उपयोग करते समय क्रैश विकल्प दिखाता है नई स्ट्रीमों के लिए जांच चलाएं एक त्रुटि स्नैकबार दिखाएं @@ -663,7 +662,6 @@ लीक-कैनरी उपलब्ध नहीं है एक त्रुटी हुई है, नोटीफिकेशन देखें यदि वीडियो प्लेबैक पर आप काली स्क्रीन या रुक-रुक कर वीडियो चलने का अनुभव करते हैं तो मीडिया टनलिंग को अक्षम करें। - छवियों के शीर्ष पर पिकासो रंगीन रिबन दिखाएँ जो उनके स्रोत को दर्शाता है: नेटवर्क के लिए लाल, डिस्क के लिए नीला और मेमोरी के लिए हरा त्रुटी की नोटीफिकेशन बनाएं इस डाउनलोड को पुनर्प्राप्त नहीं किया जा सकता अभी तक कोई डाउनलोड फ़ोल्डर सेट नहीं किया गया है, अब डिफ़ॉल्ट डाउनलोड फ़ोल्डर चुनें diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index f9f95db72..28412795e 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -640,7 +640,6 @@ Sada možeš odabrati tekst u opisu. Napomena: stranica će možda treperiti i možda nećeš moći kliknuti poveznice u načinu rada za odabir teksta. Obrada u tijeku … Može malo potrajati Za ukljanjanje stavki povuci ih - Prikaži indikatore slike %s preuzimanje je gotovo %s preuzimanja su gotova @@ -649,7 +648,6 @@ Pokreni glavni player u cjeloekranskom prikazu Dodaj u popis kao sljedeći Dodano u popis kao sljedeći - Prikaži Picassove vrpce u boji na slikama koje označavaju njihov izvor: crvena za mrežu, plava za disk i zelena za memoriju Izbrisano %1$s preuzimanje Izbrisana %1$s preuzimanja diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 1110fd248..691e31567 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -550,7 +550,6 @@ Az eltávolítás utáni, fragment vagy activity életcikluson kívüli, nem kézbesíthető Rx kivételek jelentésének kényszerítése Eredeti „ennyi ideje” megjelenítése az elemeken Tiltsa le a médiacsatornázást, ha fekete képernyőt vagy akadozást tapasztal videólejátszáskor. - Picasso színes szalagok megjelenítése a képek fölött, megjelölve a forrásukat: piros a hálózathoz, kék a lemezhez, zöld a memóriához Minden letöltésnél meg fogja kérdezni, hogy hova mentse el Válasszon egy példányt Hírfolyam utoljára frissítve: %s @@ -624,7 +623,6 @@ A lejátszási listához való hozzáadás előtt és után megtekintett közvetítések el lesznek távolítva.\nBiztos benne? A szolgáltatásokból származó eredeti szövegek láthatók lesznek a közvetítési elemeken Lejátszó összeomlasztása - Képjelölők megjelenítése A „Lejátszó összeomlasztása” lehetőség megjelenítése Megjeleníti az összeomlasztási lehetőséget a lejátszó használatakor Hangmagasság megtartása (torzítást okozhat) diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index d023e9fb3..eafd00e8d 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -625,13 +625,11 @@ Disukai oleh kreator Saran pencarian lokal Saran pencarian remote - Tampilkan indikator gambar Menghapus %1$s unduhan tambahkan ke selanjutnya telah ditambahkan ke selanjutnya - Tampilkan Ribon bewarna Picasso di atas gambar yang mengindikasikan asalnya: merah untuk jaringan, biru untuk disk dan hijau untuk memori Jangan memulai memutar video di mini player, tapi nyalakan langsung di mode layar penuh, jika rotasi otomatis terkunci. Anda tetap dapat mengakses mini player dengan keluar dari layar penuh Memproses… Mungkin butuh waktu sebentar Periksa Pembaruan diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml index 029c411ef..aa8c2e72c 100644 --- a/app/src/main/res/values-is/strings.xml +++ b/app/src/main/res/values-is/strings.xml @@ -637,8 +637,6 @@ Upprunalegir textar frá þjónustu verða sýnilegir í streymisatriðum Slökkva á margmiðlagöngum Slökktu á margmiðlunargöngum (media tunneling) ef vart verður við svartan skjá eða hökt við spilun myndskeiða. - Sýna myndvísa - Sýna Picasso litaða borða ofan á myndum sem gefa til kynna uppruna þeirra: rauðan fyrir netið, bláan fyrir disk og grænan fyrir minni Sýna „Láta spilara hrynja\" Sýna valkost til að hrynja spilara Hrynja forrit diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 3a3995b14..c3e513079 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -638,8 +638,6 @@ Commenti disattivati Apprezzato dall\'autore Segna come visto - Mostra gli indicatori colorati Picasso sopra le immagini, per indicare la loro fonte: rosso per la rete, blu per il disco e verde per la memoria - Mostra indicatori immagine Suggerimenti di ricerca remoti Suggerimenti di ricerca locali diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index ac9fe3684..b0be85292 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -628,8 +628,6 @@ %s 個のダウンロードが完了しました - ピカソは、画像の上に、画像の出所を識別する色彩記章を表示します: 赤はネットワーク、青はディスク、緑はメモリ - 画像に標識を表示 処理中… 少し時間がかかるかもしれません 新しいバージョンを手動で確認します アップデートを確認中… diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml index 444625fc0..98b5e2475 100644 --- a/app/src/main/res/values-ka/strings.xml +++ b/app/src/main/res/values-ka/strings.xml @@ -380,7 +380,6 @@ ორიგინალური ტექსტები სერვისებიდან ხილული იქნება ნაკადის ერთეულებში მედია გვირაბის გათიშვა გამორთეთ მედია გვირაბი, თუ ვიდეოს დაკვრისას შავი ეკრანი ან ჭუჭყი გაქვთ - გამოსახულების ინდიკატორების ჩვენება აჩვენე \"დამკვრელის დამსხვრევა\" აჩვენებს ავარიის ვარიანტს დამკვრელის გამოყენებისას გაუშვით შემოწმება ახალი ნაკადებისთვის @@ -677,7 +676,6 @@ გამოწერების იმპორტი ვერ მოხერხდა შეატყობინეთ სასიცოცხლო ციკლის შეცდომებს იძულებითი მოხსენება შეუსაბამო Rx გამონაკლისების შესახებ ფრაგმენტის ან აქტივობის სასიცოცხლო ციკლის გარეთ განკარგვის შემდეგ - აჩვენეთ პიკასოს ფერადი ლენტები სურათების თავზე, სადაც მითითებულია მათი წყარო: წითელი ქსელისთვის, ლურჯი დისკისთვის და მწვანე მეხსიერებისთვის სწრაფი კვების რეჟიმი ამაზე მეტ ინფორმაციას არ იძლევა. „%s“-ის არხის ჩატვირთვა ვერ მოხერხდა. ხელმისაწვდომია ზოგიერთ სერვისში, როგორც წესი, ბევრად უფრო სწრაფია, მაგრამ შეიძლება დააბრუნოს შეზღუდული რაოდენობის ელემენტი და ხშირად არასრული ინფორმაცია (მაგ. ხანგრძლივობის გარეშე, ელემენტის ტიპი, არ არის ლაივის სტატუსი) diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 59832ece4..079dc45b4 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -541,8 +541,6 @@ 미디어 터널링 비활성화 서비스의 원본 텍스트가 스트림 항목에 표시됩니다 동영상 재생 시 검은 화면이 나타나거나 끊김 현상이 발생하면 미디어 터널링을 비활성화하세요. - 이미지 표시기 표시 - 원본을 나타내는 이미지 위에 피카소 컬러 리본 표시: 네트워크는 빨간색, 디스크는 파란색, 메모리는 녹색 \"플레이어 충돌\" 표시 플레이어를 사용할 때 충돌 옵션을 표시합니다 새로운 스트림 확인 실행 diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index dd7874809..d43a69fb0 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -638,8 +638,6 @@ Nerodyti Širdelė nuo kurėjo Pažymėti kaip peržiūrėtą - Rodyti „Picasso“ spalvotas juosteles ant vaizdų, nurodančių jų šaltinį: raudona tinklui, mėlyna diskui ir žalia atmintis - Rodyti vaizdo indikatorius Nuotolinės paieškos pasiūlymai Vietinės paieškos pasiūlymai diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml index 45d126183..e474f606c 100644 --- a/app/src/main/res/values-lv/strings.xml +++ b/app/src/main/res/values-lv/strings.xml @@ -612,12 +612,10 @@ Nesākt video atskaņošanu samazinātā režīmā, bet pilnekrāna režīmā, ja automātiskā rotācija ir izslēgta Izslēgt multivides tuneļošanu Izslēdziet multivides tuneļošanu, ja jums video atskaņošanas laikā parādās melns ekrāns vai aizķeršanās. - Rādīt krāsainas lentes virs attēliem, norādot to avotu: sarkana - tīkls, zila - disks, zaļa - atmiņa Ieslēgt teksta atlasīšanu video aprakstā Lejupielādes mape vēl nav iestatīta, izvēlieties noklusējuma lejupielādes mapi Pavelciet atlasīto elementu pa kreisi vai labi, lai to aizvāktu Lokālie meklēšanas ieteikumi - Rādīt attēlu indikatorus Augstas kvalitātes (lielāks) Pārbaudīt atjauninājumus Pašrocīgi pārbaudīt jaunas versijas pieejamību diff --git a/app/src/main/res/values-ml/strings.xml b/app/src/main/res/values-ml/strings.xml index a149b910b..013802176 100644 --- a/app/src/main/res/values-ml/strings.xml +++ b/app/src/main/res/values-ml/strings.xml @@ -590,7 +590,6 @@ രണ്ടാം പ്രവർത്തന ബട്ടൺ ആദ്യ പ്രവർത്തന ബട്ടൺ വീഡിയോ കാണുമ്പോൾ കറുത്ത സ്ക്രീൻ, അവ്യക്തത അനുഭവിക്കുന്നു എങ്കിൽ മീഡിയ ട്യൂൺലിങ് പ്രവർത്തനരഹിതമാക്കുക - ഉറവിടം തിരിച്ചറിയാൻ പിക്കാസോ കളർഡ് റിബൺ ചിത്രങ്ങളുടെ മുകളിൽ കാണിക്കുക: നെറ്റ്‌വർക്കിന് ചുവപ്പ്, ഡിസ്കിനു നീല, മെമ്മറിയിക്ക് പച്ച സീക്ബാർ ചെറുചിത്രം പ്രദർശനം സ്നേഹത്തോടെ സൃഷ്ടാവ് ഡിസ്ക്രിപ്ഷനിലെ ടെക്സ്റ്റ്‌ സെലക്ട്‌ ചെയ്യുവാൻ അനുവദിക്കാതെ ഇരിക്കുക @@ -624,7 +623,6 @@ കാണിക്കരുത് കുറഞ്ഞ നിലവാരം (ചെറുത് ) ഉയർന്ന നിലവാരം (വലിയത് ) - ഇമേജ് ഇൻഡിക്കേറ്ററുകൾ കാണിക്കുക മീഡിയ ട്യൂൺലിങ് പ്രവർത്തനരഹിതമാക്കുക ഡൌൺലോഡ് ഫോൾഡർ ഇത് വരെയും സെറ്റ് ചെയ്തിട്ടില്ല, സ്ഥിര ഡൌൺലോഡ് ഫോൾഡർ ഇപ്പോൾ തിരഞ്ഞെക്കുക അഭിപ്രായങ്ങൾ പ്രവർത്തനരഹിതമായിരിക്കുന്നു diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 633140dcc..7d25bf847 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -638,9 +638,7 @@ Lokale søkeforslag Marker som sett Ikke start videoer i minispilleren, men bytt til fullskjermsmodus direkte dersom auto-rotering er låst. Du har fremdeles tilgang til minispilleren ved å avslutte fullskjermsvisningen - Vis Picasso-fargede bånd på toppen av bilder for å indikere kilde: Rød for nettverk, blå for disk, og grønn for minne Hjertemerket av skaperen - Vis bildeindikatorer Dra elementer for å fjerne dem Start hovedspiller i fullskjerm Still i kø neste diff --git a/app/src/main/res/values-nl-rBE/strings.xml b/app/src/main/res/values-nl-rBE/strings.xml index 92d36ab77..237e9238c 100644 --- a/app/src/main/res/values-nl-rBE/strings.xml +++ b/app/src/main/res/values-nl-rBE/strings.xml @@ -606,7 +606,6 @@ Geen download map ingesteld, kies nu de standaard download map Niet tonen Reacties zijn uitgeschakeld - Toon afbeeldingsindicatoren Speler melding Configureer actieve stream melding Meldingen diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 845e7431c..2ff13b391 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -626,8 +626,6 @@ Lage kwaliteit (kleiner) Hoge kwaliteit (groter) Zoekbalk miniatuurafbeelding voorbeeld - Toon Picasso-gekleurde linten bovenop afbeeldingen die hun bron aangeven: rood voor netwerk, blauw voor schijf en groen voor geheugen - Afbeeldings­indicatoren tonen Reacties zijn uitgeschakeld Zoeksuggesties op afstand Lokale zoeksuggesties diff --git a/app/src/main/res/values-nqo/strings.xml b/app/src/main/res/values-nqo/strings.xml index abf7ad70d..ee17b0921 100644 --- a/app/src/main/res/values-nqo/strings.xml +++ b/app/src/main/res/values-nqo/strings.xml @@ -436,8 +436,6 @@ ߗߋߢߊߟߌ ߟߎ߬ ߞߟߏߜߍ߫ ߓߐߛߎ߲ߡߊ ߟߎ߬ ߦߌ߬ߘߊ߬ߕߐ߫ ߟߋ߬ ߟߊ߬ߖߍ߲߬ߛߍ߲߬ߠߌ߲ ߘߐ߫ ߞߋߟߋߞߋߟߋ ߟߊ߫ ߝߊߟߊ߲ߓߍߦߊ ߟߊߛߊ߬ ߞߋߟߋߞߋߟߋ ߟߊ߫ ߝߊߟߊ߲ߓߍߦߊ ߟߊߛߊ߬ ߣߴߌ ߞߊ߬ ߥߊ߲߬ߊߥߊ߲߬ ߝߌ߲ ߦߋ߫ ߥߟߊ߫ ߜߊߘߊ߲ߜߊߘߊ߲ߠߌ߲ ߦߋߡߍ߲ߕߊ ߘߏ߫ ߘߐߛߊߙߌ߫ ߕߎߡߊ - ߞߊ߬ ߖߌ߬ߦߊ߬ߓߍ߫ ߦߌ߬ߘߊ߬ߟߊ߲ ߠߎ߫ ߝߍ߲߬ߛߍ߲߫ - ߏ߬ ߦߋ߫ ߔߌߛߊߞߏ߫ ߟߊ߫ ߡߙߎߝߋ߫ ߞߟߐ߬ߡߊ ߟߎ߫ ߟߋ߬ ߝߍ߲߬ߛߍ߲߬ ߠߊ߫ ߖߌ߬ߦߊ߬ߓߍ ߟߎ߫ ߞߎ߲߬ߘߐ߫ ߞߵߊ߬ߟߎ߬ ߓߐߛߎ߲ ߦߌ߬ߘߊ߬: ߥߎߟߋ߲߬ߡߊ߲ ߦߋ߫ ߞߙߏ߬ߝߏ ߕߊ ߘߌ߫߸ ߓߊ߯ߡߊ ߦߋ߫ ߝߘߍ߬ ߜߍߟߍ߲ ߕߊ ߘߌ߫ ߊ߬ߣߌ߫ ߝߙߌߛߌߡߊ ߦߋ߫ ߦߟߌߕߏߟߊ߲ ߕߊ ߘߌ߫ ߟߊ߬ߓߐ߬ߟߌ ߦߴߌߘߐ߫… ߞߵߊ߬ ߘߊߡߌ߬ߣߊ߬ ߞߊ߲߬ߞߎߡߊ ߟߎ߬ ߟߊߛߊ߬ߣߍ߲ ߠߋ߬ diff --git a/app/src/main/res/values-or/strings.xml b/app/src/main/res/values-or/strings.xml index c9d0e6758..57459de10 100644 --- a/app/src/main/res/values-or/strings.xml +++ b/app/src/main/res/values-or/strings.xml @@ -340,7 +340,6 @@ ସେବାଗୁଡିକରୁ ମୂଳ ଲେଖା ଷ୍ଟ୍ରିମ୍ ଆଇଟମ୍ ଗୁଡିକରେ ଦୃଶ୍ୟମାନ ହେବ ମିଡିଆ ଟନେଲିଂକୁ ଅକ୍ଷମ କରନ୍ତୁ ଯଦି ଆପଣ ଏକ କଳା ପରଦା ଅନୁଭବ କରନ୍ତି କିମ୍ବା ଭିଡିଓ ପ୍ଲେବେକ୍ ଉପରେ ଝୁଣ୍ଟି ପଡ଼ନ୍ତି ତେବେ ମିଡିଆ ଟନେଲିଂକୁ ଅକ୍ଷମ କରନ୍ତୁ । - ଚିତ୍ରଗୁଡ଼ିକର ଉପରେ ପିକାସୋ ରଙ୍ଗୀନ ଫିତା ଦେଖାନ୍ତୁ: ସେମାନଙ୍କର ଉତ୍ସକୁ ସୂଚାଇଥାଏ: ନେଟୱାର୍କ ପାଇଁ ନାଲି, ଡିସ୍କ ପାଇଁ ନୀଳ ଏବଂ ସ୍ମୃତି ପାଇଁ ସବୁଜ ଆମଦାନି କରନ୍ତୁ ଠାରୁ ଆମଦାନୀ କରନ୍ତୁ ଆମଦାନି… @@ -651,7 +650,6 @@ ଅଟୋ-ଜେନେରେଟ୍ (କୌଣସି ଅପଲୋଡର୍ ମିଳିଲା ନାହିଁ) ପୁରଣ କରନ୍ତୁ କ୍ୟାପସନ୍ - ପ୍ରତିଛବି ସୂଚକ ଦେଖାନ୍ତୁ ପ୍ଲେୟାର ବ୍ୟବହାର କରିବା ସମୟରେ ଏକ କ୍ରାସ୍ ବିକଳ୍ପ ଦେଖାଏ ନୂତନ ଷ୍ଟ୍ରିମ୍ ପାଇଁ ଯାଞ୍ଚ ଚଲାନ୍ତୁ ଆପ୍ କ୍ରାସ୍ କରନ୍ତୁ diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml index 8c69dd850..cc0be8ae4 100644 --- a/app/src/main/res/values-pa/strings.xml +++ b/app/src/main/res/values-pa/strings.xml @@ -602,8 +602,6 @@ ਨਿਊਪਾਈਪ ਖਾਮੀ ਤੋਂ ਪ੍ਰਭਾਵਤ ਹੋਈ ਹੈ, ਇੱਥੇ ਨੱਪ ਕੇ ਰਿਪੋਰਟ ਕਰੋ ਇੱਕ ਖਾਮੀ ਪ੍ਰਭਾਵੀ ਹੋਈ ਹੈ, ਨੋਟੀਫੀਕੇਸ਼ਨ ਵੇਖੋ ਆਈਟਮਾਂ ਨੂੰ ਇੱਕ ਪਾਸੇ ਖਿੱਚ ਕੇ ਹਟਾਓ - ਦ੍ਰਿਸ਼ ਸੂਚਕ ਵਿਖਾਓ - ਦ੍ਰਿਸ਼ਾਂ ਦੇ ਉੱਪਰ ਉਹਨਾਂ ਦੀ ਸਰੋਤ-ਪਛਾਣ ਲਈ ਪਿਕਾਸੋ ਦੇ ਰੰਗਦਾਰ ਰਿਬਨ ਵਿਖਾਓ : ਨੈੱਟਵਰਕ ਲਈ ਲਾਲ, ਡਿਸਕ ਲਈ ਨੀਲੇ ਤੇ ਮੈਮਰੀ ਲਈ ਹਰੇ ਨਵੀਂ ਸਟ੍ਰੀਮ ਦੇ ਨੋਟੀਫਿਕੇਸ਼ਨ ਪਿੰਨ ਕੀਤੀ ਟਿੱਪਣੀ ਅੱਪਡੇਟ ਦੀ ਉਪਲੱਬਧਤਾ ਪਰਖੀ ਜਾ ਰਹੀ… diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 910b11044..60dab077d 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -643,8 +643,6 @@ Nie pokazuj Serduszko od twórcy Oznacz jako obejrzane - 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 1cbfa6947..595fa9613 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -638,7 +638,6 @@ Os comentários estão desabilitados Marcar como assistido Curtido pelo criador - Exibir fitas coloridas no topo das imagens indicando sua fonte: vermelho para rede, azul para disco e verde para memória %1$s download excluído %1$s downloads excluídos @@ -649,7 +648,6 @@ %s downloads concluídos %s downloads concluídos - Mostrar indicadores de imagem Adicionado na próxima posição da fila Enfileira a próxima Deslize os itens para remove-los diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index f6e1b5a67..f14d2e402 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -638,8 +638,6 @@ Ainda não foi definida uma pasta de descarregamento, escolha agora a pasta de descarregamento padrão Comentários estão desativados Marcar como visto - Mostrar fitas coloridas de Picasso em cima das imagens que indicam a sua fonte: vermelho para rede, azul para disco e verde para memória - Mostrar indicadores de imagem Sugestões de pesquisa remotas Sugestões de pesquisa locais diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 8e0210dbc..b3d8fe7b4 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -638,8 +638,6 @@ Baixa qualidade (menor) Alta qualidade (maior) Os comentários estão desativados - Mostrar fitas coloridas de Picasso em cima das imagens que indicam a sua fonte: vermelho para rede, azul para disco e verde para memória - Mostrar indicadores de imagem Sugestões de pesquisa remotas Sugestões de pesquisa locais diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 2afe73875..c5c450894 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -654,8 +654,6 @@ Calitate scăzută (mai mică) Calitate înaltă (mai mare) Miniatură de previzualizare în bara de derulare - Afișați panglici colorate de Picasso deasupra imaginilor, indicând sursa acestora: roșu pentru rețea, albastru pentru disc și verde pentru memorie - Afișați indicatorii de imagine Dezactivați tunelarea media dacă întâmpinați un ecran negru sau blocaje la redarea video. Procesarea.. Poate dura un moment Verifică dacă există actualizări diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index fc32c0da3..b3f92f167 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -646,8 +646,6 @@ Миниатюра над полосой прокрутки Автору видео понравилось это Пометить проигранным - Picasso: указать цветом источник изображений (красный — сеть, синий — диск, зелёный — память) - Цветные метки на изображениях Серверные предложения поиска Локальные предложения поиска diff --git a/app/src/main/res/values-ryu/strings.xml b/app/src/main/res/values-ryu/strings.xml index 4be7d5328..f5b40be83 100644 --- a/app/src/main/res/values-ryu/strings.xml +++ b/app/src/main/res/values-ryu/strings.xml @@ -640,8 +640,6 @@ %sちぬダウンロードぬかんりょうさびたん %sちぬダウンロードぬかんりょうさびたん - ピカソー、がぞうぬういに、がぞうくとぅどぅくるしーきびちするしきさいきしーょうひょうじさびーん: あかーネットワーク、あおーディスク、みどぅれーメモリ - やしがぞうんかいふぃいょうしきひょうじ しーょりちゅう… くーてーんじがんがかかいんかむしりやびらん みーさるバージョンしーゅどうでぃかくにんさびーん アップデートかくにんちゅう… diff --git a/app/src/main/res/values-sat/strings.xml b/app/src/main/res/values-sat/strings.xml index 71a8067b1..47ac2c53d 100644 --- a/app/src/main/res/values-sat/strings.xml +++ b/app/src/main/res/values-sat/strings.xml @@ -268,7 +268,6 @@ LeakCanary ᱵᱟᱭ ᱧᱟᱢᱚᱜ ᱠᱟᱱᱟ ᱢᱮᱢᱚᱨᱤ ᱞᱤᱠᱟᱞ ᱢᱚᱱᱤᱴᱚᱨᱤᱝ ᱦᱤᱯ ᱰᱟᱢᱯᱤᱝ ᱚᱠᱛᱚ ᱨᱮ ᱮᱯᱞᱤᱠᱮᱥᱚᱱ ᱨᱟᱥᱴᱨᱤᱭ ᱦᱩᱭ ᱫᱟᱲᱮᱭᱟᱜ-ᱟ ᱡᱤᱭᱚᱱ ᱪᱤᱠᱤ ᱠᱷᱚᱱ ᱵᱟᱦᱨᱮ ᱨᱮ ᱵᱷᱮᱜᱟᱨ ᱠᱚ ᱚᱱᱚᱞ ᱢᱮ - ᱱᱮᱴᱣᱟᱨᱠ ᱞᱟᱹᱜᱤᱫ red, ᱰᱤᱥᱠ ᱞᱟᱹᱜᱤᱫ blue ᱟᱨ ᱢᱮᱢᱚᱨᱤ ᱞᱟᱹᱜᱤᱫ green ᱯᱞᱮᱭᱟᱨ ᱵᱮᱵᱷᱟᱨ ᱚᱠᱛᱮ ᱨᱮ ᱠᱨᱟᱥ ᱚᱯᱥᱚᱱ ᱧᱮᱞᱚᱜ ᱠᱟᱱᱟ ᱤᱢᱯᱳᱨᱴ ᱤᱢᱯᱚᱨᱴ @@ -535,7 +534,6 @@ ᱡᱤᱱᱤᱥ ᱠᱚᱨᱮᱱᱟᱜ ᱢᱩᱞ ᱚᱠᱛᱚ ᱧᱮᱞ ᱢᱮ ᱥᱮᱵᱟ ᱠᱷᱚᱱ ᱚᱨᱡᱤᱱᱤᱭᱟᱞ ᱴᱮᱠᱥᱴ ᱠᱚ ᱥᱴᱨᱤᱢ ᱤᱴᱮᱢ ᱨᱮ ᱧᱮᱞᱚᱜᱼᱟ ᱡᱩᱫᱤ ᱟᱢ ᱵᱷᱤᱰᱤᱭᱳ ᱯᱞᱮᱭᱚᱯ ᱨᱮ ᱵᱞᱮᱠ ᱥᱠᱨᱤᱱ ᱟᱨᱵᱟᱝ ᱠᱷᱟᱹᱞᱤ ᱥᱴᱮᱴᱞᱤᱝ ᱮᱢ ᱧᱟᱢᱟ ᱮᱱᱠᱷᱟᱱ ᱢᱤᱰᱤᱭᱟ ᱴᱩᱱᱮᱞᱤᱝ ᱵᱚᱫᱚᱞ ᱢᱮ ᱾ - ᱪᱤᱛᱟᱹᱨ ᱪᱤᱱᱦᱟᱹ ᱠᱚ ᱧᱮᱞ ᱢᱮ ᱱᱟᱣᱟ ᱥᱴᱨᱤᱢ ᱞᱟᱹᱜᱤᱫ ᱪᱟᱪᱞᱟᱣ ᱢᱮ ᱢᱤᱫ error notification ᱛᱮᱭᱟᱨ ᱢᱮ ᱥᱮᱞᱮᱫ ᱮᱠᱥᱯᱳᱨᱴ ᱵᱟᱝ ᱦᱩᱭ ᱫᱟᱲᱮᱭᱟᱜ ᱠᱟᱱᱟ diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml index f47e8e569..5f5887f5f 100644 --- a/app/src/main/res/values-sc/strings.xml +++ b/app/src/main/res/values-sc/strings.xml @@ -628,8 +628,6 @@ Sos cummentos sunt disabilitados Su creadore b\'at postu unu coro Marca comente pompiadu - Ammustra sos listrones colorados de Picasso in subra de sas immàgines chi indicant sa fonte issoro: ruja pro sa retze, biaita pro su discu e birde pro sa memòria - Ammustra sos indicadores de immàgines Impòsitos de chirca remota Impòsitos de chirca locales diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index ff6cd720a..27f34c9db 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -648,8 +648,6 @@ Nízka kvalita (menšie) Vysoká kvalita (väčšie) Náhľad miniatúry pri vyhľadávaní - Zobrazí farebné pásiky Picasso na obrázkoch podľa ich zdroja: červený pre sieť, modrý pre disk a zelený pre pamäť - Zobraziť indikátory obrázka Potiahnutím vymazať Komentáre sú zakázané Ak je automatické otáčanie zablokované, nespustí videá v miniprehrávači, ale prepne sa do celoobrazovkového režimu. Do miniprehrávača sa dostanete po ukončení režimu celej obrazovky diff --git a/app/src/main/res/values-so/strings.xml b/app/src/main/res/values-so/strings.xml index 22d5fe16f..dc2a89c9c 100644 --- a/app/src/main/res/values-so/strings.xml +++ b/app/src/main/res/values-so/strings.xml @@ -627,8 +627,6 @@ Fallooyinka waa laxidhay Kahelay soosaaraha Waan daawaday - Soo bandhig shaambado midabka Picasso leh sawirrada dushooda oo tilmaamaya isha laga keenay: guduud waa khadka, buluug waa kaydka gudaha, cagaar waa kaydka K/G - Tus tilmaamayaasha sawirka Soojeedinada raadinta banaanka Soojeedinada raadinta gudaha Cabirka soodaarida udhexeeya diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 2d14361b3..33126a211 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -638,7 +638,6 @@ Означи као одгледано Коментари су онемогућени Обрађивање… Може потрајати пар тренутака - Прикажи индикаторе слике Не покрећите видео снимке у мини-плејеру, већ директно пређите на режим целог екрана, ако је аутоматска ротација закључана. И даље можете приступити мини-плејеру тако што ћете изаћи из целог екрана Покрени главни плејер преко целог екрана Срушите плејер @@ -734,7 +733,6 @@ Обавештења за пријаву грешака Увезите или извезите праћења из менија са 3 тачке Аудио снимак - Прикажите Picasso обојене траке на врху слика које указују на њихов извор: црвена за мрежу, плава за диск и зелена за меморију Направите обавештење о грешци Проценат Користите најновију верзију NewPipe-а diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index d9742c80e..1e58d2184 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -627,7 +627,6 @@ Du kan välja det natt-tema du föredrar nedan Välj det natt-tema du föredrar — %s Sökradens förhandsvisningsminiatyr - Visa bildindikatorer Lokala sökningsförslag Tog bort %1$s nedladdning @@ -645,7 +644,6 @@ Svep objekt för att ta bort dem Förslag via fjärrsökning Starta inte videor i minispelaren, utan byt till helskärmsläge direkt, om automatisk rotation är låst. Du kan fortfarande komma åt minispelaren genom att gå ut ur helskärmsläge - Visa Picasso färgade band ovanpå bilderna som anger deras källa: rött för nätverk, blått för disk och grönt för minne Sök efter uppdateringar Kolla manuellt efter nya versioner Söker efter uppdateringar… diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml index 068a099d2..86dd3cc43 100644 --- a/app/src/main/res/values-ta/strings.xml +++ b/app/src/main/res/values-ta/strings.xml @@ -641,8 +641,6 @@ மீடியா சுரங்கப்பாதையை முடக்கு நீங்கள் ஒரு கருப்பு திரை அனுபவித்தால் அல்லது வீடியோ பிளேபேக்கில் திணறினால் மீடியா சுரங்கப்பாதையை முடக்கு. உங்கள் சாதனத்தில் முன்னிருப்பாக மீடியா சுரங்கப்பாதை முடக்கப்பட்டது, ஏனெனில் உங்கள் சாதன மாதிரி அதை ஆதரிக்காது என்று அறியப்படுகிறது. - பட குறிகாட்டிகளைக் காட்டு - அவற்றின் மூலத்தைக் குறிக்கும் படங்களின் மேல் பிக்காசோ வண்ண ரிப்பன்களைக் காட்டு: நெட்வொர்க்கிற்கு சிவப்பு, வட்டுக்கு நீலம் மற்றும் நினைவகத்திற்கு பச்சை \"வீரரை செயலிழக்க\" காட்டு பிளேயரைப் பயன்படுத்தும் போது செயலிழப்பு விருப்பத்தைக் காட்டுகிறது புதிய நீரோடைகளுக்கு காசோலை இயக்கவும் diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml index b95e04c0c..a422dc996 100644 --- a/app/src/main/res/values-te/strings.xml +++ b/app/src/main/res/values-te/strings.xml @@ -438,7 +438,6 @@ ప్లేబ్యాక్ స్పీడ్ నియంత్రణలు ఏమిలేదు మీరు బ్లాక్ స్క్రీన్ లేదా చలనచిత్రం ప్లేబ్యాక్‌లో అంతరాయాన్ని అనుభవిస్తే మీడియా టన్నెలింగ్‌ను నిలిపివేయండి - చిత్రాల మూలాన్ని సూచించే విధంగా వాటి పైభాగంలో పికాసో రంగు రిబ్బన్‌లను చూపండి: నెట్‌వర్క్ కోసం ఎరుపు, డిస్క్ కోసం నీలం మరియు మెమరీ కోసం ఆకుపచ్చ లోపం స్నాక్‌బార్‌ని చూపండి మీరు NewPipe యొక్క తాజా సంస్కరణను అమలు చేస్తున్నారు NewPipe నవీకరణ అందుబాటులో ఉంది! @@ -451,7 +450,6 @@ తక్కువ నాణ్యత (చిన్నది) చూపించవద్దు మీడియా టన్నెలింగ్‌ని నిలిపివేయండి - చిత్ర సూచికలను చూపు కొత్త స్ట్రీమ్‌ల కోసం తనిఖీని అమలు చేయండి ఎర్రర్ నోటిఫికేషన్‌ను సృష్టించండి దిగుమతి diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 9c84ee81d..76215fa0d 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -627,8 +627,6 @@ Yorumlar devre dışı Yaratıcısınca kalplendi İzlendi olarak işaretle - Resimlerin üzerinde kaynaklarını gösteren Picasso renkli şeritler göster: ağ için kırmızı, disk için mavi ve bellek için yeşil - Resim göstergelerini göster Uzak arama önerileri Yerel arama önerileri diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index df8ee490d..c6dcdbdc1 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -640,8 +640,6 @@ Мініатюра з попереднім переглядом на повзунку поступу Вподобано автором Позначити переглянутим - Показувати кольорові стрічки Пікассо поверх зображень із зазначенням їх джерела: червоний для мережі, синій для диска та зелений для пам’яті - Показати індикатори зображень Віддалені пропозиції пошуку Локальні пошукові пропозиції diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index efa12f11d..e43b2f5df 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -618,8 +618,6 @@ Bình luận đã bị tắt Đã được chủ kênh thả \"thính\" Đánh dấu là đã xem - Hiển thị các dải băng màu Picasso trên đầu các hình ảnh cho biết nguồn của chúng: màu đỏ cho mạng, màu lam cho đĩa và màu lục cho bộ nhớ - Hiện dấu chỉ hình ảnh Đề xuất tìm kiếm trên mạng Đề xuất tìm kiếm cục bộ diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index adbf2ce64..ea92db43f 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -618,8 +618,6 @@ 高品质(较大) 被创作者喜爱 标记为已观看 - 在图像顶部显示毕加索彩带,指示其来源:红色代表网络,蓝色代表磁盘,绿色代表内存 - 显示图像指示器 远程搜索建议 本地搜索建议 diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 0dd10f1bc..7b2ba5bb1 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -662,9 +662,7 @@ 你係咪要刪除呢個谷? 淨係顯示未成谷嘅訂閱 - 啲圖都要騷 Picasso 三色碼顯示源頭:紅碼係網絡上高落嚟,藍碼係儲存喺磁碟本地,綠碼係潛伏喺記憶體中 服務原本嘅字會騷返喺串流項目上面 - 影像要推三色碼 若果播片嘅時候窒下窒下或者黑畫面,就停用多媒體隧道啦。 點樣用 Google 匯出嚟匯入 YouTube 訂閱: \n diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 1f4bfb290..cca70f771 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -600,8 +600,6 @@ 拖動列縮圖預覽 被創作者加心號 標記為已觀看 - 在圖片頂部顯示畢卡索彩色絲帶,指示其來源:紅色代表網路、藍色代表磁碟、綠色代表記憶體 - 顯示圖片指示器 遠端搜尋建議 本機搜尋建議 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9095fe927..7df964aed 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -494,8 +494,6 @@ Disable media tunneling Disable media tunneling if you experience a black screen or stuttering on video playback. Media tunneling was disabled by default on your device because your device model is known to not support it. - Show image indicators - Show Picasso colored ribbons on top of images indicating their source: red for network, blue for disk and green for memory Show \"Crash the player\" Shows a crash option when using the player Run check for new streams From 08b7da4b2bbd5bc655c20aee3b6396f41fee2204 Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Fri, 30 Jan 2026 15:41:19 +0200 Subject: [PATCH 52/56] Accomodate extractor changes (EnumSet for service media capabilities) --- app/src/main/java/org/schabi/newpipe/RouterActivity.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java index d85fdf7de..2997f937f 100644 --- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java +++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java @@ -343,8 +343,7 @@ public class RouterActivity extends AppCompatActivity { return; } - final List capabilities = - currentService.getServiceInfo().getMediaCapabilities(); + final var capabilities = currentService.getServiceInfo().getMediaCapabilities(); // Check if the service supports the choice if ((isVideoPlayerSelected && capabilities.contains(VIDEO)) @@ -528,8 +527,7 @@ public class RouterActivity extends AppCompatActivity { final List returnedItems = new ArrayList<>(); returnedItems.add(showInfo); // Always present - final List capabilities = - service.getServiceInfo().getMediaCapabilities(); + final var capabilities = service.getServiceInfo().getMediaCapabilities(); if (linkType == LinkType.STREAM || linkType == LinkType.PLAYLIST) { if (capabilities.contains(VIDEO)) { From 63e19890bfb19bbff419f4068d7522e845588e36 Mon Sep 17 00:00:00 2001 From: tobigr Date: Sat, 21 Feb 2026 17:00:05 +0100 Subject: [PATCH 53/56] Update extractor to the latest version --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 944a059e8..14246cfd0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -59,7 +59,7 @@ teamnewpipe-nanojson = "e9d656ddb49a412a5a0a5d5ef20ca7ef09549996" # the corresponding commit hash, since JitPack sometimes deletes artifacts. # If there’s already a git hash, just add more of it to the end (or remove a letter) # to cause jitpack to regenerate the artifact. -teamnewpipe-newpipe-extractor = "v0.25.2" +teamnewpipe-newpipe-extractor = "824486dfdf4e9ba0fbe820bc2938f9101ae739a6" viewpager2 = "1.1.0" webkit = "1.14.0" # Newer versions require minSdk >= 23 work = "2.10.5" # Newer versions require minSdk >= 23 From caebf8461a51f88c3421629c85169455926c579b Mon Sep 17 00:00:00 2001 From: Alex Popov Date: Sat, 10 Jan 2026 01:26:10 +0300 Subject: [PATCH 54/56] Hide controls when resuming playback via double tap Remove redundant comment about hiding controls on double tap --- .../schabi/newpipe/player/gesture/BasePlayerGestureListener.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt b/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt index 8682adc43..904e2b3f1 100644 --- a/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt +++ b/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt @@ -47,6 +47,9 @@ abstract class BasePlayerGestureListener( startMultiDoubleTap(event) } else if (portion === DisplayPortion.MIDDLE) { player.playPause() + if (player.currentState == Player.STATE_PLAYING) { + playerUi.hideControls(0, 0) + } } } From 423f95a65d9d204f7a8acec1db448d9b39755d2f Mon Sep 17 00:00:00 2001 From: Alex Popov Date: Sat, 10 Jan 2026 01:48:26 +0300 Subject: [PATCH 55/56] Refactor double tap logic to use isPlaying() method for better readability --- .../schabi/newpipe/player/gesture/BasePlayerGestureListener.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt b/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt index 904e2b3f1..52175a3bf 100644 --- a/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt +++ b/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt @@ -47,7 +47,7 @@ abstract class BasePlayerGestureListener( startMultiDoubleTap(event) } else if (portion === DisplayPortion.MIDDLE) { player.playPause() - if (player.currentState == Player.STATE_PLAYING) { + if (player.isPlaying) { playerUi.hideControls(0, 0) } } From 8902ce867822a5f7a1b4569ad52199824908cd43 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Sun, 22 Feb 2026 10:46:58 +0800 Subject: [PATCH 56/56] Update dependencies and Gradle to latest stable releases Signed-off-by: Aayush Gupta --- gradle/libs.versions.toml | 10 +++++----- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c25025814..73e9cad08 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,13 +7,13 @@ acra = "5.13.1" agp = "8.13.2" appcompat = "1.7.1" -assertj = "3.27.6" +assertj = "3.27.7" autoservice-google = "1.1.1" autoservice-zacsweers = "1.2.0" bridge = "v2.0.2" cardview = "1.0.0" -checkstyle = "13.0.0" -coil = "3.0.4" +checkstyle = "13.2.0" +coil = "3.3.0" constraintlayout = "2.2.1" core = "1.17.0" desugar = "2.1.5" @@ -24,8 +24,8 @@ groupie = "2.10.1" jsoup = "1.22.1" junit = "4.13.2" junit-ext = "1.3.0" -kotlin = "2.3.0" -ksp = "2.3.5" +kotlin = "2.3.10" +ksp = "2.3.6" ktlint = "1.8.0" leakcanary = "2.14" lifecycle = "2.9.4" # Newer versions require minSdk >= 23 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 44ae9537e..414656493 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=0d585f69da091fc5b2beced877feab55a3064d43b8a1d46aeb07996b0915e0e0 -distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.0-bin.zip +distributionSha256Sum=b266d5ff6b90eada6dc3b20cb090e3731302e553a27c5d3e4df1f0d76beaff06 +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME