Merge branch 'TeamNewPipe:dev' into exo182

This commit is contained in:
Robin 2023-01-02 10:35:20 +01:00 committed by GitHub
commit f17155bb3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 663 additions and 667 deletions

View File

@ -15,7 +15,7 @@ android {
applicationId "org.schabi.newpipe"
resValue "string", "app_name", "NewPipe"
minSdk 21
targetSdk 29
targetSdk 33
versionCode 991
versionName "0.24.1"
@ -107,7 +107,7 @@ ext {
groupieVersion = '2.10.1'
markwonVersion = '4.6.2'
leakCanaryVersion = '2.5'
leakCanaryVersion = '2.9.1'
stethoVersion = '1.6.0'
mockitoVersion = '4.0.0'
assertJVersion = '3.23.1'
@ -179,7 +179,7 @@ sonar {
dependencies {
/** Desugaring **/
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.6'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.8'
/** NewPipe libraries **/
// You can use a local version by uncommenting a few lines in settings.gradle
@ -259,14 +259,14 @@ dependencies {
implementation "io.noties.markwon:linkify:${markwonVersion}"
// Crash reporting
implementation "ch.acra:acra-core:5.9.3"
implementation "ch.acra:acra-core:5.9.7"
// Properly restarting
implementation 'com.jakewharton:process-phoenix:2.1.2'
// Reactive extensions for Java VM
implementation "io.reactivex.rxjava3:rxjava:3.0.13"
implementation "io.reactivex.rxjava3:rxandroid:3.0.0"
implementation "io.reactivex.rxjava3:rxjava:3.1.5"
implementation "io.reactivex.rxjava3:rxandroid:3.0.2"
// RxJava binding APIs for Android UI widgets
implementation "com.jakewharton.rxbinding4:rxbinding:4.0.0"

View File

@ -1,12 +1,12 @@
package org.schabi.newpipe.util
import android.content.Context
import android.util.SparseArray
import android.view.View
import android.view.View.GONE
import android.view.View.INVISIBLE
import android.view.View.VISIBLE
import android.widget.Spinner
import androidx.collection.SparseArrayCompat
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
@ -39,9 +39,7 @@ class StreamItemAdapterTest {
@Test
fun videoStreams_noSecondaryStream() {
val adapter = StreamItemAdapter<VideoStream, AudioStream>(
context,
getVideoStreams(true, true, true, true),
null
getVideoStreams(true, true, true, true)
)
spinner.adapter = adapter
@ -54,7 +52,6 @@ class StreamItemAdapterTest {
@Test
fun videoStreams_hasSecondaryStream() {
val adapter = StreamItemAdapter(
context,
getVideoStreams(false, true, false, true),
getAudioStreams(false, true, false, true)
)
@ -69,7 +66,6 @@ class StreamItemAdapterTest {
@Test
fun videoStreams_Mixed() {
val adapter = StreamItemAdapter(
context,
getVideoStreams(true, true, true, true, true, false, true, true),
getAudioStreams(false, true, false, false, false, true, true, true)
)
@ -88,7 +84,6 @@ class StreamItemAdapterTest {
@Test
fun subtitleStreams_noIcon() {
val adapter = StreamItemAdapter<SubtitlesStream, Stream>(
context,
StreamItemAdapter.StreamSizeWrapper(
(0 until 5).map {
SubtitlesStream.Builder()
@ -99,8 +94,7 @@ class StreamItemAdapterTest {
.build()
},
context
),
null
)
)
spinner.adapter = adapter
for (i in 0 until spinner.count) {
@ -111,7 +105,6 @@ class StreamItemAdapterTest {
@Test
fun audioStreams_noIcon() {
val adapter = StreamItemAdapter<AudioStream, Stream>(
context,
StreamItemAdapter.StreamSizeWrapper(
(0 until 5).map {
AudioStream.Builder()
@ -122,8 +115,7 @@ class StreamItemAdapterTest {
.build()
},
context
),
null
)
)
spinner.adapter = adapter
for (i in 0 until spinner.count) {
@ -200,7 +192,7 @@ class StreamItemAdapterTest {
* Helper function that builds a secondary stream list.
*/
private fun <T : Stream> getSecondaryStreamsFromList(streams: List<T?>) =
SparseArray<SecondaryStreamHelper<T>?>(streams.size).apply {
SparseArrayCompat<SecondaryStreamHelper<T>?>(streams.size).apply {
streams.forEachIndexed { index, stream ->
val secondaryStreamHelper: SecondaryStreamHelper<T>? = stream?.let {
SecondaryStreamHelper(

View File

@ -9,6 +9,7 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-feature
android:name="android.hardware.touchscreen"
@ -24,11 +25,12 @@
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:logo="@mipmap/ic_launcher"
android:theme="@style/OpeningTheme"
android:resizeableActivity="true"
android:theme="@style/OpeningTheme"
tools:ignore="AllowBackup">
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:launchMode="singleTask">
<intent-filter>
@ -39,7 +41,9 @@
</intent-filter>
</activity>
<receiver android:name="androidx.media.session.MediaButtonReceiver">
<receiver
android:name="androidx.media.session.MediaButtonReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
@ -47,7 +51,7 @@
<service
android:name=".player.PlayerService"
android:exported="false"
android:exported="true"
android:foregroundServiceType="mediaPlayback">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
@ -56,15 +60,18 @@
<activity
android:name=".player.PlayQueueActivity"
android:exported="false"
android:label="@string/title_activity_play_queue"
android:launchMode="singleTask" />
<activity
android:name=".settings.SettingsActivity"
android:exported="false"
android:label="@string/settings" />
<activity
android:name=".about.AboutActivity"
android:exported="false"
android:label="@string/title_activity_about" />
<service android:name=".local.subscription.services.SubscriptionsImportService" />
@ -73,6 +80,7 @@
<activity
android:name=".PanicResponderActivity"
android:exported="true"
android:launchMode="singleInstance"
android:noHistory="true"
android:theme="@android:style/Theme.NoDisplay">
@ -85,13 +93,18 @@
<activity
android:name=".ExitActivity"
android:exported="false"
android:label="@string/general_error"
android:theme="@android:style/Theme.NoDisplay" />
<activity android:name=".error.ErrorActivity" />
<activity
android:name=".error.ErrorActivity"
android:exported="false" />
<!-- giga get related -->
<activity
android:name=".download.DownloadActivity"
android:exported="false"
android:label="@string/app_name"
android:launchMode="singleTask" />
@ -99,6 +112,7 @@
<activity
android:name=".util.FilePickerActivityHelper"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/FilePickerThemeDark">
<intent-filter>
@ -109,6 +123,7 @@
<activity
android:name=".error.ReCaptchaActivity"
android:exported="false"
android:label="@string/recaptcha" />
<provider
@ -124,6 +139,7 @@
<activity
android:name=".RouterActivity"
android:excludeFromRecents="true"
android:exported="true"
android:label="@string/preferred_open_action_share_menu_title"
android:taskAffinity=""
android:theme="@style/RouterActivityThemeDark">
@ -353,30 +369,30 @@
<!-- Bandcamp filter for tracks, albums and playlists -->
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH"/>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:host="*.bandcamp.com"/>
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="*.bandcamp.com" />
</intent-filter>
<!-- Bandcamp filter for radio -->
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH"/>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:sspPattern="bandcamp.com/?show=*"/>
<data android:scheme="http" />
<data android:scheme="https" />
<data android:sspPattern="bandcamp.com/?show=*" />
</intent-filter>
</activity>
@ -385,11 +401,17 @@
android:exported="false" />
<!-- opting out of sending metrics to Google in Android System WebView -->
<meta-data android:name="android.webkit.WebView.MetricsOptOut" android:value="true" />
<meta-data
android:name="android.webkit.WebView.MetricsOptOut"
android:value="true" />
<!-- see https://github.com/TeamNewPipe/NewPipe/issues/3947 -->
<!-- Version < 3.0. DeX Mode and Screen Mirroring support -->
<meta-data android:name="com.samsung.android.keepalive.density" android:value="true"/>
<meta-data
android:name="com.samsung.android.keepalive.density"
android:value="true" />
<!-- Version >= 3.0. DeX Dual Mode support -->
<meta-data android:name="com.samsung.android.multidisplay.keep_process_alive" android:value="true"/>
<meta-data
android:name="com.samsung.android.multidisplay.keep_process_alive"
android:value="true" />
</application>
</manifest>

View File

@ -157,9 +157,12 @@ public class MainActivity extends AppCompatActivity {
}
openMiniPlayerUponPlayerStarted();
// Schedule worker for checking for new streams and creating corresponding notifications
// if this is enabled by the user.
NotificationWorker.initialize(this);
if (PermissionHelper.checkPostNotificationsPermission(this,
PermissionHelper.POST_NOTIFICATIONS_REQUEST_CODE)) {
// Schedule worker for checking for new streams and creating corresponding notifications
// if this is enabled by the user.
NotificationWorker.initialize(this);
}
}
@Override
@ -599,6 +602,9 @@ public class MainActivity extends AppCompatActivity {
((VideoDetailFragment) fragment).openDownloadDialog();
}
break;
case PermissionHelper.POST_NOTIFICATIONS_REQUEST_CODE:
NotificationWorker.initialize(this);
break;
}
}

View File

@ -1,5 +1,6 @@
package org.schabi.newpipe;
import static org.schabi.newpipe.util.SparseItemUtil.fetchStreamInfoAndSaveToDatabase;
import static org.schabi.newpipe.util.external_communication.ShareUtils.shareText;
import android.content.Context;
@ -10,6 +11,7 @@ import android.widget.PopupMenu;
import androidx.fragment.app.FragmentManager;
import org.schabi.newpipe.database.stream.model.StreamEntity;
import org.schabi.newpipe.download.DownloadDialog;
import org.schabi.newpipe.local.dialog.PlaylistDialog;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
@ -75,6 +77,14 @@ public final class QueueItemMenuUtil {
shareText(context, item.getTitle(), item.getUrl(),
item.getThumbnailUrl());
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 false;
});

View File

@ -17,7 +17,6 @@ import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.util.Log;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -36,6 +35,7 @@ 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;
import androidx.fragment.app.DialogFragment;
import androidx.preference.PreferenceManager;
@ -211,8 +211,7 @@ public class DownloadDialog extends DialogFragment
setStyle(STYLE_NO_TITLE, ThemeHelper.getDialogTheme(context));
Icepick.restoreInstanceState(this, savedInstanceState);
final SparseArray<SecondaryStreamHelper<AudioStream>> secondaryStreams =
new SparseArray<>(4);
final var secondaryStreams = new SparseArrayCompat<SecondaryStreamHelper<AudioStream>>(4);
final List<VideoStream> videoStreams = wrappedVideoStreams.getStreamsList();
for (int i = 0; i < videoStreams.size(); i++) {
@ -236,10 +235,9 @@ public class DownloadDialog extends DialogFragment
}
}
this.videoStreamsAdapter = new StreamItemAdapter<>(context, wrappedVideoStreams,
secondaryStreams);
this.audioStreamsAdapter = new StreamItemAdapter<>(context, wrappedAudioStreams);
this.subtitleStreamsAdapter = new StreamItemAdapter<>(context, wrappedSubtitleStreams);
this.videoStreamsAdapter = new StreamItemAdapter<>(wrappedVideoStreams, secondaryStreams);
this.audioStreamsAdapter = new StreamItemAdapter<>(wrappedAudioStreams);
this.subtitleStreamsAdapter = new StreamItemAdapter<>(wrappedSubtitleStreams);
final Intent intent = new Intent(context, DownloadManagerService.class);
context.startService(intent);

View File

@ -10,8 +10,11 @@ import static org.schabi.newpipe.player.helper.PlayerHelper.isClearingQueueConfi
import static org.schabi.newpipe.player.playqueue.PlayQueueItem.RECOVERY_UNSET;
import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView;
import static org.schabi.newpipe.util.ListHelper.getUrlAndNonTorrentStreams;
import static org.schabi.newpipe.util.NavigationHelper.openPlayQueue;
import static org.schabi.newpipe.util.NavigationHelper.playWithKore;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
@ -119,6 +122,7 @@ import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import icepick.State;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
@ -129,9 +133,6 @@ import io.reactivex.rxjava3.schedulers.Schedulers;
public final class VideoDetailFragment
extends BaseStateFragment<StreamInfo>
implements BackPressable,
SharedPreferences.OnSharedPreferenceChangeListener,
View.OnClickListener,
View.OnLongClickListener,
PlayerServiceExtendedEventListener,
OnKeyDownListener {
public static final String KEY_SWITCHING_PLAYERS = "switching_players";
@ -167,6 +168,20 @@ public final class VideoDetailFragment
private boolean tabSettingsChanged = false;
private int lastAppBarVerticalOffset = Integer.MAX_VALUE; // prevents useless updates
private final SharedPreferences.OnSharedPreferenceChangeListener preferenceChangeListener =
(sharedPreferences, key) -> {
if (key.equals(getString(R.string.show_comments_key))) {
showComments = sharedPreferences.getBoolean(key, true);
tabSettingsChanged = true;
} else if (key.equals(getString(R.string.show_next_video_key))) {
showRelatedItems = sharedPreferences.getBoolean(key, true);
tabSettingsChanged = true;
} else if (key.equals(getString(R.string.show_description_key))) {
showDescription = sharedPreferences.getBoolean(key, true);
tabSettingsChanged = true;
}
};
@State
protected int serviceId = Constants.NO_SERVICE_ID;
@State
@ -291,7 +306,7 @@ public final class VideoDetailFragment
showDescription = prefs.getBoolean(getString(R.string.show_description_key), true);
selectedTabTag = prefs.getString(
getString(R.string.stream_info_selected_tab_key), COMMENTS_TAB_TAG);
prefs.registerOnSharedPreferenceChangeListener(this);
prefs.registerOnSharedPreferenceChangeListener(preferenceChangeListener);
setupBroadcastReceiver();
@ -378,7 +393,7 @@ public final class VideoDetailFragment
}
PreferenceManager.getDefaultSharedPreferences(activity)
.unregisterOnSharedPreferenceChangeListener(this);
.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener);
activity.unregisterReceiver(broadcastReceiver);
activity.getContentResolver().unregisterContentObserver(settingsContentObserver);
@ -424,130 +439,129 @@ public final class VideoDetailFragment
}
}
@Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences,
final String key) {
if (key.equals(getString(R.string.show_comments_key))) {
showComments = sharedPreferences.getBoolean(key, true);
tabSettingsChanged = true;
} else if (key.equals(getString(R.string.show_next_video_key))) {
showRelatedItems = sharedPreferences.getBoolean(key, true);
tabSettingsChanged = true;
} else if (key.equals(getString(R.string.show_description_key))) {
showDescription = sharedPreferences.getBoolean(key, true);
tabSettingsChanged = true;
}
}
/*//////////////////////////////////////////////////////////////////////////
// OnClick
//////////////////////////////////////////////////////////////////////////*/
@Override
public void onClick(final View v) {
switch (v.getId()) {
case R.id.detail_controls_background:
openBackgroundPlayer(false);
break;
case R.id.detail_controls_popup:
openPopupPlayer(false);
break;
case R.id.detail_controls_playlist_append:
if (getFM() != null && currentInfo != null) {
disposables.add(
PlaylistDialog.createCorrespondingDialog(
getContext(),
List.of(new StreamEntity(currentInfo)),
dialog -> dialog.show(getFM(), TAG)
)
);
}
break;
case R.id.detail_controls_download:
if (PermissionHelper.checkStoragePermissions(activity,
PermissionHelper.DOWNLOAD_DIALOG_REQUEST_CODE)) {
this.openDownloadDialog();
}
break;
case R.id.detail_controls_share:
if (currentInfo != null) {
ShareUtils.shareText(requireContext(), currentInfo.getName(),
currentInfo.getUrl(), currentInfo.getThumbnailUrl());
}
break;
case R.id.detail_controls_open_in_browser:
if (currentInfo != null) {
ShareUtils.openUrlInBrowser(requireContext(), currentInfo.getUrl());
}
break;
case R.id.detail_controls_play_with_kodi:
if (currentInfo != null) {
try {
NavigationHelper.playWithKore(
requireContext(), Uri.parse(currentInfo.getUrl()));
} catch (final Exception e) {
if (DEBUG) {
Log.i(TAG, "Failed to start kore", e);
}
KoreUtils.showInstallKoreDialog(requireContext());
}
}
break;
case R.id.detail_uploader_root_layout:
if (isEmpty(currentInfo.getSubChannelUrl())) {
if (!isEmpty(currentInfo.getUploaderUrl())) {
openChannel(currentInfo.getUploaderUrl(), currentInfo.getUploaderName());
}
if (DEBUG) {
Log.i(TAG, "Can't open sub-channel because we got no channel URL");
}
} else {
openChannel(currentInfo.getSubChannelUrl(),
currentInfo.getSubChannelName());
}
break;
case R.id.detail_thumbnail_root_layout:
// make sure not to open any player if there is nothing currently loaded!
// FIXME removing this `if` causes the player service to start correctly, then stop,
// then restart badly without calling `startForeground()`, causing a crash when
// later closing the detail fragment
if (currentInfo != null) {
autoPlayEnabled = true; // forcefully start playing
// FIXME Workaround #7427
if (isPlayerAvailable()) {
player.setRecovery();
}
openVideoPlayerAutoFullscreen();
}
break;
case R.id.detail_title_root_layout:
toggleTitleAndSecondaryControls();
break;
case R.id.overlay_thumbnail:
case R.id.overlay_metadata_layout:
case R.id.overlay_buttons_layout:
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
break;
case R.id.overlay_play_queue_button:
NavigationHelper.openPlayQueue(getContext());
break;
case R.id.overlay_play_pause_button:
if (playerIsNotStopped()) {
player.playPause();
player.UIs().get(VideoPlayerUi.class).ifPresent(ui -> ui.hideControls(0, 0));
showSystemUi();
} else {
autoPlayEnabled = true; // forcefully start playing
openVideoPlayer(false);
private void setOnClickListeners() {
binding.detailTitleRootLayout.setOnClickListener(v -> toggleTitleAndSecondaryControls());
binding.detailUploaderRootLayout.setOnClickListener(makeOnClickListener(info -> {
if (isEmpty(info.getSubChannelUrl())) {
if (!isEmpty(info.getUploaderUrl())) {
openChannel(info.getUploaderUrl(), info.getUploaderName());
}
setOverlayPlayPauseImage(isPlayerAvailable() && player.isPlaying());
break;
case R.id.overlay_close_button:
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
break;
if (DEBUG) {
Log.i(TAG, "Can't open sub-channel because we got no channel URL");
}
} else {
openChannel(info.getSubChannelUrl(), info.getSubChannelName());
}
}));
binding.detailThumbnailRootLayout.setOnClickListener(v -> {
autoPlayEnabled = true; // forcefully start playing
// FIXME Workaround #7427
if (isPlayerAvailable()) {
player.setRecovery();
}
openVideoPlayerAutoFullscreen();
});
binding.detailControlsBackground.setOnClickListener(v -> openBackgroundPlayer(false));
binding.detailControlsPopup.setOnClickListener(v -> openPopupPlayer(false));
binding.detailControlsPlaylistAppend.setOnClickListener(makeOnClickListener(info ->
disposables.add(PlaylistDialog.createCorrespondingDialog(requireContext(),
List.of(new StreamEntity(info)),
dialog -> dialog.show(getParentFragmentManager(), TAG)))));
binding.detailControlsDownload.setOnClickListener(v -> {
if (PermissionHelper.checkStoragePermissions(activity,
PermissionHelper.DOWNLOAD_DIALOG_REQUEST_CODE)) {
openDownloadDialog();
}
});
binding.detailControlsShare.setOnClickListener(makeOnClickListener(info ->
ShareUtils.shareText(requireContext(), info.getName(), info.getUrl(),
info.getThumbnailUrl())));
binding.detailControlsOpenInBrowser.setOnClickListener(makeOnClickListener(info ->
ShareUtils.openUrlInBrowser(requireContext(), info.getUrl())));
binding.detailControlsPlayWithKodi.setOnClickListener(makeOnClickListener(info -> {
try {
playWithKore(requireContext(), Uri.parse(info.getUrl()));
} catch (final Exception e) {
if (DEBUG) {
Log.i(TAG, "Failed to start kore", e);
}
KoreUtils.showInstallKoreDialog(requireContext());
}
}));
if (DEBUG) {
binding.detailControlsCrashThePlayer.setOnClickListener(v ->
VideoDetailPlayerCrasher.onCrashThePlayer(requireContext(), player));
}
final View.OnClickListener overlayListener = v -> bottomSheetBehavior
.setState(BottomSheetBehavior.STATE_EXPANDED);
binding.overlayThumbnail.setOnClickListener(overlayListener);
binding.overlayMetadataLayout.setOnClickListener(overlayListener);
binding.overlayButtonsLayout.setOnClickListener(overlayListener);
binding.overlayCloseButton.setOnClickListener(v -> bottomSheetBehavior
.setState(BottomSheetBehavior.STATE_HIDDEN));
binding.overlayPlayQueueButton.setOnClickListener(v -> openPlayQueue(requireContext()));
binding.overlayPlayPauseButton.setOnClickListener(v -> {
if (playerIsNotStopped()) {
player.playPause();
player.UIs().get(VideoPlayerUi.class).ifPresent(ui -> ui.hideControls(0, 0));
showSystemUi();
} else {
autoPlayEnabled = true; // forcefully start playing
openVideoPlayer(false);
}
setOverlayPlayPauseImage(isPlayerAvailable() && player.isPlaying());
});
}
private View.OnClickListener makeOnClickListener(final Consumer<StreamInfo> consumer) {
return v -> {
if (!isLoading.get() && currentInfo != null) {
consumer.accept(currentInfo);
}
};
}
private void setOnLongClickListeners() {
binding.detailTitleRootLayout.setOnLongClickListener(makeOnLongClickListener(info ->
ShareUtils.copyToClipboard(requireContext(),
binding.detailVideoTitleView.getText().toString())));
binding.detailUploaderRootLayout.setOnLongClickListener(makeOnLongClickListener(info -> {
if (isEmpty(info.getSubChannelUrl())) {
Log.w(TAG, "Can't open parent channel because we got no parent channel URL");
} else {
openChannel(info.getUploaderUrl(), info.getUploaderName());
}
}));
binding.detailControlsBackground.setOnLongClickListener(makeOnLongClickListener(info ->
openBackgroundPlayer(true)));
binding.detailControlsPopup.setOnLongClickListener(makeOnLongClickListener(info ->
openPopupPlayer(true)));
binding.detailControlsDownload.setOnLongClickListener(makeOnLongClickListener(info ->
NavigationHelper.openDownloads(activity)));
final View.OnLongClickListener overlayListener = makeOnLongClickListener(info ->
openChannel(info.getUploaderUrl(), info.getUploaderName()));
binding.overlayThumbnail.setOnLongClickListener(overlayListener);
binding.overlayMetadataLayout.setOnLongClickListener(overlayListener);
}
private View.OnLongClickListener makeOnLongClickListener(final Consumer<StreamInfo> consumer) {
return v -> {
if (isLoading.get() || currentInfo == null) {
return false;
}
consumer.accept(currentInfo);
return true;
};
}
private void openChannel(final String subChannelUrl, final String subChannelName) {
@ -559,43 +573,6 @@ public final class VideoDetailFragment
}
}
@Override
public boolean onLongClick(final View v) {
if (isLoading.get() || currentInfo == null) {
return false;
}
switch (v.getId()) {
case R.id.detail_controls_background:
openBackgroundPlayer(true);
break;
case R.id.detail_controls_popup:
openPopupPlayer(true);
break;
case R.id.detail_controls_download:
NavigationHelper.openDownloads(activity);
break;
case R.id.overlay_thumbnail:
case R.id.overlay_metadata_layout:
openChannel(currentInfo.getUploaderUrl(), currentInfo.getUploaderName());
break;
case R.id.detail_uploader_root_layout:
if (isEmpty(currentInfo.getSubChannelUrl())) {
Log.w(TAG,
"Can't open parent channel because we got no parent channel URL");
} else {
openChannel(currentInfo.getUploaderUrl(), currentInfo.getUploaderName());
}
break;
case R.id.detail_title_root_layout:
ShareUtils.copyToClipboard(requireContext(),
binding.detailVideoTitleView.getText().toString());
break;
}
return true;
}
private void toggleTitleAndSecondaryControls() {
if (binding.detailSecondaryControlPanel.getVisibility() == View.GONE) {
binding.detailVideoTitleView.setMaxLines(10);
@ -616,11 +593,6 @@ public final class VideoDetailFragment
// Init
//////////////////////////////////////////////////////////////////////////*/
@Override
public void onViewCreated(@NonNull final View rootView, final Bundle savedInstanceState) {
super.onViewCreated(rootView, savedInstanceState);
}
@Override // called from onViewCreated in {@link BaseFragment#onViewCreated}
protected void initViews(final View rootView, final Bundle savedInstanceState) {
super.initViews(rootView, savedInstanceState);
@ -646,44 +618,25 @@ public final class VideoDetailFragment
}
@Override
@SuppressLint("ClickableViewAccessibility")
protected void initListeners() {
super.initListeners();
binding.detailTitleRootLayout.setOnClickListener(this);
binding.detailTitleRootLayout.setOnLongClickListener(this);
binding.detailUploaderRootLayout.setOnClickListener(this);
binding.detailUploaderRootLayout.setOnLongClickListener(this);
binding.detailThumbnailRootLayout.setOnClickListener(this);
setOnClickListeners();
setOnLongClickListeners();
binding.detailControlsBackground.setOnClickListener(this);
binding.detailControlsBackground.setOnLongClickListener(this);
binding.detailControlsPopup.setOnClickListener(this);
binding.detailControlsPopup.setOnLongClickListener(this);
binding.detailControlsPlaylistAppend.setOnClickListener(this);
binding.detailControlsDownload.setOnClickListener(this);
binding.detailControlsDownload.setOnLongClickListener(this);
binding.detailControlsShare.setOnClickListener(this);
binding.detailControlsOpenInBrowser.setOnClickListener(this);
binding.detailControlsPlayWithKodi.setOnClickListener(this);
if (DEBUG) {
binding.detailControlsCrashThePlayer.setOnClickListener(
v -> VideoDetailPlayerCrasher.onCrashThePlayer(
this.getContext(),
this.player)
);
}
final View.OnTouchListener controlsTouchListener = (view, motionEvent) -> {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN
&& PreferenceManager.getDefaultSharedPreferences(activity)
.getBoolean(getString(R.string.show_hold_to_append_key), true)) {
binding.overlayThumbnail.setOnClickListener(this);
binding.overlayThumbnail.setOnLongClickListener(this);
binding.overlayMetadataLayout.setOnClickListener(this);
binding.overlayMetadataLayout.setOnLongClickListener(this);
binding.overlayButtonsLayout.setOnClickListener(this);
binding.overlayPlayQueueButton.setOnClickListener(this);
binding.overlayCloseButton.setOnClickListener(this);
binding.overlayPlayPauseButton.setOnClickListener(this);
binding.detailControlsBackground.setOnTouchListener(getOnControlsTouchListener());
binding.detailControlsPopup.setOnTouchListener(getOnControlsTouchListener());
animate(binding.touchAppendDetail, true, 250, AnimationType.ALPHA, 0, () ->
animate(binding.touchAppendDetail, false, 1500, AnimationType.ALPHA, 1000));
}
return false;
};
binding.detailControlsBackground.setOnTouchListener(controlsTouchListener);
binding.detailControlsPopup.setOnTouchListener(controlsTouchListener);
binding.appBarLayout.addOnOffsetChangedListener((layout, verticalOffset) -> {
// prevent useless updates to tab layout visibility if nothing changed
@ -702,23 +655,6 @@ public final class VideoDetailFragment
}
}
private View.OnTouchListener getOnControlsTouchListener() {
return (view, motionEvent) -> {
if (!PreferenceManager.getDefaultSharedPreferences(activity)
.getBoolean(getString(R.string.show_hold_to_append_key), true)) {
return false;
}
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
animate(binding.touchAppendDetail, true, 250, AnimationType.ALPHA,
0, () ->
animate(binding.touchAppendDetail, false, 1500,
AnimationType.ALPHA, 1000));
}
return false;
};
}
private void initThumbnailViews(@NonNull final StreamInfo info) {
PicassoHelper.loadDetailsThumbnail(info.getThumbnailUrl()).tag(PICASSO_VIDEO_DETAILS_TAG)
.into(binding.detailThumbnailImageView, new Callback() {

View File

@ -230,24 +230,24 @@ public class PlaylistFragment extends BaseListInfoFragment<StreamInfoItem, Playl
ShareUtils.openUrlInBrowser(requireContext(), url);
break;
case R.id.menu_item_share:
if (currentInfo != null) {
ShareUtils.shareText(requireContext(), name, url,
currentInfo.getThumbnailUrl());
}
ShareUtils.shareText(requireContext(), name, url,
currentInfo == null ? null : currentInfo.getThumbnailUrl());
break;
case R.id.menu_item_bookmark:
onBookmarkClicked();
break;
case R.id.menu_item_append_playlist:
disposables.add(PlaylistDialog.createCorrespondingDialog(
getContext(),
getPlayQueue()
.getStreams()
.stream()
.map(StreamEntity::new)
.collect(Collectors.toList()),
dialog -> dialog.show(getFM(), TAG)
));
if (currentInfo != null) {
disposables.add(PlaylistDialog.createCorrespondingDialog(
getContext(),
getPlayQueue()
.getStreams()
.stream()
.map(StreamEntity::new)
.collect(Collectors.toList()),
dialog -> dialog.show(getFM(), TAG)
));
}
break;
default:
return super.onOptionsItemSelected(item);

View File

@ -33,6 +33,7 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.TooltipCompat;
import androidx.collection.SparseArrayCompat;
import androidx.core.text.HtmlCompat;
import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.ItemTouchHelper;
@ -70,9 +71,7 @@ import org.schabi.newpipe.util.ServiceHelper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@ -141,7 +140,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
@State
boolean wasSearchFocused = false;
@Nullable private Map<Integer, String> menuItemToFilterName = null;
private final SparseArrayCompat<String> menuItemToFilterName = new SparseArrayCompat<>();
private StreamingService service;
private Page nextPage;
private boolean showLocalSuggestions = true;
@ -426,8 +425,6 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
supportActionBar.setDisplayHomeAsUpEnabled(true);
}
menuItemToFilterName = new HashMap<>();
int itemId = 0;
boolean isFirstItem = true;
final Context c = getContext();
@ -468,11 +465,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
@Override
public boolean onOptionsItemSelected(@NonNull final MenuItem item) {
if (menuItemToFilterName != null) {
final List<String> cf = new ArrayList<>(1);
cf.add(menuItemToFilterName.get(item.getItemId()));
changeContentFilter(item, cf);
}
final var filter = Collections.singletonList(menuItemToFilterName.get(item.getItemId()));
changeContentFilter(item, filter);
return true;
}

View File

@ -216,7 +216,6 @@ public final class Player implements PlaybackListener, Listener {
// minimized to background but will resume automatically to the original player type
private boolean isAudioOnly = false;
private boolean isPrepared = false;
private boolean wasPlaying = false;
/*//////////////////////////////////////////////////////////////////////////
// UIs, listeners and disposables
@ -918,13 +917,6 @@ public final class Player implements PlaybackListener, Listener {
error -> Log.e(TAG, "Progress update failure: ", error));
}
public void saveWasPlaying() {
this.wasPlaying = getPlayWhenReady();
}
public boolean wasPlaying() {
return wasPlaying;
}
//endregion

View File

@ -86,8 +86,6 @@ public final class PlayerService extends Service {
}
if (!player.exoPlayerIsNull()) {
player.saveWasPlaying();
// Releases wifi & cpu, disables keepScreenOn, etc.
// We can't just pause the player here because it will make transition
// from one stream to a new stream not smooth

View File

@ -1,6 +1,7 @@
package org.schabi.newpipe.player.seekbarpreview;
import static org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHelper.SeekbarPreviewThumbnailType;
import static org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHelper.getSeekbarPreviewThumbnailType;
import android.content.Context;
import android.graphics.Bitmap;
@ -8,6 +9,7 @@ import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.collection.SparseArrayCompat;
import com.google.common.base.Stopwatch;
@ -15,12 +17,9 @@ import org.schabi.newpipe.extractor.stream.Frameset;
import org.schabi.newpipe.util.PicassoHelper;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Supplier;
@ -34,18 +33,15 @@ public class SeekbarPreviewThumbnailHolder {
// Key = Position of the picture in milliseconds
// Supplier = Supplies the bitmap for that position
private final Map<Integer, Supplier<Bitmap>> seekbarPreviewData = new ConcurrentHashMap<>();
private final SparseArrayCompat<Supplier<Bitmap>> seekbarPreviewData =
new SparseArrayCompat<>();
// This ensures that if the reset is still undergoing
// and another reset starts, only the last reset is processed
private UUID currentUpdateRequestIdentifier = UUID.randomUUID();
public synchronized void resetFrom(
@NonNull final Context context,
final List<Frameset> framesets) {
final int seekbarPreviewType =
SeekbarPreviewThumbnailHelper.getSeekbarPreviewThumbnailType(context);
public void resetFrom(@NonNull final Context context, final List<Frameset> framesets) {
final int seekbarPreviewType = getSeekbarPreviewThumbnailType(context);
final UUID updateRequestIdentifier = UUID.randomUUID();
this.currentUpdateRequestIdentifier = updateRequestIdentifier;
@ -63,13 +59,12 @@ public class SeekbarPreviewThumbnailHolder {
executorService.shutdown();
}
private void resetFromAsync(
final int seekbarPreviewType,
final List<Frameset> framesets,
final UUID updateRequestIdentifier) {
private void resetFromAsync(final int seekbarPreviewType, final List<Frameset> framesets,
final UUID updateRequestIdentifier) {
Log.d(TAG, "Clearing seekbarPreviewData");
seekbarPreviewData.clear();
synchronized (seekbarPreviewData) {
seekbarPreviewData.clear();
}
if (seekbarPreviewType == SeekbarPreviewThumbnailType.NONE) {
Log.d(TAG, "Not processing seekbarPreviewData due to settings");
@ -94,10 +89,8 @@ public class SeekbarPreviewThumbnailHolder {
generateDataFrom(frameset, updateRequestIdentifier);
}
private Frameset getFrameSetForType(
final List<Frameset> framesets,
final int seekbarPreviewType) {
private Frameset getFrameSetForType(final List<Frameset> framesets,
final int seekbarPreviewType) {
if (seekbarPreviewType == SeekbarPreviewThumbnailType.HIGH_QUALITY) {
Log.d(TAG, "Strategy for seekbarPreviewData: high quality");
return framesets.stream()
@ -111,17 +104,14 @@ public class SeekbarPreviewThumbnailHolder {
}
}
private void generateDataFrom(
final Frameset frameset,
final UUID updateRequestIdentifier) {
private void generateDataFrom(final Frameset frameset, final UUID updateRequestIdentifier) {
Log.d(TAG, "Starting generation of seekbarPreviewData");
final Stopwatch sw = Log.isLoggable(TAG, Log.DEBUG) ? Stopwatch.createStarted() : null;
int currentPosMs = 0;
int pos = 1;
final int frameCountPerUrl = frameset.getFramesPerPageX() * frameset.getFramesPerPageY();
final int urlFrameCount = frameset.getFramesPerPageX() * frameset.getFramesPerPageY();
// Process each url in the frameset
for (final String url : frameset.getUrls()) {
@ -130,11 +120,11 @@ public class SeekbarPreviewThumbnailHolder {
// The data is not added directly to "seekbarPreviewData" due to
// concurrency and checks for "updateRequestIdentifier"
final Map<Integer, Supplier<Bitmap>> generatedDataForUrl = new HashMap<>();
final var generatedDataForUrl = new SparseArrayCompat<Supplier<Bitmap>>(urlFrameCount);
// The bitmap consists of several images, which we process here
// foreach frame in the returned bitmap
for (int i = 0; i < frameCountPerUrl; i++) {
for (int i = 0; i < urlFrameCount; i++) {
// Frames outside the video length are skipped
if (pos > frameset.getTotalCount()) {
break;
@ -161,7 +151,9 @@ public class SeekbarPreviewThumbnailHolder {
// Check if we are still the latest request
// If not abort method execution
if (isRequestIdentifierCurrent(updateRequestIdentifier)) {
seekbarPreviewData.putAll(generatedDataForUrl);
synchronized (seekbarPreviewData) {
seekbarPreviewData.putAll(generatedDataForUrl);
}
} else {
Log.d(TAG, "Aborted of generation of seekbarPreviewData");
break;
@ -169,7 +161,7 @@ public class SeekbarPreviewThumbnailHolder {
}
if (sw != null) {
Log.d(TAG, "Generation of seekbarPreviewData took " + sw.stop().toString());
Log.d(TAG, "Generation of seekbarPreviewData took " + sw.stop());
}
}
@ -189,17 +181,14 @@ public class SeekbarPreviewThumbnailHolder {
final Bitmap bitmap = PicassoHelper.loadSeekbarThumbnailPreview(url).get();
if (sw != null) {
Log.d(TAG,
"Download of bitmap for seekbarPreview from '" + url
+ "' took " + sw.stop().toString());
Log.d(TAG, "Download of bitmap for seekbarPreview from '" + url + "' took "
+ sw.stop());
}
return bitmap;
} catch (final Exception ex) {
Log.w(TAG,
"Failed to get bitmap for seekbarPreview from url='" + url
+ "' in time",
ex);
Log.w(TAG, "Failed to get bitmap for seekbarPreview from url='" + url
+ "' in time", ex);
return null;
}
}
@ -208,32 +197,20 @@ public class SeekbarPreviewThumbnailHolder {
return this.currentUpdateRequestIdentifier.equals(requestIdentifier);
}
public Optional<Bitmap> getBitmapAt(final int positionInMs) {
// Check if the BitmapData is empty
if (seekbarPreviewData.isEmpty()) {
return Optional.empty();
// Get the frame supplier closest to the requested position
Supplier<Bitmap> closestFrame = () -> null;
synchronized (seekbarPreviewData) {
int min = Integer.MAX_VALUE;
for (int i = 0; i < seekbarPreviewData.size(); i++) {
final int pos = Math.abs(seekbarPreviewData.keyAt(i) - positionInMs);
if (pos < min) {
closestFrame = seekbarPreviewData.valueAt(i);
min = pos;
}
}
}
// Get the closest frame to the requested position
final int closestIndexPosition =
seekbarPreviewData.keySet().stream()
.min(Comparator.comparingInt(i -> Math.abs(i - positionInMs)))
.orElse(-1);
// this should never happen, because
// it indicates that "seekbarPreviewData" is empty which was already checked
if (closestIndexPosition == -1) {
return Optional.empty();
}
try {
// Get the bitmap for the position (executes the supplier)
return Optional.ofNullable(seekbarPreviewData.get(closestIndexPosition).get());
} catch (final Exception ex) {
// If there is an error, log it and return Optional.empty
Log.w(TAG, "Unable to get seekbar preview", ex);
return Optional.empty();
}
return Optional.ofNullable(closestFrame.get());
}
}

View File

@ -154,6 +154,16 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh
protected void initListeners() {
super.initListeners();
binding.screenRotationButton.setOnClickListener(makeOnClickListener(() -> {
// Only if it's not a vertical video or vertical video but in landscape with locked
// orientation a screen orientation can be changed automatically
if (!isVerticalVideo || (isLandscape() && globalScreenOrientationLocked(context))) {
player.getFragmentListener()
.ifPresent(PlayerServiceEventListener::onScreenRotationButtonClicked);
} else {
toggleFullscreen();
}
}));
binding.queueButton.setOnClickListener(v -> onQueueClicked());
binding.segmentsButton.setOnClickListener(v -> onSegmentsClicked());
@ -173,6 +183,14 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh
settingsContentObserver);
binding.getRoot().addOnLayoutChangeListener(this);
binding.moreOptionsButton.setOnLongClickListener(v -> {
player.getFragmentListener()
.ifPresent(PlayerServiceEventListener::onMoreOptionsLongClicked);
hideControls(0, 0);
hideSystemUIIfNeeded();
return true;
});
}
@Override
@ -846,23 +864,6 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh
//////////////////////////////////////////////////////////////////////////*/
//region Click listeners
@Override
public void onClick(final View v) {
if (v.getId() == binding.screenRotationButton.getId()) {
// Only if it's not a vertical video or vertical video but in landscape with locked
// orientation a screen orientation can be changed automatically
if (!isVerticalVideo || (isLandscape() && globalScreenOrientationLocked(context))) {
player.getFragmentListener().ifPresent(
PlayerServiceEventListener::onScreenRotationButtonClicked);
} else {
toggleFullscreen();
}
}
// call it later since it calls manageControlsAfterOnClick at the end
super.onClick(v);
}
@Override
protected void onPlaybackSpeedClicked() {
final AppCompatActivity activity = getParentActivity().orElse(null);
@ -875,18 +876,6 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh
.show(activity.getSupportFragmentManager(), null);
}
@Override
public boolean onLongClick(final View v) {
if (v.getId() == binding.moreOptionsButton.getId() && isFullscreen) {
player.getFragmentListener().ifPresent(
PlayerServiceEventListener::onMoreOptionsLongClicked);
hideControls(0, 0);
hideSystemUIIfNeeded();
return true;
}
return super.onLongClick(v);
}
@Override
public boolean onKeyDown(final int keyCode) {
if (keyCode == KeyEvent.KEYCODE_SPACE && isFullscreen) {

View File

@ -84,11 +84,11 @@ import org.schabi.newpipe.util.external_communication.ShareUtils;
import org.schabi.newpipe.views.player.PlayerFastSeekOverlay;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
public abstract class VideoPlayerUi extends PlayerUi
implements SeekBar.OnSeekBarChangeListener, View.OnClickListener, View.OnLongClickListener,
public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBarChangeListener,
PopupMenu.OnMenuItemClickListener, PopupMenu.OnDismissListener {
private static final String TAG = VideoPlayerUi.class.getSimpleName();
@ -132,9 +132,11 @@ public abstract class VideoPlayerUi extends PlayerUi
private GestureDetector gestureDetector;
private BasePlayerGestureListener playerGestureListener;
@Nullable private View.OnLayoutChangeListener onLayoutChangeListener = null;
@Nullable
private View.OnLayoutChangeListener onLayoutChangeListener = null;
@NonNull private final SeekbarPreviewThumbnailHolder seekbarPreviewThumbnailHolder =
@NonNull
private final SeekbarPreviewThumbnailHolder seekbarPreviewThumbnailHolder =
new SeekbarPreviewThumbnailHolder();
@ -187,13 +189,13 @@ public abstract class VideoPlayerUi extends PlayerUi
abstract BasePlayerGestureListener buildGestureListener();
protected void initListeners() {
binding.qualityTextView.setOnClickListener(this);
binding.playbackSpeed.setOnClickListener(this);
binding.qualityTextView.setOnClickListener(makeOnClickListener(this::onQualityClicked));
binding.playbackSpeed.setOnClickListener(makeOnClickListener(this::onPlaybackSpeedClicked));
binding.playbackSeekBar.setOnSeekBarChangeListener(this);
binding.captionTextView.setOnClickListener(this);
binding.resizeTextView.setOnClickListener(this);
binding.playbackLiveSync.setOnClickListener(this);
binding.captionTextView.setOnClickListener(makeOnClickListener(this::onCaptionClicked));
binding.resizeTextView.setOnClickListener(makeOnClickListener(this::onResizeClicked));
binding.playbackLiveSync.setOnClickListener(makeOnClickListener(player::seekToDefault));
playerGestureListener = buildGestureListener();
gestureDetector = new GestureDetector(context, playerGestureListener);
@ -202,20 +204,36 @@ public abstract class VideoPlayerUi extends PlayerUi
binding.repeatButton.setOnClickListener(v -> onRepeatClicked());
binding.shuffleButton.setOnClickListener(v -> onShuffleClicked());
binding.playPauseButton.setOnClickListener(this);
binding.playPreviousButton.setOnClickListener(this);
binding.playNextButton.setOnClickListener(this);
binding.playPauseButton.setOnClickListener(makeOnClickListener(player::playPause));
binding.playPreviousButton.setOnClickListener(makeOnClickListener(player::playPrevious));
binding.playNextButton.setOnClickListener(makeOnClickListener(player::playNext));
binding.moreOptionsButton.setOnClickListener(this);
binding.moreOptionsButton.setOnLongClickListener(this);
binding.share.setOnClickListener(this);
binding.share.setOnLongClickListener(this);
binding.fullScreenButton.setOnClickListener(this);
binding.screenRotationButton.setOnClickListener(this);
binding.playWithKodi.setOnClickListener(this);
binding.openInBrowser.setOnClickListener(this);
binding.playerCloseButton.setOnClickListener(this);
binding.switchMute.setOnClickListener(this);
binding.moreOptionsButton.setOnClickListener(
makeOnClickListener(this::onMoreOptionsClicked));
binding.share.setOnClickListener(makeOnClickListener(() -> {
final PlayQueueItem currentItem = player.getCurrentItem();
if (currentItem != null) {
ShareUtils.shareText(context, currentItem.getTitle(),
player.getVideoUrlAtCurrentTime(), currentItem.getThumbnailUrl());
}
}));
binding.share.setOnLongClickListener(v -> {
ShareUtils.copyToClipboard(context, player.getVideoUrlAtCurrentTime());
return true;
});
binding.fullScreenButton.setOnClickListener(makeOnClickListener(() -> {
player.setRecovery();
NavigationHelper.playOnMainPlayer(context,
Objects.requireNonNull(player.getPlayQueue()), true);
}));
binding.playWithKodi.setOnClickListener(makeOnClickListener(this::onPlayWithKodiClicked));
binding.openInBrowser.setOnClickListener(makeOnClickListener(this::onOpenInBrowserClicked));
binding.playerCloseButton.setOnClickListener(makeOnClickListener(() ->
// set package to this app's package to prevent the intent from being seen outside
context.sendBroadcast(new Intent(VideoDetailFragment.ACTION_HIDE_MAIN_PLAYER)
.setPackage(App.PACKAGE_NAME))
));
binding.switchMute.setOnClickListener(makeOnClickListener(player::toggleMute));
ViewCompat.setOnApplyWindowInsetsListener(binding.itemsListPanel, (view, windowInsets) -> {
final Insets cutout = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout());
@ -229,11 +247,8 @@ public abstract class VideoPlayerUi extends PlayerUi
// player_overlays and fast_seek_overlay too. Without it they will be off-centered.
onLayoutChangeListener =
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
binding.playerOverlays.setPadding(
v.getPaddingLeft(),
v.getPaddingTop(),
v.getPaddingRight(),
v.getPaddingBottom());
binding.playerOverlays.setPadding(v.getPaddingLeft(), v.getPaddingTop(),
v.getPaddingRight(), v.getPaddingBottom());
// If we added padding to the fast seek overlay, too, it would not go under the
// system ui. Instead we apply negative margins equal to the window insets of
@ -603,11 +618,6 @@ public abstract class VideoPlayerUi extends PlayerUi
player.changeState(STATE_PAUSED_SEEK);
}
player.saveWasPlaying();
if (player.isPlaying()) {
player.getExoPlayer().pause();
}
showControls(0);
animate(binding.currentDisplaySeek, true, DEFAULT_CONTROLS_DURATION,
AnimationType.SCALE_AND_ALPHA);
@ -622,7 +632,7 @@ public abstract class VideoPlayerUi extends PlayerUi
}
player.seekTo(seekBar.getProgress());
if (player.wasPlaying() || player.getExoPlayer().getDuration() == seekBar.getProgress()) {
if (player.getExoPlayer().getDuration() == seekBar.getProgress()) {
player.getExoPlayer().play();
}
@ -636,9 +646,8 @@ public abstract class VideoPlayerUi extends PlayerUi
if (!player.isProgressLoopRunning()) {
player.startProgressLoop();
}
if (player.wasPlaying()) {
showControlsThenHide();
}
showControlsThenHide();
}
//endregion
@ -1173,8 +1182,6 @@ public abstract class VideoPlayerUi extends PlayerUi
binding.qualityTextView.setText(MediaFormat.getNameById(videoStream.getFormatId())
+ " " + videoStream.getResolution());
}
player.saveWasPlaying();
}
/**
@ -1326,86 +1333,39 @@ public abstract class VideoPlayerUi extends PlayerUi
//////////////////////////////////////////////////////////////////////////*/
//region Click listeners
@Override
public void onClick(final View v) {
if (DEBUG) {
Log.d(TAG, "onClick() called with: v = [" + v + "]");
}
if (v.getId() == binding.resizeTextView.getId()) {
onResizeClicked();
} else if (v.getId() == binding.captionTextView.getId()) {
onCaptionClicked();
} else if (v.getId() == binding.playbackLiveSync.getId()) {
player.seekToDefault();
} else if (v.getId() == binding.playPauseButton.getId()) {
player.playPause();
} else if (v.getId() == binding.playPreviousButton.getId()) {
player.playPrevious();
} else if (v.getId() == binding.playNextButton.getId()) {
player.playNext();
} else if (v.getId() == binding.moreOptionsButton.getId()) {
onMoreOptionsClicked();
} else if (v.getId() == binding.share.getId()) {
final PlayQueueItem currentItem = player.getCurrentItem();
if (currentItem != null) {
ShareUtils.shareText(context, currentItem.getTitle(),
player.getVideoUrlAtCurrentTime(), currentItem.getThumbnailUrl());
}
} else if (v.getId() == binding.playWithKodi.getId()) {
onPlayWithKodiClicked();
} else if (v.getId() == binding.openInBrowser.getId()) {
onOpenInBrowserClicked();
} else if (v.getId() == binding.fullScreenButton.getId()) {
player.setRecovery();
NavigationHelper.playOnMainPlayer(context, player.getPlayQueue(), true);
return;
} else if (v.getId() == binding.switchMute.getId()) {
player.toggleMute();
} else if (v.getId() == binding.playerCloseButton.getId()) {
// set package to this app's package to prevent the intent from being seen outside
context.sendBroadcast(new Intent(VideoDetailFragment.ACTION_HIDE_MAIN_PLAYER)
.setPackage(App.PACKAGE_NAME));
} else if (v.getId() == binding.playbackSpeed.getId()) {
onPlaybackSpeedClicked();
} else if (v.getId() == binding.qualityTextView.getId()) {
onQualityClicked();
}
manageControlsAfterOnClick(v);
}
/**
* Manages the controls after a click occurred on the player UI.
* @param v The view that was clicked
* Create on-click listener which manages the player controls after the view on-click action.
*
* @param runnable The action to be executed.
* @return The view click listener.
*/
public void manageControlsAfterOnClick(@NonNull final View v) {
if (player.getCurrentState() == STATE_COMPLETED) {
return;
}
protected View.OnClickListener makeOnClickListener(@NonNull final Runnable runnable) {
return v -> {
if (DEBUG) {
Log.d(TAG, "onClick() called with: v = [" + v + "]");
}
controlsVisibilityHandler.removeCallbacksAndMessages(null);
showHideShadow(true, DEFAULT_CONTROLS_DURATION);
animate(binding.playbackControlRoot, true, DEFAULT_CONTROLS_DURATION,
AnimationType.ALPHA, 0, () -> {
if (player.getCurrentState() == STATE_PLAYING && !isSomePopupMenuVisible) {
if (v.getId() == binding.playPauseButton.getId()
// Hide controls in fullscreen immediately
|| (v.getId() == binding.screenRotationButton.getId()
&& isFullscreen())) {
hideControls(0, 0);
} else {
hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME);
runnable.run();
// Manages the player controls after handling the view click.
if (player.getCurrentState() == STATE_COMPLETED) {
return;
}
controlsVisibilityHandler.removeCallbacksAndMessages(null);
showHideShadow(true, DEFAULT_CONTROLS_DURATION);
animate(binding.playbackControlRoot, true, DEFAULT_CONTROLS_DURATION,
AnimationType.ALPHA, 0, () -> {
if (player.getCurrentState() == STATE_PLAYING && !isSomePopupMenuVisible) {
if (v == binding.playPauseButton
// Hide controls in fullscreen immediately
|| (v == binding.screenRotationButton && isFullscreen())) {
hideControls(0, 0);
} else {
hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME);
}
}
}
});
}
@Override
public boolean onLongClick(final View v) {
if (v.getId() == binding.share.getId()) {
ShareUtils.copyToClipboard(context, player.getVideoUrlAtCurrentTime());
}
return true;
});
};
}
public boolean onKeyDown(final int keyCode) {

View File

@ -44,7 +44,13 @@ public class AppearanceSettingsFragment extends BasePreferenceFragment {
return false;
});
} else {
removePreference(nightThemeKey);
// disable the night theme selection
final Preference preference = findPreference(nightThemeKey);
if (preference != null) {
preference.setEnabled(false);
preference.setSummary(getString(R.string.night_theme_available,
getString(R.string.auto_device_theme_title)));
}
}
}
@ -61,13 +67,6 @@ public class AppearanceSettingsFragment extends BasePreferenceFragment {
return super.onPreferenceTreeClick(preference);
}
private void removePreference(final String preferenceKey) {
final Preference preference = findPreference(preferenceKey);
if (preference != null) {
getPreferenceScreen().removePreference(preference);
}
}
private void applyThemeChange(final String beginningThemeKey,
final String themeKey,
final Object newValue) {

View File

@ -21,6 +21,7 @@ import org.schabi.newpipe.R;
import org.schabi.newpipe.settings.NewPipeSettings;
public final class PermissionHelper {
public static final int POST_NOTIFICATIONS_REQUEST_CODE = 779;
public static final int DOWNLOAD_DIALOG_REQUEST_CODE = 778;
public static final int DOWNLOADS_REQUEST_CODE = 777;
@ -71,8 +72,7 @@ public final class PermissionHelper {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(activity,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
requestCode);
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, requestCode);
// PERMISSION_WRITE_STORAGE is an
// app-defined int constant. The callback method gets the
@ -83,6 +83,18 @@ public final class PermissionHelper {
return true;
}
public static boolean checkPostNotificationsPermission(final Activity activity,
final int requestCode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
&& ContextCompat.checkSelfPermission(activity,
Manifest.permission.POST_NOTIFICATIONS)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity,
new String[] {Manifest.permission.POST_NOTIFICATIONS}, requestCode);
return false;
}
return true;
}
/**
* In order to be able to draw over other apps,

View File

@ -1,7 +1,6 @@
package org.schabi.newpipe.util;
import android.content.Context;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -11,6 +10,8 @@ import android.widget.Spinner;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.collection.SparseArrayCompat;
import org.schabi.newpipe.DownloaderImpl;
import org.schabi.newpipe.R;
@ -39,10 +40,10 @@ import us.shandian.giga.util.Utility;
* @param <U> the secondary stream type's class extending {@link Stream}
*/
public class StreamItemAdapter<T extends Stream, U extends Stream> extends BaseAdapter {
private final Context context;
@NonNull
private final StreamSizeWrapper<T> streamsWrapper;
private final SparseArray<SecondaryStreamHelper<U>> secondaryStreams;
@NonNull
private final SparseArrayCompat<SecondaryStreamHelper<U>> secondaryStreams;
/**
* Indicates that at least one of the primary streams is an instance of {@link VideoStream},
@ -51,9 +52,10 @@ public class StreamItemAdapter<T extends Stream, U extends Stream> extends BaseA
*/
private final boolean hasAnyVideoOnlyStreamWithNoSecondaryStream;
public StreamItemAdapter(final Context context, final StreamSizeWrapper<T> streamsWrapper,
final SparseArray<SecondaryStreamHelper<U>> secondaryStreams) {
this.context = context;
public StreamItemAdapter(
@NonNull final StreamSizeWrapper<T> streamsWrapper,
@NonNull final SparseArrayCompat<SecondaryStreamHelper<U>> secondaryStreams
) {
this.streamsWrapper = streamsWrapper;
this.secondaryStreams = secondaryStreams;
@ -61,15 +63,15 @@ public class StreamItemAdapter<T extends Stream, U extends Stream> extends BaseA
checkHasAnyVideoOnlyStreamWithNoSecondaryStream();
}
public StreamItemAdapter(final Context context, final StreamSizeWrapper<T> streamsWrapper) {
this(context, streamsWrapper, null);
public StreamItemAdapter(final StreamSizeWrapper<T> streamsWrapper) {
this(streamsWrapper, new SparseArrayCompat<>(0));
}
public List<T> getAll() {
return streamsWrapper.getStreamsList();
}
public SparseArray<SecondaryStreamHelper<U>> getAllSecondary() {
public SparseArrayCompat<SecondaryStreamHelper<U>> getAllSecondary() {
return secondaryStreams;
}
@ -106,6 +108,7 @@ public class StreamItemAdapter<T extends Stream, U extends Stream> extends BaseA
final View view,
final ViewGroup parent,
final boolean isDropdownItem) {
final var context = parent.getContext();
View convertView = view;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(
@ -129,7 +132,7 @@ public class StreamItemAdapter<T extends Stream, U extends Stream> extends BaseA
if (hasAnyVideoOnlyStreamWithNoSecondaryStream) {
if (videoStream.isVideoOnly()) {
woSoundIconVisibility = hasSecondaryStream(position)
woSoundIconVisibility = secondaryStreams.get(position) != null
// It has a secondary stream associated with it, so check if it's a
// dropdown view so it doesn't look out of place (missing margin)
// compared to those that don't.
@ -163,8 +166,7 @@ public class StreamItemAdapter<T extends Stream, U extends Stream> extends BaseA
}
if (streamsWrapper.getSizeInBytes(position) > 0) {
final SecondaryStreamHelper<U> secondary = secondaryStreams == null ? null
: secondaryStreams.get(position);
final var secondary = secondaryStreams.get(position);
if (secondary != null) {
final long size = secondary.getSizeInBytes()
+ streamsWrapper.getSizeInBytes(position);
@ -196,14 +198,6 @@ public class StreamItemAdapter<T extends Stream, U extends Stream> extends BaseA
return convertView;
}
/**
* @param position which primary stream to check.
* @return whether the primary stream at position has a secondary stream associated with it.
*/
private boolean hasSecondaryStream(final int position) {
return secondaryStreams != null && secondaryStreams.get(position) != null;
}
/**
* @return if there are any video-only streams with no secondary stream associated with them.
* @see #hasAnyVideoOnlyStreamWithNoSecondaryStream
@ -213,7 +207,7 @@ public class StreamItemAdapter<T extends Stream, U extends Stream> extends BaseA
final T stream = streamsWrapper.getStreamsList().get(i);
if (stream instanceof VideoStream) {
final boolean videoOnly = ((VideoStream) stream).isVideoOnly();
if (videoOnly && !hasSecondaryStream(i)) {
if (videoOnly && secondaryStreams.get(i) == null) {
return true;
}
}
@ -228,16 +222,15 @@ public class StreamItemAdapter<T extends Stream, U extends Stream> extends BaseA
* @param <T> the stream type's class extending {@link Stream}
*/
public static class StreamSizeWrapper<T extends Stream> implements Serializable {
private static final StreamSizeWrapper<Stream> EMPTY = new StreamSizeWrapper<>(
Collections.emptyList(), null);
private static final StreamSizeWrapper<Stream> EMPTY =
new StreamSizeWrapper<>(Collections.emptyList(), null);
private final List<T> streamsList;
private final long[] streamSizes;
private final String unknownSize;
public StreamSizeWrapper(final List<T> sL, final Context context) {
this.streamsList = sL != null
? sL
: Collections.emptyList();
public StreamSizeWrapper(@NonNull final List<T> streamList,
@Nullable final Context context) {
this.streamsList = streamList;
this.streamSizes = new long[streamsList.size()];
this.unknownSize = context == null
? "--.-" : context.getString(R.string.unknown_content);
@ -297,10 +290,6 @@ public class StreamItemAdapter<T extends Stream, U extends Stream> extends BaseA
return formatSize(getSizeInBytes(streamIndex));
}
public String getFormattedSize(final T stream) {
return formatSize(getSizeInBytes(stream));
}
private String formatSize(final long size) {
if (size > -1) {
return Utility.formatBytes(size);
@ -308,10 +297,6 @@ public class StreamItemAdapter<T extends Stream, U extends Stream> extends BaseA
return unknownSize;
}
public void setSize(final int streamIndex, final long sizeInBytes) {
streamSizes[streamIndex] = sizeInBytes;
}
public void setSize(final T stream, final long sizeInBytes) {
streamSizes[streamsList.indexOf(stream)] = sizeInBytes;
}

View File

@ -1,5 +1,8 @@
package us.shandian.giga.service;
import static org.schabi.newpipe.BuildConfig.APPLICATION_ID;
import static org.schabi.newpipe.BuildConfig.DEBUG;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@ -22,12 +25,12 @@ import android.os.IBinder;
import android.os.Message;
import android.os.Parcelable;
import android.util.Log;
import android.util.SparseArray;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.collection.SparseArrayCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationCompat.Builder;
import androidx.core.app.ServiceCompat;
@ -37,24 +40,21 @@ import androidx.preference.PreferenceManager;
import org.schabi.newpipe.R;
import org.schabi.newpipe.download.DownloadActivity;
import org.schabi.newpipe.player.helper.LockManager;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import us.shandian.giga.get.DownloadMission;
import us.shandian.giga.get.MissionRecoveryInfo;
import org.schabi.newpipe.streams.io.StoredDirectoryHelper;
import org.schabi.newpipe.streams.io.StoredFileHelper;
import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.PendingIntentCompat;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import us.shandian.giga.get.DownloadMission;
import us.shandian.giga.get.MissionRecoveryInfo;
import us.shandian.giga.postprocessing.Postprocessing;
import us.shandian.giga.service.DownloadManager.NetworkState;
import static org.schabi.newpipe.BuildConfig.APPLICATION_ID;
import static org.schabi.newpipe.BuildConfig.DEBUG;
public class DownloadManagerService extends Service {
private static final String TAG = "DownloadManagerService";
@ -95,7 +95,7 @@ public class DownloadManagerService extends Service {
private Builder downloadDoneNotification = null;
private StringBuilder downloadDoneList = null;
private final ArrayList<Callback> mEchoObservers = new ArrayList<>(1);
private final List<Callback> mEchoObservers = new ArrayList<>(1);
private ConnectivityManager mConnectivityManager;
private ConnectivityManager.NetworkCallback mNetworkStateListenerL = null;
@ -108,7 +108,8 @@ public class DownloadManagerService extends Service {
private int downloadFailedNotificationID = DOWNLOADS_NOTIFICATION_ID + 1;
private Builder downloadFailedNotification = null;
private final SparseArray<DownloadMission> mFailedDownloads = new SparseArray<>(5);
private final SparseArrayCompat<DownloadMission> mFailedDownloads =
new SparseArrayCompat<>(5);
private Bitmap icLauncher;
private Bitmap icDownloadDone;
@ -277,7 +278,7 @@ public class DownloadManagerService extends Service {
}
if (msg.what != MESSAGE_ERROR)
mFailedDownloads.delete(mFailedDownloads.indexOfValue(mission));
mFailedDownloads.remove(mFailedDownloads.indexOfValue(mission));
for (Callback observer : mEchoObservers)
observer.handleMessage(msg);
@ -461,7 +462,7 @@ public class DownloadManagerService extends Service {
}
public void notifyFailedDownload(DownloadMission mission) {
if (!mDownloadNotificationEnable || mFailedDownloads.indexOfValue(mission) >= 0) return;
if (!mDownloadNotificationEnable || mFailedDownloads.containsValue(mission)) return;
int id = downloadFailedNotificationID++;
mFailedDownloads.put(id, mission);

View File

@ -48,6 +48,8 @@
<org.schabi.newpipe.views.NewPipeTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_playlist_play"
android:drawablePadding="4dp"
android:gravity="center_vertical"
android:text="@string/play_all"
android:textColor="?attr/colorAccent"

View File

@ -16,4 +16,7 @@
<item
android:id="@+id/menu_item_share"
android:title="@string/share" />
<item
android:id="@+id/menu_item_download"
android:title="@string/download" />
</menu>

View File

@ -5,7 +5,7 @@
<string name="no_player_found">Yayım oynadıcı tapılmadı. \"VLC\" yüklənilsin\?</string>
<string name="no_player_found_toast">Yayım oynadıcı tapılmadı (Oynatmaq üçün VLC\'ni quraşdıra bilərsiniz).</string>
<string name="install">Yüklə</string>
<string name="cancel">İmtina</string>
<string name="cancel">Ləğv et</string>
<string name="open_in_browser">Brauzerdə aç</string>
<string name="share">Paylaş</string>
<string name="download">Endir</string>
@ -17,7 +17,7 @@
<string name="use_external_video_player_title">Xarici video oynadıcı istifadə et</string>
<string name="use_external_video_player_summary">Bəzi qətnamələrdə səsi silir</string>
<string name="use_external_audio_player_title">Xarici səs oynadıcı istifadə et</string>
<string name="subscribe_button_title">Abunə Olun</string>
<string name="subscribe_button_title">Abunə Ol</string>
<string name="subscribed_button_title">Abunə olundu</string>
<string name="channel_unsubscribed">Kanal abunəliyi ləğv edildi</string>
<string name="show_info">Məlumat göstər</string>
@ -30,7 +30,7 @@
<string name="download_path_dialog_title">Video faylları üçün endirmə qovluğunu seç</string>
<string name="download_path_audio_title">Səs endirmə qovluğu</string>
<string name="download_path_audio_summary">Endirilmiş səs faylları burada saxlanılır</string>
<string name="download_path_audio_dialog_title">Səs faylları üçün endirmə qovluğunu seç</string>
<string name="download_path_audio_dialog_title">Səs faylları üçün endirmə qovluğu seç</string>
<string name="default_resolution_title">Defolt keyfiyyət</string>
<string name="show_higher_resolutions_title">Daha böyük keyfiyyət seçimləri göstər</string>
<string name="play_with_kodi_title">\"Kodi\" ilə Oynat</string>
@ -40,13 +40,13 @@
<string name="play_audio">Səs</string>
<string name="default_audio_format_title">Defolt səs formatı</string>
<string name="default_video_format_title">Defolt video formatı</string>
<string name="theme_title">Mövzu</string>
<string name="theme_title">Tema</string>
<string name="light_theme_title">İşıqlı</string>
<string name="dark_theme_title">Qaranlıq</string>
<string name="black_theme_title">Qara</string>
<string name="unsubscribe">Abunəlikdən çıxın</string>
<string name="open_in_popup_mode">Ani pəncərə rejimində aç</string>
<string name="autoplay_title">Avtomatik oynatma</string>
<string name="autoplay_title">Avtomatik oynat</string>
<string name="download_dialog_title">Endir</string>
<string name="resume_on_audio_focus_gain_summary">Fasilələrdən sonra (məsələn, telefon zəngləri) oynatmağa davam etdir</string>
<string name="resume_on_audio_focus_gain_title">Oynatmanı davam etdir</string>
@ -54,24 +54,24 @@
<string name="settings_category_clear_data_title">Məlumat təmizlə</string>
<string name="enable_playback_state_lists_summary">Siyahılarda oynatma mövqelərini göstər</string>
<string name="enable_playback_state_lists_title">Siyahılardakı mövqelər</string>
<string name="enable_playback_resume_summary">Son oynatma mövqeyinə qaytar</string>
<string name="enable_playback_resume_summary">Son oynatma mövqeyini qaytar</string>
<string name="enable_playback_resume_title">Oynatmanı davam etdir</string>
<string name="enable_watch_history_title">Baxış tarixçəsi</string>
<string name="enable_search_history_summary">Axtarış sorğularını yerli olaraq saxla</string>
<string name="enable_search_history_title">Axtarış tarixçəsi</string>
<string name="show_search_suggestions_summary">Axtarış edərkən göstəriləcək təklifləri seç</string>
<string name="show_search_suggestions_title">Axtarış təklifləri</string>
<string name="brightness_gesture_control_summary">Oynadıcının parlaqlığını nizamlamaq üçün jestlərdən istifadə et</string>
<string name="brightness_gesture_control_title">Parlaqlığı jestlə nizamlama</string>
<string name="volume_gesture_control_summary">Oynadıcının səsini nizamlamaq üçün jestlərdən istifadə et</string>
<string name="volume_gesture_control_title">Səsi jestlə nizamla</string>
<string name="auto_queue_toggle">Avto-növbələ</string>
<string name="auto_queue_title">Növbəti Yayımı Avto-növbələ</string>
<string name="brightness_gesture_control_summary">Oynadıcının parlaqlığını nizamlamaq üçün jestləri istifadə et</string>
<string name="brightness_gesture_control_title">Parlaqlığı jestlə nizamlamaq</string>
<string name="volume_gesture_control_summary">Oynadıcı səsini nizamlamaq üçün jestləri istifadə et</string>
<string name="volume_gesture_control_title">Səsi jestlə idarə etmək</string>
<string name="auto_queue_toggle">Avto-növbələ</string>
<string name="auto_queue_title">Növbəti Yayımı Avto-növbələ</string>
<string name="metadata_cache_wipe_complete_notice">Üst məlumat keşi silindi</string>
<string name="metadata_cache_wipe_summary">Keşlənmiş bütün veb-səhifə məlumatlarını sil</string>
<string name="metadata_cache_wipe_title">Keşlənmiş üst məlumatı təmizlə</string>
<string name="thumbnail_cache_wipe_complete_notice">Şəkil keşi silindi</string>
<string name="show_comments_summary">Şərhləri gizlətmək üçün söndür</string>
<string name="show_comments_summary">Şərhləri gizlətmək üçün bağla</string>
<string name="show_comments_title">Şərhləri göstər</string>
<string name="clear_queue_confirmation_description">Aktiv oynadıcının növbəsi dəyişdiriləcək</string>
<string name="clear_queue_confirmation_summary">Bir oynadıcıdan digərinə keçid növbənizi dəyişdirə bilər</string>
@ -94,7 +94,7 @@
<string name="controls_popup_title">Ani Pəncərə</string>
<string name="tab_choose">Paneli Seç</string>
<string name="subscription_update_failed">Abunəliyi yeniləmək alınmadı</string>
<string name="subscription_change_failed">Abunəliyi dəyişdirmək alınmadı</string>
<string name="subscription_change_failed">Abunəliyi dəyişmək alınmadı</string>
<string name="search_showing_result_for">Nəticələr göstərilir: %s</string>
<string name="channels">Kanallar</string>
<string name="video_detail_by">%s tərəfindən</string>
@ -102,8 +102,8 @@
<string name="show_age_restricted_content_summary">Yaş həddi səbəbiylə (məsələn, 18+) uşaqlar üçün uyğun olmayan məzmunu göstər</string>
<string name="show_age_restricted_content_title">Yaş məhdudiyyətli məzmunu göstər</string>
<string name="content">Məzmun</string>
<string name="popup_playing_toast">Ani pəncərədə oynadılır</string>
<string name="background_player_playing_toast">Arxa fonda oynadılır</string>
<string name="popup_playing_toast">Ani pəncərə rejimində oynadılır</string>
<string name="background_player_playing_toast">Fonda oynadılır</string>
<string name="settings_category_updates_title">Yeniləmələr</string>
<string name="settings_category_debug_title">Sazlama</string>
<string name="settings_category_appearance_title">Görünüş</string>
@ -115,7 +115,7 @@
<string name="default_content_country_title">Defolt məzmun ölkəsi</string>
<string name="unsupported_url_dialog_message">URL\'i tanımaq olmadı. Başqa tətbiqlə açılsın\?</string>
<string name="unsupported_url">Dəstəklənməyən URL\'i</string>
<string name="show_hold_to_append_title">\"Növbəyə əlavə etmək üçün basılı saxla\" ipucusun göstər</string>
<string name="show_hold_to_append_title">\"Növbələmək üçün basılı saxla\" tövsiyəsin göstər</string>
<string name="show_next_and_similar_title">\"Növbəti\" və \"Bənzər\" videoları göstər</string>
<string name="export_data_summary">Tarixçəni, abunəlikləri, pleylistləri və tənzimləmələri ixrac edin</string>
<string name="import_data_summary">Cari tarixçənizi, abunəliklərinizi, pleylistlərinizi və (könüllü) tənzimləmələrinizi etibarsız edir</string>
@ -179,7 +179,7 @@
<string name="general_error">Xəta</string>
<string name="search_history_deleted">Axtarış tarixçəsi silindi</string>
<string name="delete_search_history_alert">Bütün axtarış tarixçəsi silinsin\?</string>
<string name="clear_search_history_summary">Axtarışdakı açar sözlərin tarixçəsini silir</string>
<string name="clear_search_history_summary">Açar sözləri axtarışının tarixçəsini silir</string>
<string name="clear_search_history_title">Axtarış tarixçəsini silin</string>
<string name="watch_history_states_deleted">Oynatma mövqeləri silindi</string>
<string name="delete_playback_states_alert">Bütün oynatma mövqeləri silinsin\?</string>
@ -208,7 +208,7 @@
<string name="limit_mobile_data_usage_title">Mobil internet istifadə edərkən görüntü keyfiyyətini məhdudlaşdır</string>
<string name="limit_data_usage_none_description">Limitsiz</string>
<string name="one_item_deleted">1 element silindi.</string>
<string name="peertube_instance_add_title">Server əlavə edin</string>
<string name="peertube_instance_add_title">Nümunə əlavə et</string>
<string name="peertube_instance_url_summary">Sevimli \"PeerTube\" nümunələrinizi seçin</string>
<string name="delete_downloaded_files">Endirilmiş faylları silin</string>
<string name="confirm_prompt">Endirmə tarixçənizi təmizləmək və ya endirilmiş bütün faylları silmək istəyirsiniz\?</string>
@ -217,7 +217,7 @@
<string name="pause_downloads">Endirmələri dayandır</string>
<string name="downloads_storage_ask_title">Haraya endiriləcəyini soruş</string>
<string name="downloads_storage_ask_summary">Sizdən hər endirmənin harada saxlanılacağı soruşulacaq.
\nXarici SD karta yükləmək istəyirsinizsə, sistem qovluğu seçicisini (SAF) aktiv edin</string>
\nXarici SD karta endirmək istəyirsinizsə, sistem qovluğu seçicisini (SAF) aktiv edin</string>
<string name="downloads_storage_use_saf_summary">\'Yaddaş Giriş Çərçivəsi \' xarici SD karta endirməyə imkan verir</string>
<string name="systems_language">Sistem defoltu</string>
<string name="app_language_title">Tətbiq dili</string>
@ -262,7 +262,7 @@
<string name="download_to_sdcard_error_title">Xarici yaddaş əlçatan deyil</string>
<string name="clear_views_history_summary">Oynadılmış yayımlar tarixçəsini və oynatma mövqelərini silir</string>
<string name="show_meta_info_title">Üst məlumatı göstər</string>
<string name="show_description_summary">Video açıqlamasını və əlavə məlumatı gizlətmək üçün söndürün</string>
<string name="show_description_summary">Video açıqlamasını və əlavə məlumatı gizlətmək üçün bağla</string>
<string name="show_description_title">ıqlamanı göstər</string>
<string name="notification_colorize_title">Bildirişi rəngləndir</string>
<string name="invalid_directory">Belə qovluq yoxdur</string>
@ -270,10 +270,10 @@
<string name="external_player_unsupported_link_type">Xarici oynadıcılar bu cür linkləri dəstəkləmir</string>
<string name="local_search_suggestions">Yerli axtarış təklifləri</string>
<string name="video">Video</string>
<string name="related_items_tab_description">Əlaqədar yayımlar</string>
<string name="related_items_tab_description">Əlaqəli elementlər</string>
<string name="mark_as_watched">Baxılmış kimi işarələ</string>
<string name="open_with">ilə aç</string>
<string name="night_theme_title">Gecə Mövzusu</string>
<string name="night_theme_title">Gecə Teması</string>
<string name="popup_remember_size_pos_title">Ani pəncərə xüsusiyyətlərini xatırla</string>
<string name="popup_remember_size_pos_summary">Ani pəncərənin son ölçüsü və mövqeyini xatırla</string>
<string name="video_streams_empty">Video yayımı tapılmadı</string>
@ -292,7 +292,7 @@
<string name="permission_display_over_apps">Digər tətbiqlərin üzərində göstərməyə icazə ver</string>
<string name="restore_defaults_confirmation">İlkin tənzimləmələri qaytarmaq istəyirsiniz\?</string>
<string name="download_thumbnail_summary">Miniatürlərin yüklənməsini, dataya qənaət etmək və yaddaşdan istifadəni azaltmaq üçün söndürün. Dəyişikliklər həm yaddaşdaxili, həm də diskdə olan təsvir keşini təmizləyir</string>
<string name="enqueue_next_stream">Növbətini sıraya salın</string>
<string name="enqueue_next_stream">Növbətini növbələ</string>
<string name="retry">Yenidən Cəhd Et</string>
<string name="settings_category_player_notification_summary">Cari oynatma yayımı bildirişini konfiqurasiya et</string>
<string name="notifications">Bildirişlər</string>
@ -302,7 +302,7 @@
<string name="file_name_empty_error">Fayl adı boş ola bilməz</string>
<string name="saved_tabs_invalid_json">Yadda saxlanmış tabları oxumaq mümkün olmadı, buna görə defolt tablardan istifadə edin</string>
<string name="error_report_notification_title">NewPipe xəta ilə qarşılaşdı, bildirmək üçün toxun</string>
<string name="sorry_string">Bağışlayın, belə olmamalı idi.</string>
<string name="sorry_string">Bağışlayın, o baş verməməli idi.</string>
<string name="error_report_button_text">Bu xətanı e-poçt vasitəsilə bildirin</string>
<string name="error_report_open_issue_button_text">GitHub\'da Hesabat Ver</string>
<string name="error_report_open_github_notice">Zəhmət olmasa, xətanızı müzakirə edən məsələnin mövcud olub-olmadığını yoxlayın. Dublikat biletləri yaradarkən, bizdən faktiki səhvi düzəltməyə sərf edəcəyimiz vaxt alırsınız.</string>
@ -324,7 +324,7 @@
<string name="no_videos">Video yoxdur</string>
<string name="comments_are_disabled">Şərhlər qeyri-aktivdir</string>
<string name="start">Başlat</string>
<string name="pause">Dayandır</string>
<string name="pause">Fasilə</string>
<string name="checksum">Təsdiqləmə</string>
<string name="dismiss">İmtina</string>
<string name="msg_error">Xəta</string>
@ -386,7 +386,7 @@
<string name="caption_auto_generated">Avtomatik yaradıldı</string>
<string name="caption_setting_title">Altyazılar</string>
<string name="leak_canary_not_available">LeakCanary yoxdur</string>
<string name="enable_leak_canary_summary">Yaddaş sızmasının monitorinqi yığın boşaltma zamanı tətbiqin cavab verməməsinə səbəb ola bilər</string>
<string name="enable_leak_canary_summary">Yaddaş sızma monitorinqi yığın boşaltma zamanı tətbiqin cavab verməməsinə səbəb ola bilər</string>
<string name="show_memory_leaks">Yaddaş sızmalarını göstər</string>
<string name="enable_disposed_exceptions_summary">Utilizasiyadan sonra fraqment və ya fəaliyyətin yaşam dövründən kənarda çatdırıla bilməyən Rx istisnaları barədə hesabat verməyə məcbur et</string>
<string name="show_original_time_ago_summary">Xidmətlərdən alınmış orijinal mətnlər yayım elementlərində görünəcək</string>
@ -430,8 +430,8 @@
<string name="recent">Ən Yeni</string>
<string name="georestricted_content">Bu məzmun ölkənizdə mövcud deyil.</string>
<string name="paid_content">Bu məzmun yalnız ödəniş etmiş istifadəçilər üçün əlçatandır, ona görə də NewPipe tərəfindən yayımlana və ya endirilə bilməz.</string>
<string name="auto_device_theme_title">Avtomatik (cihaz mövzusu)</string>
<string name="night_theme_summary">Sevimli gecə mövzunuzu seçin — %s</string>
<string name="auto_device_theme_title">Avtomatik (cihaz teması)</string>
<string name="night_theme_summary">Sevimli gecə temanızı seçin — %s</string>
<string name="detail_pinned_comment_view_description">Sabitlənmiş şərh</string>
<string name="notifications_disabled">Bildirişlər deaktiv edilib</string>
<string name="get_notified">Bildiriş al</string>
@ -464,7 +464,7 @@
<string name="downloads_storage_ask_summary_no_saf_notice">Sizdən hər endirmənin harada saxlanılacağı soruşulacaq</string>
<string name="downloads_storage_use_saf_summary_api_29">\"Yaddaş Giriş Çərçivəsi\"yalnız Android 10\'dan başlayaraq dəstəklənir</string>
<string name="detail_sub_channel_thumbnail_view_description">Kanalın avatar miniatürü</string>
<string name="select_night_theme_toast">Sevdiyiniz gecə mövzusunu aşağıda seçə bilərsiniz</string>
<string name="select_night_theme_toast">Sevdiyiniz gecə temasını aşağıda seçə bilərsiniz</string>
<string name="notification_colorize_summary">Android\'in bildiriş rəngini miniatürdəki əsas rəngə uyğun fərdiləşdirməsini təmin et (qeyd edək ki, bu, bütün cihazlarda mövcud deyil)</string>
<string name="view_on_github">GitHub\'da Bax</string>
<string name="donation_title">İanə Et</string>
@ -498,10 +498,10 @@
<string name="notification_scale_to_square_image_title">Miniatürü 1:1 görünüş nisbətinə kəs</string>
<string name="progressive_load_interval_summary">Yükləmə intervalının həcmini dəyişdir (hazırda %s). Daha aşağı dəyər ilkin video yükləməni sürətləndirə bilər. Dəyişikliklər oynadıcının yenidən başladılmasını tələb edir</string>
<string name="show_meta_info_summary">Yayım yaradıcısı, məzmunu və ya axtarış sorğusu haqqında əlavə məlumat olan üst məlumat qutularını gizlətmək üçün söndürün</string>
<string name="auto_queue_summary">Əlaqədar yayımı əlavə etməklə (təkrarlanmayan) sonlanacaq oynatma sırasını davam etdir</string>
<string name="auto_queue_summary">Əlaqəli yayımı əlavə etməklə (təkrarlanmayan) sonlanacaq oynatma növbəsini davam etdir</string>
<string name="remote_search_suggestions">Kənar axtarış təklifləri</string>
<string name="peertube_instance_add_exists">Server artıq mövcuddur</string>
<string name="start_main_player_fullscreen_summary">Videoları mini oynadıcıda başlatma, avtomatik fırlatma kilidlidirsə, birbaşa tam ekran rejiminə keçid. Siz hələ də tam ekran rejimindən çıxmaqla mini pleyerə daxil ola bilərsiniz</string>
<string name="peertube_instance_add_exists">Nümunə artıq mövcuddur</string>
<string name="start_main_player_fullscreen_summary">Videoları mini oynadıcıda başlatma, avtomatik fırlatma kilidlidirsə, birbaşa tam ekran rejiminə keçid. Siz hələ də tam ekrandan çıxmaqla mini oynadıcıya daxil ola bilərsiniz</string>
<string name="more_than_100_videos">100+ video</string>
<string name="infinite_videos">∞ video</string>
<string name="no_comments">Şərhlər yoxdur</string>
@ -548,7 +548,7 @@
<string name="semitone">Yarımton</string>
<plurals name="download_finished_notification">
<item quantity="one">Endirmə tamamlandı</item>
<item quantity="other">%s endirmələr tamamlandı</item>
<item quantity="other">%s endirmə tamamlandı</item>
</plurals>
<string name="progressive_load_interval_exoplayer_default">Defolt ExoPlayer</string>
<string name="feed_use_dedicated_fetch_method_title">Mövcud olduqda xüsusi axından al</string>
@ -605,11 +605,11 @@
<string name="info_labels">Nə:\\nTələb:\\nMəzmun Dili:\\nMəzmun Ölkəsi:\\nTətbiq Dili:\\nXidmət:\\nGMT Saatı:\\nPaket:\\nVersiya:\\nƏS versiyası:</string>
<string name="error_snackbar_message">Bağışlayın, nəsə xəta baş verdi.</string>
<string name="copy_for_github">Formatlanmış hesabatı kopyala</string>
<string name="peertube_instance_add_help">Server URL\'sini daxil edin</string>
<string name="peertube_instance_add_fail">Serveri doğrulamaq mümkün olmadı</string>
<string name="peertube_instance_add_help">Nümunə URL\'sini daxil et</string>
<string name="peertube_instance_add_fail">Nümunəni doğrulamaq mümkün olmadı</string>
<string name="peertube_instance_url_help">%s-də bəyəndiyiniz nümunələri tapın</string>
<string name="show_hold_to_append_summary">Video \"Təfsilatlar:\"səhifəsində fon və ya ani pəncərə düyməsini basarkən ipucu göstər</string>
<string name="caption_setting_description">Oynadıcı altyazı miqyasını və arxa fon üslublarını dəyişdirin. Effektiv olması üçün tətbiqin yenidən başladılması tələb olunur</string>
<string name="caption_setting_description">Oynadıcı altyazı mətn miqyasını və arxa fon üslublarını dəyişdirin. Effektiv olması üçün tətbiqi yenidən başlatmaq tələb olunur</string>
<string name="error_occurred_detail">Xəta baş verdi: %1$s</string>
<string name="invalid_file">Fayl mövcud deyil, yaxud oxumaq və ya yazmaq icazəsi yoxdur</string>
<string name="parsing_error">Veb saytı təhlil etmək alınmadı</string>
@ -654,7 +654,7 @@
<string name="youtube_signature_deobfuscation_error">Video URL\'i imzasının şifrəsi qırılmadı</string>
<string name="no_streams_available_download">Endirmək üçün heç bir yayım yoxdur</string>
<string name="error_report_notification_toast">Xəta baş verdi, bildirişə baxın</string>
<string name="your_comment">Şərhiniz (İngilis dilində):</string>
<string name="your_comment">Şərhiniz (İngiliscə):</string>
<string name="detail_thumbnail_view_description">Video oynat, müddət:</string>
<string name="no_available_dir">Zəhmət olmasa, daha sonra tənzimləmələrdə endirmə qovluğunu təyin et</string>
<string name="msg_running">NewPipe Endirilir</string>
@ -704,8 +704,8 @@
\nZəhmət olmasa ,Yaddaş Giriş Çərçivəsinə uyğun fayl menecerini quraşdırın</string>
<string name="youtube_music_premium_content">Bu video yalnız YouTube Music Premium üzvləri üçün əlçatandır, ona görə də NewPipe tərəfindən yayımlamaq və ya endirmək mümkün deyil.</string>
<string name="description_select_note">İndi açıqlamadakı mətni seçə bilərsiniz. Nəzərə alın ki, seçim rejimində səhifə titrəyə və keçidlər kliklənməyə bilər.</string>
<string name="notification_scale_to_square_image_summary">Bildirişdə göstərilən video miniatürünü 16:9-dan 1:1 nisbətinə qədər kəs</string>
<string name="notification_actions_summary">Aşağıdakı bildiriş fəaliyyətini hər birinin üzərinə toxunaraq redaktə edin. Sağdakı təsdiq qutularından istifadə edərək yığcam bildirişdə göstərilməsi üçün onlardan üçə qədərini seç</string>
<string name="notification_scale_to_square_image_summary">Bildirişdə göstərilən video miniatürünü 16:9-dan 1:1 görünüş nisbətinə qədər kəs</string>
<string name="notification_actions_summary">Aşağıdakı bildiriş fəaliyyətini hər birinin üzərinə toxunaraq redaktə edin. Sağdakı təsdiq qutularından istifadə edərək yığcam bildirişdə göstərilməsi üçün onların üçə qədərini seç</string>
<string name="invalid_source">Belə fayl/məzmun mənbəyi yoxdur</string>
<string name="selected_stream_external_player_not_supported">Seçilmiş yayım xarici oynadıcılar tərəfindən dəstəklənmir</string>
<string name="streams_not_yet_supported_removed">Yükləyici tərəfindən hələ dəstəklənməyən yayımlar göstərilmir</string>

View File

@ -18,7 +18,7 @@
<string name="play_audio">ध्वनि</string>
<string name="light_theme_title">रौशनी</string>
<string name="black_theme_title">काला</string>
<string name="enable_watch_history_title">देखे हुए विडियोज का इतिहास</string>
<string name="enable_watch_history_title">देखे हुए वीडियोज़ का इतिहास</string>
<string name="download_dialog_title">डाउनलोड करे</string>
<string name="settings_category_video_audio_title">वीडियो और ऑडियो</string>
<string name="settings_category_history_title">इतिहास और कैश</string>
@ -29,7 +29,7 @@
<string name="title_licenses">तृतीय-पक्ष लाइसेंस</string>
<string name="tab_about">ऐप के बारे में और सामान्य प्रश्न</string>
<string name="tab_licenses">लाइसेंस</string>
<string name="view_on_github">GitHub में देखें</string>
<string name="view_on_github">गिटहब में देखें</string>
<string name="app_license_title">न्यूपाइप का लाइसेंस</string>
<string name="read_full_license">लाइसेंस पढ़ें</string>
<string name="contribution_title">योगदान करें</string>
@ -41,12 +41,12 @@
<string name="cancel">रद्द करें</string>
<string name="did_you_mean">क्या आप का मतलब \"%1$s\" था\?</string>
<string name="share_dialog_title">के साथ शेयर करे</string>
<string name="use_external_video_player_title">कोई दूसरा विडियो चालक प्रयोग करें</string>
<string name="use_external_video_player_summary">कुछ विडियो गुणवत्ता स्तर पर ध्वनि हट सकती है</string>
<string name="use_external_video_player_title">कोई दूसरा वडियो चालक प्रयोग करें</string>
<string name="use_external_video_player_summary">कुछ वडियो गुणवत्ता स्तर पर ध्वनि हट सकती है</string>
<string name="use_external_audio_player_title">कोई दूसरा ध्वनि चालक उपयोग करें</string>
<string name="subscription_change_failed">सब्सक्रिप्शन बदली नहीं जा सकी</string>
<string name="subscription_update_failed">सब्सक्रिप्शन अपडेट नहीं किया जा सका</string>
<string name="fragment_feed_title">देखे की क्या नया है</string>
<string name="fragment_feed_title">देखें कि क्या नया है</string>
<string name="download_path_title">वीडियो डाउनलोड का फ़ोल्डर</string>
<string name="download_path_summary">डाउनलोड की गई वीडियो फ़ाइलें यहां संग्रहीत हैं</string>
<string name="download_path_dialog_title">वीडियो फ़ाइलों के लिए डाउनलोड फ़ोल्डर चुनें</string>
@ -56,33 +56,33 @@
<string name="default_resolution_title">प्रथम स्थापित गुणवत्ता स्तर</string>
<string name="default_popup_resolution_title">पॉपअप का प्रथम स्थापित गुणवत्ता स्तर</string>
<string name="show_higher_resolutions_title">उच्च गुणवत्ता स्तर दिखाएं</string>
<string name="show_higher_resolutions_summary">केवल कुछ ही यंत्र 2K/4K मे विडियो चला सकते हैं</string>
<string name="show_higher_resolutions_summary">केवल कुछ ही यंत्र 2K/4K मे वडियो चला सकते हैं</string>
<string name="play_with_kodi_title">Kodi मे चलाए</string>
<string name="kore_not_found">Kore ऐप नहीं मिली, इसे स्थापित करें\?</string>
<string name="show_play_with_kodi_title">\"Kodi मे चलाएं\" वाला विकल्प दिखाएँ</string>
<string name="show_play_with_kodi_summary">Kodi मीडिया सेंटर से विडियो चलने के लिए विकल्प प्रदर्शित करें</string>
<string name="show_play_with_kodi_summary">कोडी मीडिया सेंटर से वीडियो चलने के लिए विकल्प प्रदर्शित करें</string>
<string name="default_audio_format_title">प्रथम स्थापित ध्वनि फॉर्मेट</string>
<string name="default_video_format_title">प्रथम स्थापित विडियो फॉर्मेट</string>
<string name="default_video_format_title">प्रथम स्थापित वडियो फॉर्मेट</string>
<string name="theme_title">ऐप थीम</string>
<string name="dark_theme_title">गहरा</string>
<string name="popup_remember_size_pos_title">िडियो पॉपअप का आकर और उसकी स्थति को याद रखे</string>
<string name="popup_remember_size_pos_summary">िडियो पॉपअप की अंतिम स्थिति और आकर को याद रखे</string>
<string name="popup_remember_size_pos_title">ीडियो पॉपअप का आकार और उसकी स्थिति को याद रखें</string>
<string name="popup_remember_size_pos_summary">डियो पॉपअप की अंतिम स्थिति और आकर को याद रखे</string>
<string name="show_search_suggestions_title">खोज में सुझाव</string>
<string name="show_search_suggestions_summary">खोज के दौरान दिखाये जाने वाले सुझाव चुने</string>
<string name="enable_search_history_title">खोज का इतिहास</string>
<string name="enable_search_history_summary">खोज के डेटा को सिर्फ डिवाइस मेमोरी में रखे</string>
<string name="enable_watch_history_summary">देखे गए विडियोज की सूची रखे</string>
<string name="enable_watch_history_summary">देखे गए वीडियोज़ की सूची रखें</string>
<string name="resume_on_audio_focus_gain_title">प्लेबैक फिर से शुरू करें</string>
<string name="resume_on_audio_focus_gain_summary">ूकावटे खत्म होने के बाद विडियो प्ले करे (जैसे - फ़ोन कॉल)</string>
<string name="resume_on_audio_focus_gain_summary">ुकावटें खत्म होने के बाद वीडियो प्ले करें (जैसे - फ़ोन कॉल)</string>
<string name="show_next_and_similar_title">\'अगला\' और \'समान\' वीडियो दिखाए</string>
<string name="show_hold_to_append_title">\"कतार में जोड़ने के लिए स्पर्श बनाये रखें\" दिखाएं</string>
<string name="show_hold_to_append_summary">जब बैकग्राउंड और पॉपअप बटन विडियो के विवरण पन्ने में दबाई जाए तो सलाह दिखाएं</string>
<string name="show_hold_to_append_summary">जब बैकग्राउंड और पॉपअप बटन वडियो के विवरण पन्ने में दबाई जाए तो सलाह दिखाएं</string>
<string name="unsupported_url">असमर्थित URL</string>
<string name="content_language_title">डिफ़ॉल्ट विषय की भाषा</string>
<string name="settings_category_player_title">प्लेयर</string>
<string name="settings_category_player_behavior_title">चाल चलन</string>
<string name="settings_category_appearance_title">दिखावट</string>
<string name="popup_playing_toast">िडियो पॉपअप के अंदाज में चल रहा</string>
<string name="popup_playing_toast">डियो पॉपअप के अंदाज में चल रहा</string>
<string name="content">विषयवस्तु</string>
<string name="show_age_restricted_content_title">आयु प्रतिबंधित सामग्री दिखाएं</string>
<string name="duration_live">लाइव</string>
@ -92,23 +92,23 @@
<string name="all">सारे</string>
<string name="disabled">बंद करे</string>
<string name="clear">साफ़</string>
<string name="best_resolution">बेहतर विडियो की क्वालिटी</string>
<string name="undo">वापस जाए</string>
<string name="best_resolution">बेहतर वडियो की क्वालिटी</string>
<string name="undo">वापस जाए</string>
<string name="play_all">सारे प्ले करे</string>
<string name="notification_channel_name">NewPipe की सूचनापत्र</string>
<string name="notification_channel_description">न्यूपाइप के बैकग्राउंड में चल रहे विडियो और पॉपअप विडियो के लिए सूचनापत्र</string>
<string name="notification_channel_description">न्यूपाइप के बैकग्राउंड में चल रहे वीडियो और पॉपअप वीडियो के लिए सूचनापत्र</string>
<string name="unknown_content">[नहीं जानते]</string>
<string name="general_error">त्रुटी</string>
<string name="network_error">नेटवर्क में त्रुटी</string>
<string name="could_not_load_thumbnails">सारे thumbnail(फोटो जो फ़ोन की मेमोरी में है ) भरे नहीं जा सकते</string>
<string name="youtube_signature_deobfuscation_error">िडियो के URL signature को decrypt नहीं कर सकते</string>
<string name="youtube_signature_deobfuscation_error">ीडियो के URL हस्ताक्षर को डीऑबफस्केट नहीं कर सकते</string>
<string name="parsing_error">इस website का निरंक्षण नहीं कर सकते</string>
<string name="content_not_available">विषय वस्तु उपलब्ध नहीं है</string>
<string name="could_not_setup_download_menu">डाउनलोड मेनू को स्थापित नहीं कर सकते</string>
<string name="app_ui_crash">APP/UI टूट गया</string>
<string name="player_stream_failure">इस विडियो को चलाने में असफल हुए</string>
<string name="player_unrecoverable_failure">कभी ठीक न होने वाले विडियो प्लेयर की त्रुटी आ रही है</string>
<string name="player_recoverable_failure">िडियो प्लेयर त्रुटी से ठीक हो रहा है</string>
<string name="player_stream_failure">इस वडियो को चलाने में असफल हुए</string>
<string name="player_unrecoverable_failure">कभी ठीक न होने वाले वडियो प्लेयर की त्रुटी आ रही है</string>
<string name="player_recoverable_failure">डियो प्लेयर त्रुटी से ठीक हो रहा है</string>
<string name="sorry_string">खेद है की, ऐसा होना नहीं चाहिए था.</string>
<string name="error_report_button_text">त्रुटी की रिपोर्ट को ईमेल से भेजे</string>
<string name="error_snackbar_message">माफ़ करे , कुछ त्रुटियाँ हो रही है</string>
@ -124,7 +124,7 @@
<string name="detail_dislikes_img_view_description">नापसंद</string>
<string name="search_no_results">कोई परिणाम नहीं मिला</string>
<string name="empty_list_subtitle">यहां के खालीपन को दूर करने के लिए कुछ सर्च करें या किसी चैनल को सब्सक्राइब करें</string>
<string name="video">िडियो</string>
<string name="video">डियो</string>
<string name="audio">ऑडियो</string>
<string name="retry">फिर से कोशिश करे</string>
<string name="short_thousand">हज़ार</string>
@ -146,7 +146,7 @@
<string name="start">शुरू</string>
<string name="pause">रोकें</string>
<string name="delete">मिटाएँ</string>
<string name="checksum">checksum</string>
<string name="checksum">चेकसम</string>
<string name="ok">ठीक है</string>
<string name="msg_name">फाइल का नाम</string>
<string name="msg_threads">मेसेज के thread</string>
@ -187,10 +187,10 @@
<string name="no_player_found_toast">स्ट्रीमिंग करने के लिए कोई चालक उपलब्ध नहीं है (आप इसे चलाने के लिए VLC चालक स्थापित कर सकते हैं)।</string>
<string name="controls_download_desc">स्ट्रीम फाइल डाउनलोड करें</string>
<string name="show_info">जानकारी दिखाएं</string>
<string name="tab_bookmarks">बुकमार्क किये गए प्लेलिस्टस</string>
<string name="tab_bookmarks">बुकमार्क की गई प्लेलिस्टें</string>
<string name="controls_add_to_playlist_title">में शामिल करें</string>
<string name="default_content_country_title">डिफ़ॉल्ट देश का विषय</string>
<string name="always">हमेशा के लिए</string>
<string name="always">हमेशा</string>
<string name="just_once">सिर्फ एक बार के लिए</string>
<string name="switch_to_background">बैकग्राउंड में स्विच करें</string>
<string name="switch_to_popup">पॉपअप मोड में जाएं</string>
@ -208,7 +208,7 @@
<string name="rename">नाम बदलें</string>
<string name="donation_title">दान करें</string>
<string name="donation_encouragement">न्यूपाइप स्वयंसेवकों द्वारा विकसित किया जाता है जो आपको अच्छा अनुभव देने के लिए अपना खाली समय व्यतीत करते हैं। स्वयंसेवको को मदद भेजे, ताकि वह न्यूपाइप को और अच्छा बना सके।</string>
<string name="give_back">वापस दे</string>
<string name="give_back">वापस दे</string>
<string name="website_title">वेबसाइट</string>
<string name="website_encouragement">अधिक जानकारी और खबरों के लिए न्यूपाइप की वेबसाइट पर जाएं।</string>
<string name="title_last_played">पिछला चलाया गया</string>
@ -281,7 +281,7 @@
\nन्यूपाइप की गोपनीयता नीति विस्तार से समज़ाती है कि कोनसा डेटा भेजा या संग्रह किया जाता है जब आप क्रेश विवरण भेजते है।</string>
<string name="read_privacy_policy">गोपनीयता नीति पढ़े</string>
<string name="import_settings">क्या आप सेटिंग्स भी आयात करना चाहते है?</string>
<string name="preferred_open_action_settings_title">पसंदीदा \'खोलने\' कि प्रक्रिया</string>
<string name="preferred_open_action_settings_title">पसंदीदा \'खोलने\' क प्रक्रिया</string>
<string name="preferred_open_action_settings_summary">सामग्री खोलते समय डिफ़ॉल्ट कारवाही — %s</string>
<string name="caption_setting_title">अनुशीर्षक</string>
<string name="caption_setting_description">प्लेयर अनुशीर्षक के शब्दों का परिमाण और पृष्ठभूमि शैलियों को बदले। लागू करने के लिए ऐप को पुनः प्रारम्भ करना जरूरी है</string>
@ -321,7 +321,7 @@
<string name="minimize_on_exit_title">ऐप बदलते समय उसे मिनिमाइज करे</string>
<string name="minimize_on_exit_summary">मुख्य वीडियो चालक से दूसरी ऐप पर जाने पर — %s</string>
<string name="minimize_on_exit_none_description">कोई नही</string>
<string name="minimize_on_exit_background_description">पृष्ठभूमि प्लेयर में बदले</string>
<string name="minimize_on_exit_background_description">बैकग्राउंड प्लेयर में बदले</string>
<string name="minimize_on_exit_popup_description">पॉप अप प्लेयर में बदले</string>
<string name="app_license">न्यूपाइप एक काॅपीलेफ़्ट फ़्री साॅफ़्टवेर है: इसे आप अपनी इच्छा के अनुसार इस्तेमाल, जाँच, बाँट तथा और बेहतर बना सकते है। खास तौर पर आप इसे फ़्री साॅफ़्टवेर फ़ाउंडेशन के द्वारा जारी जीएनयू जनरल पब्लिक लाइसेंस के तीसरे या उसके बाद आने वाले कोई भी वर्णन के शर्तों के मुताबिक फिर से बाँट या बदल सकते हैं।</string>
<string name="unsubscribe">अनसब्सक्राईब करें</string>
@ -690,7 +690,7 @@
<string name="show_original_time_ago_title">आइटम्स का असल अपलोड समय दिखाएं</string>
<string name="show_original_time_ago_summary">सेवाओं से मूल पाठ स्ट्रीम आइटम में दिखाई देंगे</string>
<string name="remove_watched_popup_warning">प्लेलिस्ट में जोड़े गए पहले और बाद में देखे गए वीडियो हटा दिए जाएंगे।
\nक्या आपको यकीन है\? इसे असंपादित नहीं किया जा सकेगा!</string>
\nक्या यकीनन आप ऐसा चाह्ते है\? इसे असंपादित नहीं किया जा सकेगा!</string>
<plurals name="minutes">
<item quantity="one">%d मिनट</item>
<item quantity="other">%d मिनट</item>
@ -712,7 +712,7 @@
<string name="detail_heart_img_view_description">निर्माता द्वारा दिया दिल</string>
<string name="tablet_mode_title">टैबलेट मोड</string>
<string name="you_successfully_subscribed">आपने इस चैनल को अब सब्सक्राइब किया है</string>
<string name="no_video_streams_available_for_external_players">बाहरी प्लेयरस के लिए कोई विडियो स्ट्रीम उपलब्ध नहीं है</string>
<string name="no_video_streams_available_for_external_players">बाहरी प्लेयरस के लिए कोई वडियो स्ट्रीम उपलब्ध नहीं है</string>
<string name="no_audio_streams_available_for_external_players">बाहरी प्लेयरस के लिए कोई ऑडियो स्ट्रीम उपलब्ध नहीं है</string>
<string name="feed_use_dedicated_fetch_method_summary">कुछ सेवाओं में उपलब्ध, यह आमतौर पर बहुत तेज होता है लेकिन सीमित मात्रा में आइटम और अक्सर अधूरी जानकारी (जैसे कोई अवधि नहीं, आइटम प्रकार, कोई लाइव स्थिति नहीं) लौटा सकता है</string>
<string name="no_appropriate_file_manager_message">इस क्रिया के लिए कोई उपयुक्त फ़ाइल प्रबंधक नहीं मिला।

View File

@ -135,9 +135,9 @@
<string name="controls_download_desc">Közvetítési fájl letöltése</string>
<string name="controls_add_to_playlist_title">Hozzáadás ehhez</string>
<string name="use_inexact_seek_title">Gyorsabb, de pontatlan tekerés használata</string>
<string name="use_inexact_seek_summary">A pontatlan tekerés lehetővé teszi, hogy gyorsabban ugorjon a pozíciókra, de kisebb pontossággal. Az 5, 15, vagy 25 másodperces tekerés nem működik ebben a módban.</string>
<string name="use_inexact_seek_summary">A pontatlan tekerés lehetővé teszi, hogy gyorsabban ugorjon a pozíciókra, de kisebb pontossággal. Az 5, 15, vagy 25 másodperces tekerés nem működik ebben a módban</string>
<string name="download_thumbnail_title">Bélyegképek betöltése</string>
<string name="download_thumbnail_summary">Kapcsolja ki, hogy a megelőzze a bélyegképek betöltését, így csökkentve az adat- és memóriahasználatot. A megváltoztatása törli a memóriában és a meghajtón lévő képgyorsítótárat.</string>
<string name="download_thumbnail_summary">Kapcsolja ki, hogy a megelőzze a bélyegképek betöltését, így csökkentve az adat- és memóriahasználatot. A megváltoztatása törli a memóriában és a meghajtón lévő képgyorsítótárat</string>
<string name="thumbnail_cache_wipe_complete_notice">A bélyegkép gyorsítótár törölve</string>
<string name="metadata_cache_wipe_title">Gyorsítótárazott metaadatok törlése</string>
<string name="metadata_cache_wipe_summary">Minden gyorsítótárazott weboldaladat törlése</string>
@ -266,7 +266,7 @@
<string name="resize_zoom">Nagyítás</string>
<string name="caption_auto_generated">Automatikusan létrehozott</string>
<string name="caption_setting_title">Feliratok</string>
<string name="caption_setting_description">Feliratok méretének és hátterének stílusbeli módosítása. A módosítások életbe lépésehez az alkalmazás újraindítása szükséges.</string>
<string name="caption_setting_description">Feliratok méretének és hátterének stílusbeli módosítása. A módosítások életbe lépésehez az alkalmazás újraindítása szükséges</string>
<string name="import_title">Importálás</string>
<string name="import_from">Importálás a következőből</string>
<string name="export_to">Exportálás a következőbe</string>
@ -491,7 +491,7 @@
<string name="updates_setting_description">Frissítési értesítés megjelenítése, amikor egy új verzió érhető el</string>
<string name="updates_setting_title">Frissítések</string>
<string name="notification_colorize_summary">Az Android igazítsa az értesítés színét a bélyegkép meghatározó színéhez (nem minden eszközön érhető el)</string>
<string name="notification_actions_at_most_three">Legfeljebb három művelet jeleníthető meg a kompakt értesítésben.</string>
<string name="notification_actions_at_most_three">Legfeljebb három művelet jeleníthető meg a kompakt értesítésben!</string>
<string name="notification_actions_summary">Koppintással szerkesztheti az egyes értesítéseken megjelenő műveleteket. Válasszon ki legfeljebb hármat a jobb oldali jelölőnégyzetekkel, amelyek a kompakt értesítéseken is megjelennek.</string>
<string name="notification_action_4_title">Ötödik műveletgomb</string>
<string name="notification_action_3_title">Negyedik műveletgomb</string>
@ -568,13 +568,13 @@
<string name="local_search_suggestions">Helyi keresési javaslatok</string>
<string name="remote_search_suggestions">Távoli keresési javaslatok</string>
<string name="start_main_player_fullscreen_title">A fő lejátszó teljes képernyős indítása</string>
<string name="start_main_player_fullscreen_summary">A videókat ne a kis lejátszóban indítsa el, hanem kapcsolja be a teljes képernyős módot, ha az automatikus forgatás zárolva van. Továbbra is elérheti a kis lejátszót, ha kilép a teljes képernyőből.</string>
<string name="start_main_player_fullscreen_summary">A videókat ne a kis lejátszóban indítsa el, hanem kapcsolja be a teljes képernyős módot, ha az automatikus forgatás zárolva van. Továbbra is elérheti a kis lejátszót, ha kilép a teljes képernyőből</string>
<string name="drawer_header_description">Szolgáltatás be/ki, jelenleg kiválasztott:</string>
<string name="comments_are_disabled">A megjegyzések ki vannak kapcsolva</string>
<string name="main_page_content_swipe_remove">Húzza oldalra az elemeket az eltávolításukhoz</string>
<string name="enqueue_next_stream">A következő sorba állítása</string>
<string name="enqueued_next">A következő sorba állítva</string>
<string name="processing_may_take_a_moment">Feldolgozás… Ez eltarthat egy ideig.</string>
<string name="processing_may_take_a_moment">Feldolgozás… Ez eltarthat egy ideig</string>
<string name="enable_disposed_exceptions_summary">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</string>
<string name="show_original_time_ago_title">Eredeti „ennyi ideje” megjelenítése az elemeken</string>
<string name="disable_media_tunneling_summary">Tiltsa le a médiacsatornázást, ha fekete képernyőt vagy akadozást tapasztal videólejátszáskor</string>
@ -617,7 +617,7 @@
<string name="metadata_privacy_unlisted">Nem listázott</string>
<string name="off">Ki</string>
<string name="no_appropriate_file_manager_message">Nem található megfelelő fájlkezelő ehhez a művelethez.
\nTelepítsen egy fájlkezelőt, vagy próbálja meg letiltani a következőt a letöltési beállításokban: „%s”.</string>
\nTelepítsen egy fájlkezelőt, vagy próbálja meg letiltani a következőt a letöltési beállításokban: „%s”</string>
<plurals name="download_finished_notification">
<item quantity="one">Letöltés befejezve</item>
<item quantity="other">%s letöltés befejezve</item>
@ -656,7 +656,7 @@
<string name="checking_updates_toast">Frissítések keresése…</string>
<string name="video_detail_by">Készítette: %s</string>
<string name="no_appropriate_file_manager_message_android_10">Nem található megfelelő fájlkezelő ehhez a művelethez.
\nTelepítsen egy olyan fájlkezelőt, amely kompatibilis a Storage Access Frameworkkel.</string>
\nTelepítsen egy olyan fájlkezelőt, amely kompatibilis a Storage Access Frameworkkel</string>
<string name="description_select_enable">Szöveg kijelölésének engedélyezése a leírásban</string>
<string name="metadata_category">Kategória</string>
<string name="metadata_tags">Címkék</string>
@ -664,7 +664,7 @@
<string name="feed_use_dedicated_fetch_method_disable_button">Gyors mód letiltása</string>
<string name="remove_watched_popup_yes_and_partially_watched_videos">Igen, és távolítsa el a részben megnézett videókat is</string>
<string name="remove_watched_popup_warning">A videók, melyeket már megnézett miután a lejátszási listához adta őket, el lesznek távolítva.
\nBiztos benne\? Ez nem vonható vissza.</string>
\nBiztos benne\? Ez nem vonható vissza!</string>
<string name="show_original_time_ago_summary">A szolgáltatásokból származó eredeti szövegek láthatók lesznek a közvetítési elemeken</string>
<string name="crash_the_player">Lejátszó összeomlasztása</string>
<string name="show_image_indicators_title">Képjelölők megjelenítése</string>
@ -682,7 +682,7 @@
<string name="detail_pinned_comment_view_description">Rögzített megjegyzés</string>
<string name="leak_canary_not_available">LeakCanary nem elérhető</string>
<string name="settings_category_player_notification_title">Lejátszó értesítés</string>
<string name="progressive_load_interval_summary">Módosítsa a betöltési intervallum méretét (jelenleg %s). Az alacsonyabb érték felgyorsíthatja a videó kezdeti betöltését. A változtatásokhoz a lejátszó újraindítása szükséges.</string>
<string name="progressive_load_interval_summary">Módosítsa a betöltési intervallum méretét (jelenleg %s). Az alacsonyabb érték felgyorsíthatja a videó kezdeti betöltését. A változtatásokhoz a lejátszó újraindítása szükséges</string>
<string name="settings_category_player_notification_summary">Az aktuális lejátszás konfigurálása értesítés</string>
<string name="notifications">Értesítések</string>
<string name="streams_notification_channel_name">Új élő közvetítések</string>
@ -720,6 +720,10 @@
<string name="faq_title">Gyakran ismételt kérdések</string>
<string name="faq">Megtekintés a weboldalon</string>
<string name="sort">Rendezés</string>
<string name="faq_description">Ha problémája van az alkalmazás használatával, akkor nézze meg az ezekre a gyakori kérdésekre adott válaszokat.</string>
<string name="faq_description">Ha problémája van az alkalmazás használatával, akkor nézze meg az ezekre a gyakori kérdésekre adott válaszokat!</string>
<string name="feed_toggle_hide_played_items">Megnézett elemek elrejtése</string>
<string name="fast_mode">Gyors mód</string>
<string name="import_subscriptions_hint">Feliratkozások importálása vagy exportálása a 3 pontos menüből</string>
<string name="app_update_unavailable_toast">Ön a Newpipe legfrissebb verzióját futtatja</string>
<string name="app_update_available_notification_text">Nyomjon a %s letöltéséhez</string>
</resources>

View File

@ -721,4 +721,9 @@
<string name="faq_title">Veelgestelde vragen</string>
<string name="faq_description">Als u problemen ondervindt bij het gebruik van de app, bekijk dan deze antwoorden op veelgestelde vragen!</string>
<string name="faq">Bekijk op de website</string>
<string name="sort">Sorteer</string>
<string name="fast_mode">Snelle modus</string>
<string name="import_subscriptions_hint">Importeer of exporteer abonnementen vanuit het 3-punten menu</string>
<string name="app_update_unavailable_toast">U heeft de laatste versie van NewPipe</string>
<string name="app_update_available_notification_text">Klik om %s te downloaden</string>
</resources>

View File

@ -16,7 +16,7 @@
<string name="did_you_mean">ਕੀ ਤੁਹਾਡਾ ਮਤਲਬ ਸੀ \"%1$s\"\?</string>
<string name="share_dialog_title">ਇਸ ਨਾਲ਼ ਸਾਂਝਾ ਕਰੋ</string>
<string name="use_external_video_player_title">ਬਾਹਰੀ ਵੀਡੀਓ ਪਲੇਅਰ ਵਰਤੋ</string>
<string name="use_external_video_player_summary">ਕੁਝ ਰੈਜ਼ੋਲਸ਼ਨਾਂ \'ਤੇ ਆਵਾਜ਼ ਨੂੰ ਹਟਾ ਦਿੰਦਾ ਹੈ</string>
<string name="use_external_video_player_summary">ਕੁਝ ਰੈਜ਼ੋਲਿਊਸ਼ਨਾਂ \'ਤੇ ਆਵਾਜ਼ ਨੂੰ ਹਟਾ ਦਿੰਦਾ ਹੈ</string>
<string name="use_external_audio_player_title">ਬਾਹਰੀ ਆਡੀਓ ਪਲੇਅਰ ਵਰਤੋ</string>
<string name="subscribe_button_title">ਸਬਸਕ੍ਰਾਈਬ ਕਰੋ</string>
<string name="subscribed_button_title">ਸਬਸਕ੍ਰਾਈਬ ਹੈ</string>
@ -36,9 +36,9 @@
<string name="download_path_audio_title">ਆਡੀਓ ਲਈ ਡਾਊਨਲੋਡ ਫ਼ੋਲਡਰ</string>
<string name="download_path_audio_summary">ਡਾਊਨਲੋਡ ਕੀਤੀਆਂ ਆਡੀਓ ਇੱਥੇ ਜਮ੍ਹਾਂ ਹੁੰਦੀਆਂ ਹਨ</string>
<string name="download_path_audio_dialog_title">ਆਡੀਓ ਫ਼ਾਈਲਾਂ ਲਈ ਡਾਊਨਲੋਡ ਫ਼ੋਲਡਰ ਚੁਣੋ</string>
<string name="default_resolution_title">ਡਿਫ਼ਾਲਟ ਰੈਜ਼ੋਲਸ਼ਨ</string>
<string name="default_popup_resolution_title">ਪੌਪ-ਅਪ ਲਈ ਡਿਫ਼ਾਲਟ ਰੈਜ਼ੋਲਸ਼ਨ</string>
<string name="show_higher_resolutions_title">ਵੱਡੀਆਂ ਰੈਜ਼ੋਲੂਸ਼ਨਾਂ ਦਿਖਾਓ</string>
<string name="default_resolution_title">ਡਿਫ਼ਾਲਟ ਰੈਜ਼ੋਲਿਊਸ਼ਨ</string>
<string name="default_popup_resolution_title">ਪੌਪ-ਅਪ ਲਈ ਡਿਫ਼ਾਲਟ ਰੈਜ਼ੋਲਿਊਸ਼ਨ</string>
<string name="show_higher_resolutions_title">ਵੱਡੀਆਂ ਰੈਜ਼ੋਲਿਊਸ਼ਨਜ਼ ਦਿਖਾਓ</string>
<string name="show_higher_resolutions_summary">ਸਿਰਫ਼ ਕੁਝ ਹੀ ਡਿਵਾਈਸ 2K/4K ਵੀਡੀਓ ਨੂੰ ਚਲਾ ਸਕਦੇ ਹਨ</string>
<string name="play_with_kodi_title">Kodi ਵਿੱਚ ਚਲਾਓ</string>
<string name="kore_not_found">Kodi ਐਪ ਇੰਸਟਾਲ ਨਹੀਂ ਹੈ\?</string>
@ -53,13 +53,13 @@
<string name="black_theme_title">ਕਾਲ੍ਹਾ</string>
<string name="popup_remember_size_pos_title">ਪੌਪ-ਅਪ ਦਾ ਆਕਾਰ ਅਤੇ ਸਥਿਤੀ ਯਾਦ ਰੱਖੋ</string>
<string name="popup_remember_size_pos_summary">ਪੌਪ-ਅਪ ਦਾ ਆਖਰੀ ਅਕਾਰ ਅਤੇ ਸਥਿਤੀ ਯਾਦ ਰੱਖੋ</string>
<string name="use_inexact_seek_title">ਤੇਜ਼ ਪਰ inexact seek ਵਰਤੋ</string>
<string name="use_inexact_seek_summary">Inexact seek ਵੀਡੀਓ ਨੂੰ ਤੇਜ਼ ਪਰ ਅਣ-ਸਟੀਕ ਢੰਗ ਨਾਲ ਅੱਗੇ-ਪਿੱਛੇ ਲਿਜਾਂਦਾ ਹੈ । ਇਸ ਨਾਲ ਅੱਗੇ-ਪਿੱਛੇ 5,15 ਜਾਂ 25 ਸਕਿੰਟ ਜਾਣਾ ਕੰਮ ਨਹੀਂ ਕਰੇਗਾ</string>
<string name="use_inexact_seek_title">ਤੇਜ਼ ਪਰ ਅਸਪੱਸ਼ਟ ਸੀਕ ਵਰਤੋ</string>
<string name="use_inexact_seek_summary">ਅਸਪੱਸ਼ਟ ਸੀਕ ਵੀਡੀਓ ਨੂੰ ਤੇਜ਼ ਪਰ ਅਣ-ਸਟੀਕ ਢੰਗ ਨਾਲ ਅੱਗੇ-ਪਿੱਛੇ ਲਿਜਾਂਦਾ ਹੈ । ਇਸ ਨਾਲ ਅੱਗੇ-ਪਿੱਛੇ 5,15 ਜਾਂ 25 ਸਕਿੰਟ ਜਾਣਾ ਕੰਮ ਨਹੀਂ ਕਰੇਗਾ</string>
<string name="download_thumbnail_title">ਥੰਮਨੇਲ ਲੋਡ ਕਰੋ</string>
<string name="download_thumbnail_summary">ਥੰਮਨੇਲ ਲੋਡ, ਡਾਟਾ ਦੀ ਬੱਚਤ ਅਤੇ ਮੈਮੋਰੀ ਦੀ ਵਰਤੋਂ ਨੂੰ ਰੋਕਣ ਲਈ ਇਸਨੂੰ ਬੰਦ ਕਰੋ। ਇਸ ਵਿਚ ਤਬਦੀਲੀ ਕਰਨ ਨਾਲ ਇਨ-ਮੈਮੋਰੀ ਅਤੇ ਆਨ-ਡਿਸਕ ਚਿੱਤਰ cache ਦੋਵੇਂ ਮਿਟ ਜਾਣਗੇ</string>
<string name="thumbnail_cache_wipe_complete_notice">ਚਿੱਤਰ cache ਮਿਟਾ ਦਿੱਤੀ ਗਈ ਹੈ</string>
<string name="metadata_cache_wipe_title">Cached ਮੈਟਾ-ਡਾਟਾ ਮਿਟਾਓ</string>
<string name="metadata_cache_wipe_summary">ਸਾਰੇ cached ਵੈੱਬ-ਪੇਜਾਂ ਦਾ ਡਾਟਾ ਮਿਟਾਓ</string>
<string name="metadata_cache_wipe_title">ਕੈਸ਼ ਕੀਤਾ ਮੈਟਾ-ਡਾਟਾ ਮਿਟਾਓ</string>
<string name="metadata_cache_wipe_summary">ਸਾਰੇ ਕੈਸ਼ ਕੀਤੇ ਵੈੱਬ-ਪੇਜਾਂ ਦਾ ਡਾਟਾ ਮਿਟਾਓ</string>
<string name="metadata_cache_wipe_complete_notice">ਮੈਟਾ-ਡਾਟਾ cache ਮਿਟਾ ਦਿੱਤੀ ਗਈ ਹੈ</string>
<string name="auto_queue_title">ਅਗਲੀ ਸਟ੍ਰੀਮ ਨੂੰ ਆਟੋ-ਕਤਾਰਬੱਧ ਕਰੋ</string>
<string name="auto_queue_summary">ਇੱਕ ਮੁੱਕਣ ਵਾਲੀ ਪਰ ਨਾ-ਦੁਹਰਾਉਣ ਵਾਲੀ ਕਤਾਰ ਨੂੰ, ਸੰਬੰਧਤ ਸਟ੍ਰੀਮ ਜੋੜਦਿਆਂ, ਚਲਾਉਂਦੇ ਜਾਓ</string>
@ -94,7 +94,7 @@
<string name="all">ਸਾਰੇ</string>
<string name="disabled">ਬੰਦ ਕੀਤਾ</string>
<string name="clear">ਮਿਟਾਓ</string>
<string name="best_resolution">ਵਧੀਆ ਰੈਜ਼ੋਲਸ਼ਨ</string>
<string name="best_resolution">ਵਧੀਆ ਰੈਜ਼ੋਲਿਊਸ਼ਨ</string>
<string name="undo">ਵਾਪਿਸ</string>
<string name="play_all">ਸਾਰੇ ਚਲਾਓ</string>
<string name="always">ਹਮੇਸ਼ਾ</string>
@ -110,7 +110,7 @@
<string name="export_data_title">ਡਾਟਾਬੇਸ ਨਿਰਯਾਤ ਕਰੋ</string>
<string name="import_data_summary">ਤੁਹਾਡੇ ਮੌਜੂਦਾ ਇਤਿਹਾਸ, ਸਬਸਕ੍ਰਿਪਸ਼ਨਜ਼, ਪਲੇਸੂਚੀ ਅਤੇ (ਆਪਨਸ਼ਨਲੀ) ਸੈਟਿੰਗਾਂ ਨੂੰ ਨਵਿਆਂ ਨਾਲ਼ ਬਦਲ ਦਿੰਦਾ ਹੈ</string>
<string name="export_data_summary">ਇਤਿਹਾਸ, ਸੁਬਸਕ੍ਰਿਪਸ਼ਨਜ਼, ਪਲੇ-ਸੂਚੀ ਅਤੇ ਸੈਟਿੰਗਾਂ ਦਰਾਮਦ ਕਰੋ</string>
<string name="clear_views_history_title">ੇਖੇ ਗਏ ਵੀਡੀਓਜ਼ ਦੀ ਸੂਚੀ ਮਿਟਾਓ</string>
<string name="clear_views_history_title">ੇਖੇ ਗਏ ਵੀਡੀਓਜ਼ ਦੀ ਸੂਚੀ ਮਿਟਾਓ</string>
<string name="clear_views_history_summary">ਚਲਾਏ ਗਏ ਵੀਡੀਓਜ਼ ਦੇ ਇਤਿਹਾਸ ਅਤੇ ਪਲੇ-ਸਥਿਤੀਆਂ ਨੂੰ ਮਿਟਾਉਂਦਾ ਹੈ</string>
<string name="delete_view_history_alert">ਕੀ ਵੇਖੇ ਗਏ ਵੀਡੀਓਜ਼ ਦਾ ਇਤਿਹਾਸ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇ\?</string>
<string name="clear_search_history_title">ਖੋਜ ਸੂਚੀ ਦਾ ਇਤਿਹਾਸ ਮਿਟਾਓ</string>
@ -318,7 +318,7 @@
<string name="accept">ਸਵੀਕਾਰ ਕਰੋ</string>
<string name="decline">ਅਸਵੀਕਾਰ</string>
<string name="limit_data_usage_none_description">ਕੋਈ ਸੀਮਾ ਨਹੀਂ</string>
<string name="limit_mobile_data_usage_title">ਮੋਬਾਈਲ ਡਾਟਾ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਸਮੇਂ ਰੈਜ਼ੋਲੂਸ਼ਨ ਨੂੰ ਸੀਮਿਤ ਕਰੋ</string>
<string name="limit_mobile_data_usage_title">ਮੋਬਾਈਲ ਡਾਟਾ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਸਮੇਂ ਰੈਜ਼ੋਲਿਊਸ਼ਨ ਨੂੰ ਸੀਮਿਤ ਕਰੋ</string>
<string name="minimize_on_exit_title">ਐਪ ਸਵਿੱਚ ਕਰਨ ਤੇ ਮਿਨੀਮਾਈਜ਼ ਕਰੋ</string>
<string name="minimize_on_exit_summary">ਮੁੱਖ ਵੀਡੀਓ ਪਲੇਅਰ ਤੋਂ ਦੂਜੇ ਐਪ \'ਤੇ ਜਾਣ ਵੇਲ਼ੇ ਕਾਰਵਾਈ — %s</string>
<string name="minimize_on_exit_none_description">ਕੋਈ ਨਹੀਂ</string>
@ -327,7 +327,7 @@
<string name="skip_silence_checkbox">ਚੁੱਪ ਦੌਰਾਨ ਤੇਜ਼ੀ ਨਾਲ ਅੱਗੇ ਕਰੋ</string>
<string name="playback_step">ਕਦਮ</string>
<string name="playback_reset">ਰੀਸੈੱਟ</string>
<string name="channels">ਚੈਨਲਾਂ</string>
<string name="channels">ਚੈਨਲ</string>
<string name="playlists">ਪਲੇ ਸੂਚੀਆਂ</string>
<string name="tracks">ਟਰੈਕਸ</string>
<string name="users">ਯੂਜ਼ਰਸ</string>
@ -575,11 +575,11 @@
<string name="delete_playback_states_alert">ਸਾਰੀਆਂ ਪਲੇ-ਸਥਿਤੀਆਂ ਮਿਟਾਉਣੀਆਂ ਹਨ\?</string>
<string name="clear_playback_states_summary">ਸਾਰੀਆਂ ਪਲੇ-ਸਥਿਤੀਆਂ ਮਿਟਾਉਂਦਾ ਹੈ</string>
<string name="clear_playback_states_title">ਪਲੇ-ਸਥਿਤੀਆਂ ਮਿਟਾਓ</string>
<string name="hash_channel_name">ਵੀਡੀ ਹੈਸ਼ ਇਤਲਾਹ</string>
<string name="hash_channel_name">ਵੀਡੀ ਹੈਸ਼ ਇਤਲਾਹ</string>
<string name="albums">ਐਲਬਮਾਂ</string>
<string name="artists">ਕਲਾਕਾਰ</string>
<string name="songs">ਗੀਤ</string>
<string name="videos_string">ਿਡੀਉ</string>
<string name="videos_string">ੀਡੀਓ</string>
<string name="restricted_video">ਇਹ ਵੀਡੀਓ ਉਮਰ-ਪਾਬੰਦੀਸ਼ੁਦਾ ਹੈ।
\n
\nਜੇ ਤੁਸੀਂ ਇਸਨੂੰ ਵੇਖਣਾ ਚਾਹੁੰਦੇ ਹੋ ਤਾਂ ਸੈਟਿੰਗਾਂ ਵਿੱਚੋਂ \"%1$s\" ਚਾਲੂ ਕਰੋ।</string>
@ -598,7 +598,7 @@
<string name="auto_queue_toggle">ਆਪ-ਮੁਖ਼ਤਾਰ ਕਤਾਰ ਕਰੋ</string>
<string name="show_meta_info_summary">ਸਟ੍ਰੀਮ ਦੇ ਕਰਤਾ, ਸਮੱਗਰੀ ਜਾਂ ਖੋਜ ਬੇਨਤੀ ਵਾਲੇ ਵਾਧੂ ਜਾਣਕਾਰੀ ਬਕਸਿਆਂ ਵਾਲ਼ੀ ਮੈਟਾ ਜਾਣਕਾਰੀ ਲੁਕਾਉਣ ਲਈ ਇਸਨੂੰ ਬੰਦ ਕਰ ਦਿਓ</string>
<string name="show_meta_info_title">ਮੈਟਾ ਜਾਣਕਾਰੀ ਦਿਖਾਓ</string>
<string name="show_description_summary">ਵੀਡੀ ਵੇਰਵਾ ਅਤੇ ਵਾਧੂ ਜਾਣਕਾਰੀ ਲੁਕਾਉਣ ਲਈ ਇਸਨੂੰ ਬੰਦ ਕਰੋ</string>
<string name="show_description_summary">ਵੀਡੀ ਵੇਰਵਾ ਅਤੇ ਵਾਧੂ ਜਾਣਕਾਰੀ ਲੁਕਾਉਣ ਲਈ ਇਸਨੂੰ ਬੰਦ ਕਰੋ</string>
<string name="show_description_title">ਵੇਰਵਾ ਦਿਖਾਓ</string>
<string name="clear_queue_confirmation_description">ਸਰਗਰਮ ਪਲੇਅਰ ਕਤਾਰ ਬਦਲ ਜਾਵੇਗੀ</string>
<string name="clear_queue_confirmation_summary">ਪਲੇਅਰ ਬਦਲਣ ਨਾਲ ਤੁਹਾਡੀ ਕਤਾਰ ਬਦਲ ਸਕਦੀ ਹੈ</string>

View File

@ -493,7 +493,7 @@
<string name="content_not_available">Conteúdo indisponível</string>
<string name="subscribed_button_title">Subscrito</string>
<string name="thumbnail_cache_wipe_complete_notice">Cache de imagens limpa</string>
<string name="tab_about">Acerca</string>
<string name="tab_about">Sobre e FAQ</string>
<string name="subscribers_count_not_available">Contagem de subscrições indisponível</string>
<string name="preferred_open_action_settings_summary">Ação padrão ao abrir o conteúdo — %s</string>
<string name="playback_reset">Repor</string>
@ -716,9 +716,14 @@
<string name="select_quality_external_players">Selecione a qualidade para reprodutores externos</string>
<string name="progressive_load_interval_title">Tamanho do intervalo de carregamento da reprodução</string>
<string name="feed_toggle_show_future_items">Mostrar artigos futuros</string>
<string name="feed_toggle_hide_played_items">Ocultar artigos vistos</string>
<string name="feed_toggle_hide_played_items">Ocultar itens reproduzidos</string>
<string name="feed_toggle_hide_future_items">Ocultar artigos futuros</string>
<string name="faq_title">Perguntas frequentes</string>
<string name="faq_description">Se tem problemas a usar a app, veja estas respostas para perguntas frequentes!</string>
<string name="faq">Ver no sítio web</string>
<string name="fast_mode">Modo rápido</string>
<string name="import_subscriptions_hint">Importar ou exportar subscrições do menu de 3 pontos</string>
<string name="app_update_unavailable_toast">Já está a executar a versão mais recente do NewPipe</string>
<string name="app_update_available_notification_text">Toque para descarregar %s</string>
<string name="sort">Ordenação</string>
</resources>

View File

@ -735,4 +735,8 @@
<string name="faq_description">Dacă întâmpinați probleme cu utilizarea aplicației, nu uitați să consultați aceste răspunsuri la întrebări frecvente!</string>
<string name="faq_title">Întrebări puse frecvent</string>
<string name="sort">Sortează</string>
<string name="fast_mode">Modul rapid</string>
<string name="import_subscriptions_hint">Importați sau exportați abonamente din meniul cu 3 puncte</string>
<string name="app_update_unavailable_toast">Rulați cea mai recentă versiune NewPipe</string>
<string name="app_update_available_notification_text">Atingeți pentru a descărca %s</string>
</resources>

View File

@ -716,7 +716,7 @@
<string name="detail_pinned_comment_view_description">Закреплённый комментарий</string>
<string name="leak_canary_not_available">LeakCanary недоступна</string>
<string name="progressive_load_interval_exoplayer_default">Стандартное значение ExoPlayer</string>
<string name="progressive_load_interval_summary">Изменить размер предварительной загрузки (сейчас %s). Меньшее значение может ускорить загрузку видео. При изменении требуется перезапуск плеера</string>
<string name="progressive_load_interval_summary">Изменить интервал загрузки (сейчас %s). Меньшее значение может ускорить запуск видео. Нужен перезапуск плеера</string>
<string name="loading_stream_details">Загрузка сведений о трансляции…</string>
<string name="check_new_streams">Проверить наличие новых трансляций</string>
<string name="delete_downloaded_files_confirm">Удалить все загруженные файлы\?</string>

View File

@ -373,4 +373,5 @@
<string name="streams_notification_channel_description">சந்தாவுக்கான புதிய ஸ்ட்ரீம்கள் பற்றிய அறிவிப்புகள்</string>
<string name="restricted_video_no_stream">இந்த வீடியோ வயது வரம்புக்குட்பட்டது.
\nவயது வரம்புக்குட்பட்ட வீடியோக்கள் கொண்ட புதிய YouTube கொள்கைகள் காரணமாக, NewPipe ஆல் அதன் எந்த வீடியோ ஸ்ட்ரீம்களையும் அணுக முடியாது, இதனால் அதை இயக்க முடியவில்லை.</string>
<string name="fast_mode">வேகமான பயன்முறை</string>
</resources>

View File

@ -449,4 +449,26 @@
<string name="playback_step">అడుగు</string>
<string name="skip_silence_checkbox">నిశ్శబ్ద సమయంలో వేగంగా ముందుకు వెళ్లుము</string>
<string name="playback_speed_control">ప్లేబ్యాక్ స్పీడ్ నియంత్రణలు</string>
<string name="minimize_on_exit_none_description">ఏమిలేదు</string>
<string name="disable_media_tunneling_summary">మీరు బ్లాక్ స్క్రీన్ లేదా చలనచిత్రం ప్లేబ్యాక్‌లో అంతరాయాన్ని అనుభవిస్తే మీడియా టన్నెలింగ్‌ను నిలిపివేయండి</string>
<string name="show_image_indicators_summary">చిత్రాల మూలాన్ని సూచించే విధంగా వాటి పైభాగంలో పికాసో రంగు రిబ్బన్‌లను చూపండి: నెట్‌వర్క్ కోసం ఎరుపు, డిస్క్ కోసం నీలం మరియు మెమరీ కోసం ఆకుపచ్చ</string>
<string name="show_error_snackbar">లోపం స్నాక్‌బార్‌ని చూపండి</string>
<string name="app_update_unavailable_toast">మీరు NewPipe యొక్క తాజా సంస్కరణను అమలు చేస్తున్నారు</string>
<string name="app_update_available_notification_title">NewPipe నవీకరణ అందుబాటులో ఉంది!</string>
<string name="missions_header_finished">పూర్తయింది</string>
<string name="missions_header_pending">వేలాడుతున్న</string>
<string name="show_original_time_ago_summary">సర్వీస్‌ల నుండి ఒరిజినల్ టెక్స్ట్‌లు స్ట్రీమ్ ఐటెమ్‌లలో కనిపిస్తాయి</string>
<string name="show_crash_the_player_title">\"ప్లేయర్ పతనం\" చూపించు</string>
<string name="show_crash_the_player_summary">ప్లేయర్‌ని ఉపయోగిస్తున్నప్పుడు పతనం ఎంపికను చూపుము</string>
<string name="crash_the_app">యాప్‌ను పతనం చేయండి</string>
<string name="low_quality_smaller">తక్కువ నాణ్యత (చిన్నది)</string>
<string name="dont_show">చూపించవద్దు</string>
<string name="disable_media_tunneling_title">మీడియా టన్నెలింగ్‌ని నిలిపివేయండి</string>
<string name="show_image_indicators_title">చిత్ర సూచికలను చూపు</string>
<string name="check_new_streams">కొత్త స్ట్రీమ్‌ల కోసం తనిఖీని అమలు చేయండి</string>
<string name="create_error_notification">ఎర్రర్ నోటిఫికేషన్‌ను సృష్టించండి</string>
<string name="import_title">దిగుమతి</string>
<string name="paused">ఆగిపోయింది</string>
<string name="sort">క్రమం</string>
<string name="app_update_available_notification_text">%sని డౌన్‌లోడ్ చేయడానికి నొక్కండి</string>
</resources>

View File

@ -321,7 +321,7 @@
<string name="import_settings">Імпортувати разом з налаштуваннями\?</string>
<string name="privacy_policy_title">Політика приватності NewPipe</string>
<string name="privacy_policy_encouragement">Проєкт NewPipe дуже серйозно ставиться до вашої приватності. Тому застосунок не збирає ніяких даних без вашої згоди.
\nПолітика приватності докладно NewPipe пояснює, які дані надсилаються і зберігаються у звіті про збій програми.</string>
\nПолітика приватності докладно NewPipe пояснює, які дані надсилаються і зберігаються у звіті про збій.</string>
<string name="read_privacy_policy">Читати політику приватності</string>
<string name="start_accept_privacy_policy">З метою дотримання Загального регламенту про захист даних ЄС (General Data Protection Regulation, GDPR) ми звертаємо вашу увагу на політику приватності NewPipe. Будь ласка, прочитайте уважно.
\nВи маєте прийняти її, аби надіслати нам звіт про помилку.</string>
@ -578,7 +578,7 @@
<string name="related_items_tab_description">Повʼязані елементи</string>
<string name="comments_tab_description">Коментарі</string>
<string name="settings_category_player_notification_summary">Налаштувати повідомлення про відтворюваний наразі потік</string>
<string name="unsupported_url_dialog_message">Не розпізнано URL. Відкрити через іншу програму\?</string>
<string name="unsupported_url_dialog_message">Не розпізнано URL. Відкрити через інший застосунок\?</string>
<string name="auto_queue_toggle">Автоматична черга</string>
<string name="show_meta_info_title">Показувати метадані</string>
<string name="show_description_title">Показувати описи</string>

View File

@ -498,4 +498,14 @@
<string name="open_with">کے ساتھ کھولیں</string>
<string name="crash_the_player">ویڈیو پلیئر کو کریش کریں</string>
<string name="mark_as_watched">دیکھے ہوئے کو نشان لگائیں</string>
<string name="local_search_suggestions">مقامی تلاش کی سفارشات</string>
<string name="notifications">اطلاعات</string>
<string name="start_main_player_fullscreen_title">مین پلیئر کو مکمل سکرین سے شروع کریں</string>
<string name="error_report_channel_name">غلطی کی دستاویزات کی اطلاع</string>
<string name="error_report_channel_description">غلطی کی حبر کی اطلاعات</string>
<string name="subtitle_activity_recaptcha">جب ٹھیک ہو جائے تو \"Done\" دبائیں</string>
<string name="recaptcha_solve">حل کریں</string>
<string name="faq_title">زیادہ تر پوچھے گئے سوالات</string>
<string name="faq_description">اگر آپ کو یہ ایپ استعمال کرنے میں دشواری آ رہی ہو تو ان عام سوالات کے جوابات کو ضرور دیکھیں!</string>
<string name="faq">ویب سائٹ پر دیکھیں</string>
</resources>

View File

@ -709,4 +709,8 @@
<string name="sort">排序</string>
<string name="faq_title">常見問題</string>
<string name="faq_description">若然您用呢個 app 有疑問,然而「亦有些難啟齒」,不妨睇下常見問題集,話唔定會發現「有場舞還未發表」!</string>
<string name="fast_mode">快速模式</string>
<string name="import_subscriptions_hint">右上角嘅選單有得匯入或匯出訂閱</string>
<string name="app_update_unavailable_toast">您已經用緊最新版本嘅 NewPipe</string>
<string name="app_update_available_notification_text">撳一下去下載 %s</string>
</resources>

View File

@ -441,6 +441,7 @@
<item>hu</item>
<item>nl</item>
<item>no</item>
<item>nn</item>
<item>uz</item>
<item>pl</item>
<item>pt-PT</item>
@ -519,6 +520,7 @@
<item>Magyar</item>
<item>Nederlands</item>
<item>Norsk</item>
<item>Nynorsk</item>
<item>Ozbek</item>
<item>Polski</item>
<item>Português</item>

View File

@ -716,6 +716,7 @@
<string name="auto_device_theme_title">Automatic (device theme)</string>
<string name="night_theme_summary">Select your favorite night theme — %s</string>
<string name="select_night_theme_toast">You can select your favorite night theme below</string>
<string name="night_theme_available">This option is only available if %s is selected for Theme</string>
<string name="download_has_started">Download has started</string>
<string name="description_select_note">You can now select text inside the description. Note that the page may flicker and links may not be clickable while in selection mode.</string>
<string name="description_select_enable">Enable selecting text in the description</string>

View File

@ -7,7 +7,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.3.0'
classpath 'com.android.tools.build:gradle:7.3.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong

View File

@ -0,0 +1,23 @@
<h4>Améliorations</h4>
<ul>
<li>Rendre les liens dans les commentaires cliquables, augmenter la taille du texte</li>
<li>Rechercher en cliquant sur les liens d'horodatage dans les commentaires</li>
<li>Afficher l'onglet préféré en fonction de l'état récemment sélectionné</li>
<li>Ajouter la liste de lecture à la file d'attente lors d'un clic long sur &#39;Arrière-plan&#39; dans la fenêtre de la liste de lecture</li>
<li>Rechercher le texte partagé lorsqu'il ne s'agit pas d'une URL</li>
<li>Ajouter &quot;partager à l'heure actuelle&quot; bouton au lecteur vidéo principal lecteur vidéo principal</li>
<li>Ajouter un bouton de fermeture du lecteur principal lorsque la file d'attente vidéo est terminée</li>
<li>Ajouter &quot;jouer directement en arrière-plan&quot; au menu longpress pour les éléments de la liste vidéo</li>
<li>Améliorer les traductions en anglais des commandes Play/Enqueue</li>
<li>Petites améliorations des performances</li>
<li>Supprimer les fichiers inutilisés</li>
<li>Mise à jour ExoPlayer à 2.9.6</li>
<li>Ajouter le support pour les liens Invidious</li>
</ul>
<h4>Corrections</h4>
<ul>
<li>Défilement avec les commentaires et les flux associés désactivés</li>
<li>CheckForNewAppVersionTask qui est exécuté alors qu'il ne devrait pas l'être&#39;</li>
<li> Importation des abonnements YouTube : ignorer ceux dont lURL est invalide et conserver ceux dont le titre est vide</li>
<li>URL YouTube invalide : le nom de la balise signature n'est pas toujours "signature", ce qui empêche le chargement des flux.</li>
</ul>

View File

@ -0,0 +1,13 @@
Nouveautés
• Ajout du bouton « Ouvrir dans un navigateur » dans le paneau d'erreur
• Ajout de la possibilité d'afficher les groupes de chaîne en liste
• [YouTube] Appuis long sur le segment d'un flux pour partager l'URL avec l'horodatage
• Ajout d'un bouton sur le lecteur reduit
Améliorations
• Ajout de la traduction en islandais et mise à jour de d'autre langues
• De nombreuses améliorations internes
Corrections
• Correction de plantages
• [YouTube] Correction du chargement des chaînes

View File

@ -1,4 +1,4 @@
<li><h4>Miglioramenti</h4>
<h4>Miglioramenti</h4>
<ul>
<li>rendi cliccabili i link nei commenti, aumenta la dimensione del testo</li>
<li>cerca facendo clic sui collegamenti timestamp nei commenti</li>

View File

@ -0,0 +1,26 @@
### మెరుగుదలలు
- బర్గర్‌మెను ఐకాన్ యానిమేషన్ #1486ని నిలిపివేయండి
- డౌన్‌లోడ్‌ల తొలగింపును రద్దు చేయండి #1472
- షేర్ మెను #1498లో డౌన్‌లోడ్ ఎంపిక
- లాంగ్ ట్యాప్ మెనూ #1454కి షేర్ ఆప్షన్ జోడించబడింది
- నిష్క్రమణ #1354లో ప్రధాన ప్లేయర్‌ని తగ్గించండి
- లైబ్రరీ వెర్షన్ అప్‌డేట్ మరియు డేటాబేస్ బ్యాకప్ ఫిక్స్ #1510
- ExoPlayer 2.8.2 నవీకరణ #1392
- వేగవంతమైన స్పీడ్ మార్పు కోసం వివిధ దశల పరిమాణాలకు మద్దతు ఇవ్వడానికి ప్లేబ్యాక్ స్పీడ్ కంట్రోల్ డైలాగ్‌ని మళ్లీ రూపొందించారు.
- ప్లేబ్యాక్ స్పీడ్ కంట్రోల్‌లో నిశ్శబ్దం సమయంలో ఫాస్ట్-ఫార్వర్డ్ చేయడానికి టోగుల్ జోడించబడింది. ఇది ఆడియోబుక్‌లు మరియు నిర్దిష్ట సంగీత శైలులకు సహాయకరంగా ఉండాలి మరియు నిజమైన అతుకులు లేని అనుభవాన్ని అందించగలదు (మరియు అనేక నిశ్శబ్దాలతో పాటను విచ్ఛిన్నం చేయవచ్చు =\\).
- మాన్యువల్‌గా కాకుండా ప్లేయర్‌లో అంతర్గతంగా మీడియాతో పాటు మెటాడేటాను పాస్ చేయడానికి రీఫ్యాక్టర్డ్ మీడియా సోర్స్ రిజల్యూషన్. ఇప్పుడు మేము మెటాడేటా యొక్క ఒకే మూలాన్ని కలిగి ఉన్నాము మరియు ప్లేబ్యాక్ ప్రారంభమైనప్పుడు నేరుగా అందుబాటులో ఉంటుంది.
- ప్లేజాబితా భాగాన్ని తెరిచినప్పుడు కొత్త మెటాడేటా అందుబాటులో ఉన్నప్పుడు స్థిర రిమోట్ ప్లేజాబితా మెటాడేటా నవీకరించబడదు.
- వివిధ UI పరిష్కారాలు: #1383, బ్యాక్‌గ్రౌండ్ ప్లేయర్ నోటిఫికేషన్ నియంత్రణలు ఇప్పుడు ఎల్లప్పుడూ తెల్లగా ఉంటాయి, ఫ్లింగ్ ద్వారా పాప్‌అప్ ప్లేయర్‌ని షట్‌డౌన్ చేయడం సులభం
- మల్టీసర్వీస్ కోసం రీఫ్యాక్టర్డ్ ఆర్కిటెక్చర్‌తో కొత్త ఎక్స్‌ట్రాక్టర్‌ని ఉపయోగించండి
### పరిష్కారాలు
- #1440 బ్రోకెన్ వీడియో ఇన్ఫో లేఅవుట్ #1491ని పరిష్కరించండి
- చరిత్ర పరిష్కారాన్ని వీక్షించండి #1497
- #1495, యూజర్ ప్లేజాబితాను యాక్సెస్ చేసిన వెంటనే మెటాడేటా (థంబ్‌నెయిల్, టైటిల్ మరియు వీడియో కౌంట్) అప్‌డేట్ చేయడం ద్వారా.
- #1475, వినియోగదారు వివరాలు ఫ్రాగ్‌మెంట్‌పై బాహ్య ప్లేయర్‌లో వీడియోను ప్రారంభించినప్పుడు డేటాబేస్‌లో వీక్షణను నమోదు చేయడం ద్వారా.
- పాప్అప్ మోడ్ విషయంలో స్క్రీన్ సమయం ముగియడాన్ని పరిష్కరించండి. #1463 (స్థిర #640)
- ప్రధాన వీడియో ప్లేయర్ ఫిక్స్ #1509
- [#1412] ప్లేయర్ యాక్టివిటీ బ్యాక్‌గ్రౌండ్‌లో ఉన్నప్పుడు కొత్త ఉద్దేశం వచ్చినప్పుడు ప్లేయర్ NPEకి కారణమయ్యే ఫిక్స్డ్ రిపీట్ మోడ్.
- పాప్‌అప్‌కి ప్లేయర్‌ని కనిష్టీకరించడం అనేది పాప్‌అప్ అనుమతి ఇవ్వనప్పుడు ప్లేయర్‌ను నాశనం చేయదు.

View File

@ -5,7 +5,7 @@
•Швид.перемот.вперед/назад у фоні/вікні програв.черги
•Показ порад пошуку: мали на увазі й показ результ. для
Покр.
•Вил.запис метадан.програми в зміш.файли
•Вил.запис метадан.застосунку в зміш.файли
•Не вилуч.невдалі потоки з черги
•Оновл.колір пан.стану відповідно до коль.пан.засобів
Випр.