diff --git a/README.md b/README.md index f78725338..987327ab8 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@


ScreenshotsDescriptionFeaturesUpdatesContributionDonateLicense

-

WebsiteBlogPress

+

WebsiteBlogFAQPress


WARNING: THIS IS A BETA VERSION, THEREFORE YOU MAY ENCOUNTER BUGS. IF YOU DO, OPEN AN ISSUE VIA OUR GITHUB REPOSITORY. diff --git a/app/build.gradle b/app/build.gradle index f7017a6df..0ca03f158 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ android { applicationId "org.schabi.newpipe" minSdkVersion 19 targetSdkVersion 28 - versionCode 800 - versionName "0.18.0" + versionCode 820 + versionName "0.18.2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true @@ -62,7 +62,7 @@ dependencies { exclude module: 'support-annotations' }) - implementation 'com.github.TeamNewPipe:NewPipeExtractor:8e53fda' + implementation 'com.github.TeamNewPipe:NewPipeExtractor:ff61e284' testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-core:2.23.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3284202fd..38c0c4ca8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -157,6 +157,7 @@ + diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 78cb9284a..a2f161847 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -458,6 +458,16 @@ public class MainActivity extends AppCompatActivity { sharedPreferences.edit().putBoolean(Constants.KEY_MAIN_PAGE_CHANGE, false).apply(); NavigationHelper.openMainActivity(this); } + + if (sharedPreferences.getBoolean(Constants.KEY_ENABLE_WATCH_HISTORY, true)) { + if (DEBUG) Log.d(TAG, "do not show History-menu as its disabled in settings"); + drawerItems.getMenu().findItem(ITEM_ID_HISTORY).setVisible(true); + } + + if (!sharedPreferences.getBoolean(Constants.KEY_ENABLE_WATCH_HISTORY, true)) { + if (DEBUG) Log.d(TAG, "show History-menu as its enabled in settings"); + drawerItems.getMenu().findItem(ITEM_ID_HISTORY).setVisible(false); + } } @Override @@ -567,8 +577,6 @@ public class MainActivity extends AppCompatActivity { if (!(fragment instanceof SearchFragment)) { findViewById(R.id.toolbar).findViewById(R.id.toolbar_search_container).setVisibility(View.GONE); - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.main_menu, menu); } ActionBar actionBar = getSupportActionBar(); @@ -590,14 +598,6 @@ public class MainActivity extends AppCompatActivity { case android.R.id.home: onHomeButtonPressed(); return true; - case R.id.action_show_downloads: - return NavigationHelper.openDownloads(this); - case R.id.action_history: - NavigationHelper.openStatisticFragment(getSupportFragmentManager()); - return true; - case R.id.action_settings: - NavigationHelper.openSettings(this); - return true; default: return super.onOptionsItemSelected(item); } diff --git a/app/src/main/java/org/schabi/newpipe/about/AboutActivity.java b/app/src/main/java/org/schabi/newpipe/about/AboutActivity.java index 2326e795e..e028c0322 100644 --- a/app/src/main/java/org/schabi/newpipe/about/AboutActivity.java +++ b/app/src/main/java/org/schabi/newpipe/about/AboutActivity.java @@ -99,11 +99,6 @@ public class AboutActivity extends AppCompatActivity { case android.R.id.home: finish(); return true; - case R.id.action_settings: - NavigationHelper.openSettings(this); - return true; - case R.id.action_show_downloads: - return NavigationHelper.openDownloads(this); } return super.onOptionsItemSelected(item); diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java b/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java index 56265d321..6ceacbb05 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java @@ -84,11 +84,7 @@ public class DownloadActivity extends AppCompatActivity { onBackPressed(); return true; } - case R.id.action_settings: { - Intent intent = new Intent(this, SettingsActivity.class); - startActivity(intent); - return true; - } + default: return super.onOptionsItemSelected(item); } diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java index 4fbf4ab5f..44966744b 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java @@ -559,8 +559,16 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck case R.id.audio_button: mainStorage = mainStorageAudio; format = audioStreamsAdapter.getItem(selectedAudioIndex).getFormat(); - mime = format.mimeType; - filename += format.suffix; + switch(format) { + case WEBMA_OPUS: + mime = "audio/ogg"; + filename += "opus"; + break; + default: + mime = format.mimeType; + filename += format.suffix; + break; + } break; case R.id.video_button: mainStorage = mainStorageVideo; @@ -824,7 +832,6 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck psArgs = new String[]{ selectedStream.getFormat().getSuffix(), "false",// ignore empty frames - "false",// detect youtube duplicate lines }; } break; diff --git a/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java index 720e0f216..88a4c9c63 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java @@ -30,6 +30,7 @@ import org.schabi.newpipe.settings.tabs.Tab; import org.schabi.newpipe.settings.tabs.TabsManager; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.ServiceHelper; +import org.schabi.newpipe.views.ScrollableTabLayout; import java.util.ArrayList; import java.util.List; @@ -37,7 +38,7 @@ import java.util.List; public class MainFragment extends BaseFragment implements TabLayout.OnTabSelectedListener { private ViewPager viewPager; private SelectedTabsPagerAdapter pagerAdapter; - private TabLayout tabLayout; + private ScrollableTabLayout tabLayout; private List tabsList = new ArrayList<>(); private TabsManager tabsManager; diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index c698d4ad4..1fb44a813 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -79,6 +79,7 @@ import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.ImageDisplayConstants; import org.schabi.newpipe.util.InfoCache; +import org.schabi.newpipe.util.KoreUtil; import org.schabi.newpipe.util.ListHelper; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.NavigationHelper; @@ -627,7 +628,7 @@ public class VideoDetailFragment url.replace("https", "http"))); } catch (Exception e) { if (DEBUG) Log.i(TAG, "Failed to start kore", e); - showInstallKoreDialog(activity); + KoreUtil.showInstallKoreDialog(activity); } return true; default: @@ -635,16 +636,6 @@ public class VideoDetailFragment } } - private static void showInstallKoreDialog(final Context context) { - final AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setMessage(R.string.kore_not_found) - .setPositiveButton(R.string.install, (DialogInterface dialog, int which) -> - NavigationHelper.installKore(context)) - .setNegativeButton(R.string.cancel, (DialogInterface dialog, int which) -> { - }); - builder.create().show(); - } - private void setupActionBarOnError(final String url) { if (DEBUG) Log.d(TAG, "setupActionBarHandlerOnError() called with: url = [" + url + "]"); Log.e("-----", "missing code"); diff --git a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistAppendDialog.java b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistAppendDialog.java index ac02b0b37..81058eee6 100644 --- a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistAppendDialog.java +++ b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistAppendDialog.java @@ -1,15 +1,16 @@ package org.schabi.newpipe.local.dialog; import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import org.schabi.newpipe.NewPipeDatabase; import org.schabi.newpipe.R; import org.schabi.newpipe.database.LocalItem; @@ -152,6 +153,12 @@ public final class PlaylistAppendDialog extends PlaylistDialog { final Toast successToast = Toast.makeText(getContext(), R.string.playlist_add_stream_success, Toast.LENGTH_SHORT); + if (playlist.thumbnailUrl.equals("drawable://" + R.drawable.dummy_thumbnail_playlist)) { + playlistDisposables.add(manager.changePlaylistThumbnail(playlist.uid, streams.get(0).getThumbnailUrl()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(ignored -> successToast.show())); + } + playlistDisposables.add(manager.appendToPlaylist(playlist.uid, streams) .observeOn(AndroidSchedulers.mainThread()) .subscribe(ignored -> successToast.show())); diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index c60cdac3f..9f21e05ff 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -4,11 +4,6 @@ import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.os.Parcelable; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AlertDialog; -import androidx.recyclerview.widget.RecyclerView; -import androidx.recyclerview.widget.ItemTouchHelper; import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; @@ -18,6 +13,12 @@ import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.RecyclerView; + import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; import org.schabi.newpipe.NewPipeDatabase; @@ -413,10 +414,25 @@ public class LocalPlaylistFragment extends BaseLocalListFragment modifyPlaylist(final long playlistId, @Nullable final String name, @Nullable final String thumbnailUrl) { diff --git a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java index ab07ded22..76da7da36 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java @@ -25,12 +25,17 @@ import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.content.res.Resources; import android.graphics.Bitmap; import android.os.Build; import android.os.IBinder; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; import androidx.core.app.NotificationCompat; + +import android.preference.PreferenceManager; import android.util.Log; import android.view.View; import android.widget.RemoteViews; @@ -48,6 +53,7 @@ import org.schabi.newpipe.player.helper.LockManager; import org.schabi.newpipe.player.playqueue.PlayQueueItem; import org.schabi.newpipe.player.resolver.AudioPlaybackResolver; import org.schabi.newpipe.player.resolver.MediaSourceTag; +import org.schabi.newpipe.util.BitmapUtils; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.ThemeHelper; @@ -75,6 +81,7 @@ public final class BackgroundPlayer extends Service { private BasePlayerImpl basePlayerImpl; private LockManager lockManager; + private SharedPreferences sharedPreferences; /*////////////////////////////////////////////////////////////////////////// // Service-Activity Binder @@ -95,6 +102,9 @@ public final class BackgroundPlayer extends Service { private boolean shouldUpdateOnProgress; + private static final int NOTIFICATION_UPDATES_BEFORE_RESET = 60; + private int timesNotificationUpdated; + /*////////////////////////////////////////////////////////////////////////// // Service's LifeCycle //////////////////////////////////////////////////////////////////////////*/ @@ -104,6 +114,7 @@ public final class BackgroundPlayer extends Service { if (DEBUG) Log.d(TAG, "onCreate() called"); notificationManager = ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)); lockManager = new LockManager(this); + sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); ThemeHelper.setTheme(this); basePlayerImpl = new BasePlayerImpl(this); @@ -180,6 +191,7 @@ public final class BackgroundPlayer extends Service { private void resetNotification() { notBuilder = createNotification(); + timesNotificationUpdated = 0; } private NotificationCompat.Builder createNotification() { @@ -195,12 +207,45 @@ public final class BackgroundPlayer extends Service { .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setCustomContentView(notRemoteView) .setCustomBigContentView(bigNotRemoteView); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + setLockScreenThumbnail(builder); + } + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) { builder.setPriority(NotificationCompat.PRIORITY_MAX); } return builder; } + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private void setLockScreenThumbnail(NotificationCompat.Builder builder) { + boolean isLockScreenThumbnailEnabled = sharedPreferences.getBoolean( + getString(R.string.enable_lock_screen_video_thumbnail_key), + true + ); + + if (isLockScreenThumbnailEnabled) { + basePlayerImpl.mediaSessionManager.setLockScreenArt( + builder, + getCenteredThumbnailBitmap() + ); + } else { + basePlayerImpl.mediaSessionManager.clearLockScreenArt(builder); + } + } + + @Nullable + private Bitmap getCenteredThumbnailBitmap() { + int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels; + int screenHeight = Resources.getSystem().getDisplayMetrics().heightPixels; + + return BitmapUtils.centerCrop( + basePlayerImpl.getThumbnail(), + screenWidth, + screenHeight); + } + private void setupNotification(RemoteViews remoteViews) { if (basePlayerImpl == null) return; @@ -248,10 +293,13 @@ public final class BackgroundPlayer extends Service { //if (DEBUG) Log.d(TAG, "updateNotification() called with: drawableId = [" + drawableId + "]"); if (notBuilder == null) return; if (drawableId != -1) { - if (notRemoteView != null) notRemoteView.setImageViewResource(R.id.notificationPlayPause, drawableId); - if (bigNotRemoteView != null) bigNotRemoteView.setImageViewResource(R.id.notificationPlayPause, drawableId); + if (notRemoteView != null) + notRemoteView.setImageViewResource(R.id.notificationPlayPause, drawableId); + if (bigNotRemoteView != null) + bigNotRemoteView.setImageViewResource(R.id.notificationPlayPause, drawableId); } notificationManager.notify(NOTIFICATION_ID, notBuilder.build()); + timesNotificationUpdated++; } /*////////////////////////////////////////////////////////////////////////// @@ -275,7 +323,8 @@ public final class BackgroundPlayer extends Service { protected class BasePlayerImpl extends BasePlayer { - @NonNull final private AudioPlaybackResolver resolver; + @NonNull + final private AudioPlaybackResolver resolver; private int cachedDuration; private String cachedDurationString; @@ -294,8 +343,10 @@ public final class BackgroundPlayer extends Service { super.handleIntent(intent); resetNotification(); - if (bigNotRemoteView != null) bigNotRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 0, false); - if (notRemoteView != null) notRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 0, false); + if (bigNotRemoteView != null) + bigNotRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 0, false); + if (notRemoteView != null) + notRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 0, false); startForeground(NOTIFICATION_ID, notBuilder.build()); } @@ -330,6 +381,7 @@ public final class BackgroundPlayer extends Service { updateNotificationThumbnail(); updateNotification(-1); } + /*////////////////////////////////////////////////////////////////////////// // States Implementation //////////////////////////////////////////////////////////////////////////*/ @@ -351,10 +403,15 @@ public final class BackgroundPlayer extends Service { updateProgress(currentProgress, duration, bufferPercent); if (!shouldUpdateOnProgress) return; - resetNotification(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O /*Oreo*/) updateNotificationThumbnail(); + if (timesNotificationUpdated > NOTIFICATION_UPDATES_BEFORE_RESET) { + resetNotification(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O /*Oreo*/) { + updateNotificationThumbnail(); + } + } if (bigNotRemoteView != null) { - if(cachedDuration != duration) { + if (cachedDuration != duration) { cachedDuration = duration; cachedDurationString = getTimeString(duration); } @@ -382,8 +439,10 @@ public final class BackgroundPlayer extends Service { @Override public void destroy() { super.destroy(); - if (notRemoteView != null) notRemoteView.setImageViewBitmap(R.id.notificationCover, null); - if (bigNotRemoteView != null) bigNotRemoteView.setImageViewBitmap(R.id.notificationCover, null); + if (notRemoteView != null) + notRemoteView.setImageViewBitmap(R.id.notificationCover, null); + if (bigNotRemoteView != null) + bigNotRemoteView.setImageViewBitmap(R.id.notificationCover, null); } /*////////////////////////////////////////////////////////////////////////// diff --git a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayerActivity.java b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayerActivity.java index 761b50d85..1b5b5d07c 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayerActivity.java +++ b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayerActivity.java @@ -55,10 +55,7 @@ public final class BackgroundPlayerActivity extends ServicePlayerActivity { return true; } - this.player.setRecovery(); - getApplicationContext().sendBroadcast(getPlayerShutdownIntent()); - getApplicationContext().startService(getSwitchIntent(PopupVideoPlayer.class)); - return true; + return switchTo(PopupVideoPlayer.class); } return false; } diff --git a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java index 7c9041385..343de1ec1 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java @@ -150,6 +150,8 @@ public abstract class BasePlayer implements @NonNull public static final String RESUME_PLAYBACK = "resume_playback"; @NonNull + public static final String START_PAUSED = "start_paused"; + @NonNull public static final String SELECT_ON_APPEND = "select_on_append"; /*////////////////////////////////////////////////////////////////////////// @@ -304,7 +306,7 @@ public abstract class BasePlayer implements } // Good to go... initPlayback(queue, repeatMode, playbackSpeed, playbackPitch, playbackSkipSilence, - /*playOnInit=*/true); + /*playOnInit=*/!intent.getBooleanExtra(START_PAUSED, false)); } protected void initPlayback(@NonNull final PlayQueue queue, @@ -944,10 +946,10 @@ public abstract class BasePlayer implements public void onPlayPause() { if (DEBUG) Log.d(TAG, "onPlayPause() called"); - if (!isPlaying()) { - onPlay(); - } else { + if (isPlaying()) { onPause(); + } else { + onPlay(); } } diff --git a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java index 0650e2a26..fa742f771 100644 --- a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java @@ -29,6 +29,7 @@ import android.database.ContentObserver; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.media.AudioManager; +import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; @@ -78,6 +79,7 @@ import org.schabi.newpipe.player.resolver.MediaSourceTag; import org.schabi.newpipe.player.resolver.VideoPlaybackResolver; import org.schabi.newpipe.util.AnimationUtils; import org.schabi.newpipe.util.FireTvUtils; +import org.schabi.newpipe.util.KoreUtil; import org.schabi.newpipe.util.ListHelper; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.PermissionHelper; @@ -480,6 +482,7 @@ public final class MainVideoPlayer extends AppCompatActivity private boolean queueVisible; private ImageButton moreOptionsButton; + private ImageButton kodiButton; private ImageButton shareButton; private ImageButton toggleOrientationButton; private ImageButton switchPopupButton; @@ -516,6 +519,7 @@ public final class MainVideoPlayer extends AppCompatActivity this.moreOptionsButton = rootView.findViewById(R.id.moreOptionsButton); this.secondaryControls = rootView.findViewById(R.id.secondaryControls); + this.kodiButton = rootView.findViewById(R.id.kodi); this.shareButton = rootView.findViewById(R.id.share); this.toggleOrientationButton = rootView.findViewById(R.id.toggleOrientation); this.switchBackgroundButton = rootView.findViewById(R.id.switchBackground); @@ -527,6 +531,9 @@ public final class MainVideoPlayer extends AppCompatActivity titleTextView.setSelected(true); channelTextView.setSelected(true); + boolean showKodiButton = PreferenceManager.getDefaultSharedPreferences(this.context).getBoolean( + this.context.getString(R.string.show_play_with_kodi_key), false); + kodiButton.setVisibility(showKodiButton ? View.VISIBLE : View.GONE); getRootView().setKeepScreenOn(true); } @@ -563,6 +570,7 @@ public final class MainVideoPlayer extends AppCompatActivity closeButton.setOnClickListener(this); moreOptionsButton.setOnClickListener(this); + kodiButton.setOnClickListener(this); shareButton.setOnClickListener(this); toggleOrientationButton.setOnClickListener(this); switchBackgroundButton.setOnClickListener(this); @@ -633,6 +641,17 @@ public final class MainVideoPlayer extends AppCompatActivity finish(); } + public void onKodiShare() { + onPause(); + try { + NavigationHelper.playWithKore(this.context, Uri.parse( + playerImpl.getVideoUrl().replace("https", "http"))); + } catch (Exception e) { + if (DEBUG) Log.i(TAG, "Failed to start kore", e); + KoreUtil.showInstallKoreDialog(this.context); + } + } + /*////////////////////////////////////////////////////////////////////////// // Player Overrides //////////////////////////////////////////////////////////////////////////*/ @@ -659,7 +678,8 @@ public final class MainVideoPlayer extends AppCompatActivity this.getPlaybackPitch(), this.getPlaybackSkipSilence(), this.getPlaybackQuality(), - false + false, + !isPlaying() ); context.startService(intent); @@ -682,7 +702,8 @@ public final class MainVideoPlayer extends AppCompatActivity this.getPlaybackPitch(), this.getPlaybackSkipSilence(), this.getPlaybackQuality(), - false + false, + !isPlaying() ); context.startService(intent); @@ -731,6 +752,8 @@ public final class MainVideoPlayer extends AppCompatActivity } else if (v.getId() == closeButton.getId()) { onPlaybackShutdown(); return; + } else if (v.getId() == kodiButton.getId()) { + onKodiShare(); } if (getCurrentState() != STATE_COMPLETED) { diff --git a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java index 969c47990..70fb77060 100644 --- a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java @@ -567,7 +567,8 @@ public final class PopupVideoPlayer extends Service { this.getPlaybackPitch(), this.getPlaybackSkipSilence(), this.getPlaybackQuality(), - false + false, + !isPlaying() ); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); @@ -1123,4 +1124,4 @@ public final class PopupVideoPlayer extends Service { return distanceFromCloseButton(popupMotionEvent) <= getClosingRadius(); } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayerActivity.java b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayerActivity.java index 44fcdb8dd..b2af6d9d8 100644 --- a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayerActivity.java +++ b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayerActivity.java @@ -48,10 +48,7 @@ public final class PopupVideoPlayerActivity extends ServicePlayerActivity { @Override public boolean onPlayerOptionSelected(MenuItem item) { if (item.getItemId() == R.id.action_switch_background) { - this.player.setRecovery(); - getApplicationContext().sendBroadcast(getPlayerShutdownIntent()); - getApplicationContext().startService(getSwitchIntent(BackgroundPlayer.class)); - return true; + return switchTo(BackgroundPlayer.class); } return false; } diff --git a/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java b/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java index 2207808ac..08fcbc769 100644 --- a/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java +++ b/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java @@ -157,18 +157,11 @@ public abstract class ServicePlayerActivity extends AppCompatActivity case R.id.action_append_playlist: appendAllToPlaylist(); return true; - case R.id.action_settings: - NavigationHelper.openSettings(this); - redraw = true; - return true; case R.id.action_system_audio: startActivity(new Intent(Settings.ACTION_SOUND_SETTINGS)); return true; case R.id.action_switch_main: - this.player.setRecovery(); - getApplicationContext().sendBroadcast(getPlayerShutdownIntent()); - getApplicationContext().startActivity(getSwitchIntent(MainVideoPlayer.class)); - return true; + return switchTo(MainVideoPlayer.class); } return onPlayerOptionSelected(item) || super.onOptionsItemSelected(item); } @@ -189,8 +182,17 @@ public abstract class ServicePlayerActivity extends AppCompatActivity this.player.getPlaybackPitch(), this.player.getPlaybackSkipSilence(), null, + false, false - ).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + ).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + .putExtra(BasePlayer.START_PAUSED, !this.player.isPlaying()); + } + + protected boolean switchTo(final Class clazz) { + this.player.setRecovery(); + getApplicationContext().sendBroadcast(getPlayerShutdownIntent()); + getApplicationContext().startActivity(getSwitchIntent(clazz)); + return true; } //////////////////////////////////////////////////////////////////////////// diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/MediaSessionManager.java b/app/src/main/java/org/schabi/newpipe/player/helper/MediaSessionManager.java index a5c703837..8b9369613 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/MediaSessionManager.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/MediaSessionManager.java @@ -2,12 +2,19 @@ package org.schabi.newpipe.player.helper; import android.content.Context; import android.content.Intent; +import android.graphics.Bitmap; +import android.media.MediaMetadata; +import android.os.Build; +import android.support.v4.media.MediaMetadataCompat; import android.support.v4.media.session.MediaSessionCompat; import android.view.KeyEvent; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; +import androidx.core.app.NotificationCompat; import androidx.media.session.MediaButtonReceiver; +import androidx.media.app.NotificationCompat.MediaStyle; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector; @@ -19,8 +26,10 @@ import org.schabi.newpipe.player.mediasession.PlayQueuePlaybackController; public class MediaSessionManager { private static final String TAG = "MediaSessionManager"; - @NonNull private final MediaSessionCompat mediaSession; - @NonNull private final MediaSessionConnector sessionConnector; + @NonNull + private final MediaSessionCompat mediaSession; + @NonNull + private final MediaSessionConnector sessionConnector; public MediaSessionManager(@NonNull final Context context, @NonNull final Player player, @@ -40,13 +49,45 @@ public class MediaSessionManager { return MediaButtonReceiver.handleIntent(mediaSession, intent); } + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + public void setLockScreenArt(NotificationCompat.Builder builder, @Nullable Bitmap thumbnailBitmap) { + if (thumbnailBitmap == null || !mediaSession.isActive()) { + return; + } + + mediaSession.setMetadata( + new MediaMetadataCompat.Builder() + .putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, thumbnailBitmap) + .build() + ); + + MediaStyle mediaStyle = new MediaStyle() + .setMediaSession(mediaSession.getSessionToken()); + + builder.setStyle(mediaStyle); + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + public void clearLockScreenArt(NotificationCompat.Builder builder) { + mediaSession.setMetadata( + new MediaMetadataCompat.Builder() + .putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, null) + .build() + ); + + MediaStyle mediaStyle = new MediaStyle() + .setMediaSession(mediaSession.getSessionToken()); + + builder.setStyle(mediaStyle); + } + /** * Should be called on player destruction to prevent leakage. - * */ + */ public void dispose() { this.sessionConnector.setPlayer(null); this.sessionConnector.setQueueNavigator(null); this.mediaSession.setActive(false); this.mediaSession.release(); - } + } } diff --git a/app/src/main/java/org/schabi/newpipe/streams/SrtFromTtmlWriter.java b/app/src/main/java/org/schabi/newpipe/streams/SrtFromTtmlWriter.java new file mode 100644 index 000000000..6f1cceeed --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/streams/SrtFromTtmlWriter.java @@ -0,0 +1,95 @@ +package org.schabi.newpipe.streams; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.nodes.Node; +import org.jsoup.nodes.TextNode; +import org.jsoup.parser.Parser; +import org.jsoup.select.Elements; +import org.schabi.newpipe.streams.io.SharpStream; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +/** + * @author kapodamy + */ +public class SrtFromTtmlWriter { + private static final String NEW_LINE = "\r\n"; + + private SharpStream out; + private boolean ignoreEmptyFrames; + private final Charset charset = StandardCharsets.UTF_8; + + private int frameIndex = 0; + + public SrtFromTtmlWriter(SharpStream out, boolean ignoreEmptyFrames) { + this.out = out; + this.ignoreEmptyFrames = ignoreEmptyFrames; + } + + private static String getTimestamp(Element frame, String attr) { + return frame + .attr(attr) + .replace('.', ',');// SRT subtitles uses comma as decimal separator + } + + private void writeFrame(String begin, String end, StringBuilder text) throws IOException { + writeString(String.valueOf(frameIndex++)); + writeString(NEW_LINE); + writeString(begin); + writeString(" --> "); + writeString(end); + writeString(NEW_LINE); + writeString(text.toString()); + writeString(NEW_LINE); + writeString(NEW_LINE); + } + + private void writeString(String text) throws IOException { + out.write(text.getBytes(charset)); + } + + public void build(SharpStream ttml) throws IOException { + /* + * TTML parser with BASIC support + * multiple CUE is not supported + * styling is not supported + * tag timestamps (in auto-generated subtitles) are not supported, maybe in the future + * also TimestampTagOption enum is not applicable + * Language parsing is not supported + */ + + // parse XML + byte[] buffer = new byte[(int) ttml.available()]; + ttml.read(buffer); + Document doc = Jsoup.parse(new ByteArrayInputStream(buffer), "UTF-8", "", Parser.xmlParser()); + + StringBuilder text = new StringBuilder(128); + Elements paragraph_list = doc.select("body > div > p"); + + // check if has frames + if (paragraph_list.size() < 1) return; + + for (Element paragraph : paragraph_list) { + text.setLength(0); + + for (Node children : paragraph.childNodes()) { + if (children instanceof TextNode) + text.append(((TextNode) children).text()); + else if (children instanceof Element && ((Element) children).tagName().equalsIgnoreCase("br")) + text.append(NEW_LINE); + } + + if (ignoreEmptyFrames && text.length() < 1) continue; + + String begin = getTimestamp(paragraph, "begin"); + String end = getTimestamp(paragraph, "end"); + + writeFrame(begin, end, text); + } + } +} diff --git a/app/src/main/java/org/schabi/newpipe/streams/SubtitleConverter.java b/app/src/main/java/org/schabi/newpipe/streams/SubtitleConverter.java deleted file mode 100644 index c41db4373..000000000 --- a/app/src/main/java/org/schabi/newpipe/streams/SubtitleConverter.java +++ /dev/null @@ -1,369 +0,0 @@ -package org.schabi.newpipe.streams; - -import org.schabi.newpipe.streams.io.SharpStream; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.nio.charset.Charset; -import java.text.ParseException; -import java.util.Locale; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.xpath.XPathExpressionException; - -/** - * @author kapodamy - */ -public class SubtitleConverter { - private static final String NEW_LINE = "\r\n"; - - public void dumpTTML(SharpStream in, final SharpStream out, final boolean ignoreEmptyFrames, final boolean detectYoutubeDuplicateLines - ) throws IOException, ParseException, SAXException, ParserConfigurationException, XPathExpressionException { - - final FrameWriter callback = new FrameWriter() { - int frameIndex = 0; - final Charset charset = Charset.forName("utf-8"); - - @Override - public void yield(SubtitleFrame frame) throws IOException { - if (ignoreEmptyFrames && frame.isEmptyText()) { - return; - } - out.write(String.valueOf(frameIndex++).getBytes(charset)); - out.write(NEW_LINE.getBytes(charset)); - out.write(getTime(frame.start, true).getBytes(charset)); - out.write(" --> ".getBytes(charset)); - out.write(getTime(frame.end, true).getBytes(charset)); - out.write(NEW_LINE.getBytes(charset)); - out.write(frame.text.getBytes(charset)); - out.write(NEW_LINE.getBytes(charset)); - out.write(NEW_LINE.getBytes(charset)); - } - }; - - read_xml_based(in, callback, detectYoutubeDuplicateLines, - "tt", "xmlns", "http://www.w3.org/ns/ttml", - new String[]{"timedtext", "head", "wp"}, - new String[]{"body", "div", "p"}, - "begin", "end", true - ); - } - - private void read_xml_based(SharpStream source, FrameWriter callback, boolean detectYoutubeDuplicateLines, - String root, String formatAttr, String formatVersion, String[] cuePath, String[] framePath, - String timeAttr, String durationAttr, boolean hasTimestamp - ) throws IOException, ParseException, SAXException, ParserConfigurationException, XPathExpressionException { - /* - * XML based subtitles parser with BASIC support - * multiple CUE is not supported - * styling is not supported - * tag timestamps (in auto-generated subtitles) are not supported, maybe in the future - * also TimestampTagOption enum is not applicable - * Language parsing is not supported - */ - - byte[] buffer = new byte[(int) source.available()]; - source.read(buffer); - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document xml = builder.parse(new ByteArrayInputStream(buffer)); - - String attr; - - // get the format version or namespace - Element node = xml.getDocumentElement(); - - if (node == null) { - throw new ParseException("Can't get the format version. ¿wrong namespace?", -1); - } else if (!node.getNodeName().equals(root)) { - throw new ParseException("Invalid root", -1); - } - - if (formatAttr.equals("xmlns")) { - if (!node.getNamespaceURI().equals(formatVersion)) { - throw new UnsupportedOperationException("Expected xml namespace: " + formatVersion); - } - } else { - attr = node.getAttributeNS(formatVersion, formatAttr); - if (attr == null) { - throw new ParseException("Can't get the format attribute", -1); - } - if (!attr.equals(formatVersion)) { - throw new ParseException("Invalid format version : " + attr, -1); - } - } - - NodeList node_list; - - int line_break = 0;// Maximum characters per line if present (valid for TranScript v3) - - if (!hasTimestamp) { - node_list = selectNodes(xml, cuePath, formatVersion); - - if (node_list != null) { - // if the subtitle has multiple CUEs, use the highest value - for (int i = 0; i < node_list.getLength(); i++) { - try { - int tmp = Integer.parseInt(((Element) node_list.item(i)).getAttributeNS(formatVersion, "ah")); - if (tmp > line_break) { - line_break = tmp; - } - } catch (Exception err) { - } - } - } - } - - // parse every frame - node_list = selectNodes(xml, framePath, formatVersion); - - if (node_list == null) { - return;// no frames detected - } - - int fs_ff = -1;// first timestamp of first frame - boolean limit_lines = false; - - for (int i = 0; i < node_list.getLength(); i++) { - Element elem = (Element) node_list.item(i); - SubtitleFrame obj = new SubtitleFrame(); - obj.text = elem.getTextContent(); - - attr = elem.getAttribute(timeAttr);// ¡this cant be null! - obj.start = hasTimestamp ? parseTimestamp(attr) : Integer.parseInt(attr); - - attr = elem.getAttribute(durationAttr); - if (obj.text == null || attr == null) { - continue;// normally is a blank line (on auto-generated subtitles) ignore - } - - if (hasTimestamp) { - obj.end = parseTimestamp(attr); - - if (detectYoutubeDuplicateLines) { - if (limit_lines) { - int swap = obj.end; - obj.end = fs_ff; - fs_ff = swap; - } else { - if (fs_ff < 0) { - fs_ff = obj.end; - } else { - if (fs_ff < obj.start) { - limit_lines = true;// the subtitles has duplicated lines - } else { - detectYoutubeDuplicateLines = false; - } - } - } - } - } else { - obj.end = obj.start + Integer.parseInt(attr); - } - - if (/*node.getAttribute("w").equals("1") &&*/line_break > 1 && obj.text.length() > line_break) { - - // implement auto line breaking (once) - StringBuilder text = new StringBuilder(obj.text); - obj.text = null; - - switch (text.charAt(line_break)) { - case ' ': - case '\t': - putBreakAt(line_break, text); - break; - default:// find the word start position - for (int j = line_break - 1; j > 0; j--) { - switch (text.charAt(j)) { - case ' ': - case '\t': - putBreakAt(j, text); - j = -1; - break; - case '\r': - case '\n': - j = -1;// long word, just ignore - break; - } - } - break; - } - - obj.text = text.toString();// set the processed text - } - - callback.yield(obj); - } - } - - private static NodeList selectNodes(Document xml, String[] path, String namespaceUri) { - Element ref = xml.getDocumentElement(); - - for (int i = 0; i < path.length - 1; i++) { - NodeList nodes = ref.getChildNodes(); - if (nodes.getLength() < 1) { - return null; - } - - Element elem; - for (int j = 0; j < nodes.getLength(); j++) { - if (nodes.item(j).getNodeType() == Node.ELEMENT_NODE) { - elem = (Element) nodes.item(j); - if (elem.getNodeName().equals(path[i]) && elem.getNamespaceURI().equals(namespaceUri)) { - ref = elem; - break; - } - } - } - } - - return ref.getElementsByTagNameNS(namespaceUri, path[path.length - 1]); - } - - private static int parseTimestamp(String multiImpl) throws NumberFormatException, ParseException { - if (multiImpl.length() < 1) { - return 0; - } else if (multiImpl.length() == 1) { - return Integer.parseInt(multiImpl) * 1000;// ¡this must be a number in seconds! - } - - // detect wallclock-time - if (multiImpl.startsWith("wallclock(")) { - throw new UnsupportedOperationException("Parsing wallclock timestamp is not implemented"); - } - - // detect offset-time - if (multiImpl.indexOf(':') < 0) { - int multiplier = 1000; - char metric = multiImpl.charAt(multiImpl.length() - 1); - switch (metric) { - case 'h': - multiplier *= 3600000; - break; - case 'm': - multiplier *= 60000; - break; - case 's': - if (multiImpl.charAt(multiImpl.length() - 2) == 'm') { - multiplier = 1;// ms - } - break; - default: - if (!Character.isDigit(metric)) { - throw new NumberFormatException("Invalid metric suffix found on : " + multiImpl); - } - metric = '\0'; - break; - } - try { - String offset_time = multiImpl; - - if (multiplier == 1) { - offset_time = offset_time.substring(0, offset_time.length() - 2); - } else if (metric != '\0') { - offset_time = offset_time.substring(0, offset_time.length() - 1); - } - - double time_metric_based = Double.parseDouble(offset_time); - if (Math.abs(time_metric_based) <= Double.MAX_VALUE) { - return (int) (time_metric_based * multiplier); - } - } catch (Exception err) { - throw new UnsupportedOperationException("Invalid or not implemented timestamp on: " + multiImpl); - } - } - - // detect clock-time - int time = 0; - String[] units = multiImpl.split(":"); - - if (units.length < 3) { - throw new ParseException("Invalid clock-time timestamp", -1); - } - - time += Integer.parseInt(units[0]) * 3600000;// hours - time += Integer.parseInt(units[1]) * 60000;//minutes - time += Float.parseFloat(units[2]) * 1000f;// seconds and milliseconds (if present) - - // frames and sub-frames are ignored (not implemented) - // time += units[3] * fps; - return time; - } - - private static void putBreakAt(int idx, StringBuilder str) { - // this should be optimized at compile time - - if (NEW_LINE.length() > 1) { - str.delete(idx, idx + 1);// remove after replace - str.insert(idx, NEW_LINE); - } else { - str.setCharAt(idx, NEW_LINE.charAt(0)); - } - } - - private static String getTime(int time, boolean comma) { - // cast every value to integer to avoid auto-round in ToString("00"). - StringBuilder str = new StringBuilder(12); - str.append(numberToString(time / 1000 / 3600, 2));// hours - str.append(':'); - str.append(numberToString(time / 1000 / 60 % 60, 2));// minutes - str.append(':'); - str.append(numberToString(time / 1000 % 60, 2));// seconds - str.append(comma ? ',' : '.'); - str.append(numberToString(time % 1000, 3));// miliseconds - - return str.toString(); - } - - private static String numberToString(int nro, int pad) { - return String.format(Locale.ENGLISH, "%0".concat(String.valueOf(pad)).concat("d"), nro); - } - - - /****************** - * helper classes * - ******************/ - - private interface FrameWriter { - - void yield(SubtitleFrame frame) throws IOException; - } - - private static class SubtitleFrame { - //Java no support unsigned int - - public int end; - public int start; - public String text = ""; - - private boolean isEmptyText() { - if (text == null) { - return true; - } - - for (int i = 0; i < text.length(); i++) { - switch (text.charAt(i)) { - case ' ': - case '\t': - case '\r': - case '\n': - break; - default: - return false; - } - } - - return true; - } - } - -} diff --git a/app/src/main/java/org/schabi/newpipe/util/BitmapUtils.java b/app/src/main/java/org/schabi/newpipe/util/BitmapUtils.java new file mode 100644 index 000000000..7ad71eb5c --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/BitmapUtils.java @@ -0,0 +1,43 @@ +package org.schabi.newpipe.util; + +import android.graphics.Bitmap; + +import androidx.annotation.Nullable; + +public class BitmapUtils { + + @Nullable + public static Bitmap centerCrop(Bitmap inputBitmap, int newWidth, int newHeight) { + if (inputBitmap == null || inputBitmap.isRecycled()) { + return null; + } + + float sourceWidth = inputBitmap.getWidth(); + float sourceHeight = inputBitmap.getHeight(); + + float xScale = newWidth / sourceWidth; + float yScale = newHeight / sourceHeight; + + float newXScale; + float newYScale; + + if (yScale > xScale) { + newXScale = xScale / yScale; + newYScale = 1.0f; + } else { + newXScale = 1.0f; + newYScale = yScale / xScale; + } + + float scaledWidth = newXScale * sourceWidth; + float scaledHeight = newYScale * sourceHeight; + + int left = (int) ((sourceWidth - scaledWidth) / 2); + int top = (int) ((sourceHeight - scaledHeight) / 2); + int width = (int) scaledWidth; + int height = (int) scaledHeight; + + return Bitmap.createBitmap(inputBitmap, left, top, width, height); + } + +} diff --git a/app/src/main/java/org/schabi/newpipe/util/Constants.java b/app/src/main/java/org/schabi/newpipe/util/Constants.java index b01b6df6a..50350651d 100644 --- a/app/src/main/java/org/schabi/newpipe/util/Constants.java +++ b/app/src/main/java/org/schabi/newpipe/util/Constants.java @@ -11,5 +11,7 @@ public class Constants { public static final String KEY_THEME_CHANGE = "key_theme_change"; public static final String KEY_MAIN_PAGE_CHANGE = "key_main_page_change"; + public static final String KEY_ENABLE_WATCH_HISTORY = "enable_watch_history"; + public static final int NO_SERVICE_ID = -1; } diff --git a/app/src/main/java/org/schabi/newpipe/util/KoreUtil.java b/app/src/main/java/org/schabi/newpipe/util/KoreUtil.java new file mode 100644 index 000000000..2ed3c698d --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/KoreUtil.java @@ -0,0 +1,23 @@ +package org.schabi.newpipe.util; + + +import android.content.Context; +import android.content.DialogInterface; +import androidx.appcompat.app.AlertDialog; + +import org.schabi.newpipe.R; + + +public class KoreUtil { + private KoreUtil() { } + + public static void showInstallKoreDialog(final Context context) { + final AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setMessage(R.string.kore_not_found) + .setPositiveButton(R.string.install, + (DialogInterface dialog, int which) -> NavigationHelper.installKore(context)) + .setNegativeButton(R.string.cancel, (DialogInterface dialog, int which) -> { + }); + builder.create().show(); + } +} diff --git a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java index e2b03c8e8..a19aa92ae 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -109,12 +109,14 @@ public class NavigationHelper { final float playbackPitch, final boolean playbackSkipSilence, @Nullable final String playbackQuality, - final boolean resumePlayback) { + final boolean resumePlayback, + final boolean startPaused) { return getPlayerIntent(context, targetClazz, playQueue, playbackQuality, resumePlayback) .putExtra(BasePlayer.REPEAT_MODE, repeatMode) .putExtra(BasePlayer.PLAYBACK_SPEED, playbackSpeed) .putExtra(BasePlayer.PLAYBACK_PITCH, playbackPitch) - .putExtra(BasePlayer.PLAYBACK_SKIP_SILENCE, playbackSkipSilence); + .putExtra(BasePlayer.PLAYBACK_SKIP_SILENCE, playbackSkipSilence) + .putExtra(BasePlayer.START_PAUSED, startPaused); } public static void playOnMainPlayer(final Context context, final PlayQueue queue, final boolean resumePlayback) { diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamItemAdapter.java b/app/src/main/java/org/schabi/newpipe/util/StreamItemAdapter.java index 312c47263..cb2fae4f0 100644 --- a/app/src/main/java/org/schabi/newpipe/util/StreamItemAdapter.java +++ b/app/src/main/java/org/schabi/newpipe/util/StreamItemAdapter.java @@ -140,7 +140,15 @@ public class StreamItemAdapter extends BaseA if (stream instanceof SubtitlesStream) { formatNameView.setText(((SubtitlesStream) stream).getLanguageTag()); } else { - formatNameView.setText(stream.getFormat().getName()); + switch (stream.getFormat()) { + case WEBMA_OPUS: + // noinspection AndroidLintSetTextI18n + formatNameView.setText("opus"); + break; + default: + formatNameView.setText(stream.getFormat().getName()); + break; + } } qualityView.setText(qualityString); diff --git a/app/src/main/java/org/schabi/newpipe/views/ScrollableTabLayout.java b/app/src/main/java/org/schabi/newpipe/views/ScrollableTabLayout.java new file mode 100644 index 000000000..48327220a --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/views/ScrollableTabLayout.java @@ -0,0 +1,128 @@ +package org.schabi.newpipe.views; + +import android.content.Context; +import android.os.Build; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; + +import androidx.annotation.NonNull; + +import com.google.android.material.tabs.TabLayout; +import com.google.android.material.tabs.TabLayout.Tab; + +/** + * A TabLayout that is scrollable when tabs exceed its width. + * Hides when there are less than 2 tabs. + */ +public class ScrollableTabLayout extends TabLayout { + private static final String TAG = ScrollableTabLayout.class.getSimpleName(); + + private int layoutWidth = 0; + private int prevVisibility = View.GONE; + + public ScrollableTabLayout(Context context) { + super(context); + } + + public ScrollableTabLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public ScrollableTabLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + + remeasureTabs(); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + + layoutWidth = w; + } + + @Override + public void addTab(@NonNull Tab tab, int position, boolean setSelected) { + super.addTab(tab, position, setSelected); + + hasMultipleTabs(); + + // Adding a tab won't decrease total tabs' width so tabMode won't have to change to FIXED + if (getTabMode() != MODE_SCROLLABLE) { + remeasureTabs(); + } + } + + @Override + public void removeTabAt(int position) { + super.removeTabAt(position); + + hasMultipleTabs(); + + // Removing a tab won't increase total tabs' width so tabMode won't have to change to SCROLLABLE + if (getTabMode() != MODE_FIXED) { + remeasureTabs(); + } + } + + @Override + protected void onVisibilityChanged(View changedView, int visibility) { + super.onVisibilityChanged(changedView, visibility); + + // Recheck content width in case some tabs have been added or removed while ScrollableTabLayout was invisible + // We don't have to check if it was GONE because then requestLayout() will be called + if (changedView == this) { + if (prevVisibility == View.INVISIBLE) { + remeasureTabs(); + } + prevVisibility = visibility; + } + } + + private void setMode(int mode) { + if (mode == getTabMode()) return; + + setTabMode(mode); + } + + /** + * Make ScrollableTabLayout not visible if there are less than two tabs + */ + private void hasMultipleTabs() { + if (getTabCount() > 1) { + setVisibility(View.VISIBLE); + } else { + setVisibility(View.GONE); + } + } + + /** + * Calculate minimal width required by tabs and set tabMode accordingly + */ + private void remeasureTabs() { + if (prevVisibility != View.VISIBLE) return; + if (layoutWidth == 0) return; + + final int count = getTabCount(); + int contentWidth = 0; + for (int i = 0; i < count; i++) { + View child = getTabAt(i).view; + if (child.getVisibility() == View.VISIBLE) { + // Use tab's minimum requested width should actual content be too small + contentWidth += Math.max(child.getMinimumWidth(), child.getMeasuredWidth()); + } + } + + if (contentWidth > layoutWidth) { + setMode(TabLayout.MODE_SCROLLABLE); + } else { + setMode(TabLayout.MODE_FIXED); + } + } +} diff --git a/app/src/main/java/us/shandian/giga/postprocessing/Postprocessing.java b/app/src/main/java/us/shandian/giga/postprocessing/Postprocessing.java index 773ff92d1..e93e83a87 100644 --- a/app/src/main/java/us/shandian/giga/postprocessing/Postprocessing.java +++ b/app/src/main/java/us/shandian/giga/postprocessing/Postprocessing.java @@ -80,7 +80,7 @@ public abstract class Postprocessing implements Serializable { private transient DownloadMission mission; - private File tempFile; + private transient File tempFile; Postprocessing(boolean reserveSpace, boolean worksOnSameFile, String algorithmName) { this.reserveSpace = reserveSpace; @@ -95,8 +95,12 @@ public abstract class Postprocessing implements Serializable { public void cleanupTemporalDir() { if (tempFile != null && tempFile.exists()) { - //noinspection ResultOfMethodCallIgnored - tempFile.delete(); + try { + //noinspection ResultOfMethodCallIgnored + tempFile.delete(); + } catch (Exception e) { + // nothing to do + } } } diff --git a/app/src/main/java/us/shandian/giga/postprocessing/TtmlConverter.java b/app/src/main/java/us/shandian/giga/postprocessing/TtmlConverter.java index 5a5b687f7..8ed0dfae5 100644 --- a/app/src/main/java/us/shandian/giga/postprocessing/TtmlConverter.java +++ b/app/src/main/java/us/shandian/giga/postprocessing/TtmlConverter.java @@ -2,15 +2,10 @@ package us.shandian.giga.postprocessing; import android.util.Log; -import org.schabi.newpipe.streams.SubtitleConverter; +import org.schabi.newpipe.streams.SrtFromTtmlWriter; import org.schabi.newpipe.streams.io.SharpStream; -import org.xml.sax.SAXException; import java.io.IOException; -import java.text.ParseException; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.xpath.XPathExpressionException; /** * @author kapodamy @@ -27,33 +22,16 @@ class TtmlConverter extends Postprocessing { int process(SharpStream out, SharpStream... sources) throws IOException { // check if the subtitle is already in srt and copy, this should never happen String format = getArgumentAt(0, null); + boolean ignoreEmptyFrames = getArgumentAt(1, "true").equals("true"); if (format == null || format.equals("ttml")) { - SubtitleConverter ttmlDumper = new SubtitleConverter(); + SrtFromTtmlWriter writer = new SrtFromTtmlWriter(out, ignoreEmptyFrames); try { - ttmlDumper.dumpTTML( - sources[0], - out, - getArgumentAt(1, "true").equals("true"), - getArgumentAt(2, "true").equals("true") - ); + writer.build(sources[0]); } catch (Exception err) { Log.e(TAG, "subtitle parse failed", err); - - if (err instanceof IOException) { - return 1; - } else if (err instanceof ParseException) { - return 2; - } else if (err instanceof SAXException) { - return 3; - } else if (err instanceof ParserConfigurationException) { - return 4; - } else if (err instanceof XPathExpressionException) { - return 7; - } - - return 8; + return err instanceof IOException ? 1 : 8; } return OK_RESULT; diff --git a/app/src/main/java/us/shandian/giga/service/DownloadManager.java b/app/src/main/java/us/shandian/giga/service/DownloadManager.java index e8bc468e9..994c6ee63 100644 --- a/app/src/main/java/us/shandian/giga/service/DownloadManager.java +++ b/app/src/main/java/us/shandian/giga/service/DownloadManager.java @@ -139,6 +139,9 @@ public class DownloadManager { Log.d(TAG, "Loading pending downloads from directory: " + mPendingMissionsDir.getAbsolutePath()); } + File tempDir = pickAvailableTemporalDir(ctx); + Log.i(TAG, "using '" + tempDir + "' as temporal directory"); + for (File sub : subs) { if (!sub.isFile()) continue; if (sub.getName().equals(".tmp")) continue; @@ -184,7 +187,7 @@ public class DownloadManager { if (mis.psAlgorithm != null) { mis.psAlgorithm.cleanupTemporalDir(); - mis.psAlgorithm.setTemporalDir(pickAvailableTemporalDir(ctx)); + mis.psAlgorithm.setTemporalDir(tempDir); } mis.metadata = sub; @@ -513,13 +516,21 @@ public class DownloadManager { } static File pickAvailableTemporalDir(@NonNull Context ctx) { - if (isDirectoryAvailable(ctx.getExternalFilesDir(null))) - return ctx.getExternalFilesDir(null); - else if (isDirectoryAvailable(ctx.getFilesDir())) - return ctx.getFilesDir(); + File dir = ctx.getExternalFilesDir(null); + if (isDirectoryAvailable(dir)) return dir; + + dir = ctx.getFilesDir(); + if (isDirectoryAvailable(dir)) return dir; // this never should happen - return ctx.getDir("tmp", Context.MODE_PRIVATE); + dir = ctx.getDir("muxing_tmp", Context.MODE_PRIVATE); + if (isDirectoryAvailable(dir)) return dir; + + // fallback to cache dir + dir = ctx.getCacheDir(); + if (isDirectoryAvailable(dir)) return dir; + + throw new RuntimeException("Not temporal directories are available"); } @Nullable diff --git a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java index 8420e343b..aaf7826ef 100644 --- a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java +++ b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java @@ -5,6 +5,7 @@ import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; +import android.graphics.Color; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; @@ -35,6 +36,8 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView.Adapter; import androidx.recyclerview.widget.RecyclerView.ViewHolder; +import com.google.android.material.snackbar.Snackbar; + import org.schabi.newpipe.BuildConfig; import org.schabi.newpipe.R; import org.schabi.newpipe.extractor.NewPipe; @@ -46,6 +49,7 @@ import java.io.File; import java.lang.ref.WeakReference; import java.net.URI; import java.util.ArrayList; +import java.util.Iterator; import us.shandian.giga.get.DownloadMission; import us.shandian.giga.get.FinishedMission; @@ -104,8 +108,12 @@ public class MissionAdapter extends Adapter implements Handler.Callb private MenuItem mPauseButton; private View mEmptyMessage; private RecoverHelper mRecover; + private View mView; + private ArrayList mHidden; + private Snackbar mSnackbar; private final Runnable rUpdater = this::updater; + private final Runnable rDelete = this::deleteFinishedDownloads; public MissionAdapter(Context context, @NonNull DownloadManager downloadManager, View emptyMessage, View root) { mContext = context; @@ -122,6 +130,10 @@ public class MissionAdapter extends Adapter implements Handler.Callb mDeleter = new Deleter(root, mContext, this, mDownloadManager, mIterator, mHandler); + mView = root; + + mHidden = new ArrayList<>(); + checkEmptyMessageVisibility(); onResume(); } @@ -557,9 +569,50 @@ public class MissionAdapter extends Adapter implements Handler.Callb ); } - public void clearFinishedDownloads() { - mDownloadManager.forgetFinishedDownloads(); - applyChanges(); + public void clearFinishedDownloads(boolean delete) { + if (delete && mIterator.hasFinishedMissions() && mHidden.isEmpty()) { + for (int i = 0; i < mIterator.getOldListSize(); i++) { + FinishedMission mission = mIterator.getItem(i).mission instanceof FinishedMission ? (FinishedMission) mIterator.getItem(i).mission : null; + if (mission != null) { + mIterator.hide(mission); + mHidden.add(mission); + } + } + applyChanges(); + + String msg = String.format(mContext.getString(R.string.deleted_downloads), mHidden.size()); + mSnackbar = Snackbar.make(mView, msg, Snackbar.LENGTH_INDEFINITE); + mSnackbar.setAction(R.string.undo, s -> { + Iterator i = mHidden.iterator(); + while (i.hasNext()) { + mIterator.unHide(i.next()); + i.remove(); + } + applyChanges(); + mHandler.removeCallbacks(rDelete); + }); + mSnackbar.setActionTextColor(Color.YELLOW); + mSnackbar.show(); + + mHandler.postDelayed(rDelete, 5000); + } else if (!delete) { + mDownloadManager.forgetFinishedDownloads(); + applyChanges(); + } + } + + private void deleteFinishedDownloads() { + if (mSnackbar != null) mSnackbar.dismiss(); + + Iterator i = mHidden.iterator(); + while (i.hasNext()) { + Mission mission = i.next(); + if (mission != null) { + mDownloadManager.deleteMission(mission); + mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, mission.storage.getUri())); + } + i.remove(); + } } private boolean handlePopupItem(@NonNull ViewHolderItem h, @NonNull MenuItem option) { diff --git a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java index 921eaff5c..be0b0bb25 100644 --- a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java +++ b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java @@ -17,6 +17,7 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.widget.CheckBox; import android.widget.Toast; import androidx.annotation.NonNull; @@ -189,10 +190,12 @@ public class MissionsFragment extends Fragment { return true; case R.id.clear_list: AlertDialog.Builder prompt = new AlertDialog.Builder(mContext); - prompt.setTitle(R.string.clear_finished_download); + prompt.setTitle(R.string.clear_download_history); prompt.setMessage(R.string.confirm_prompt); - prompt.setPositiveButton(android.R.string.ok, (dialog, which) -> mAdapter.clearFinishedDownloads()); - prompt.setNegativeButton(R.string.cancel, null); + // Intentionally misusing button's purpose in order to achieve good order + prompt.setNegativeButton(R.string.clear_download_history, (dialog, which) -> mAdapter.clearFinishedDownloads(false)); + prompt.setPositiveButton(R.string.delete_downloaded_files, (dialog, which) -> mAdapter.clearFinishedDownloads(true)); + prompt.setNeutralButton(R.string.cancel, null); prompt.create().show(); return true; case R.id.start_downloads: diff --git a/app/src/main/res/layout-large-land/activity_main_player.xml b/app/src/main/res/layout-large-land/activity_main_player.xml index c40931a1a..851a687f9 100644 --- a/app/src/main/res/layout-large-land/activity_main_player.xml +++ b/app/src/main/res/layout-large-land/activity_main_player.xml @@ -311,7 +311,7 @@ tools:text="English" /> + + + + - - - diff --git a/app/src/main/res/menu/main_menu.xml b/app/src/main/res/menu/main_menu.xml deleted file mode 100644 index 05920099a..000000000 --- a/app/src/main/res/menu/main_menu.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/menu/menu_about.xml b/app/src/main/res/menu/menu_about.xml index 673cef94b..dbe91a04f 100644 --- a/app/src/main/res/menu/menu_about.xml +++ b/app/src/main/res/menu/menu_about.xml @@ -3,14 +3,4 @@ xmlns:tools="http://schemas.android.com/tools" tools:context="org.schabi.newpipe.about.AboutActivity"> - - - - diff --git a/app/src/main/res/menu/menu_play_queue.xml b/app/src/main/res/menu/menu_play_queue.xml index 6261b8c18..5413794be 100644 --- a/app/src/main/res/menu/menu_play_queue.xml +++ b/app/src/main/res/menu/menu_play_queue.xml @@ -10,11 +10,6 @@ android:visible="true" app:showAsAction="ifRoom"/> - - مستمعين تسريع إلى الأمام/-ترجيع وقت البحث - نموذج بيرتوب - تعيين حالات بيرتوب المفضلة لديك + مثيلات خوادم پيرتيوب + عيّن مثيلات خوادم پيرتيوب التي تُفضّلها إضافة نموذج - أدخل رابط نموذج - فشل في التحقق من النموذج + أدخل رابط مثيل الخادم + فشل في التحقق من مثيل الخادم فقط عناوين https المدعومة - نموذج موجود بالفعل + مثيل الخادم موجود بالفعل محلي أضيف مؤخرا الأكثر إعجابا تم إنشاؤه-تلقائيًا (لم يتم العثور على برنامج تحميل) استرد لا يمكن استرداد هذا التنزيل - اختيار نموذج + اختيار مثيل خادم \ No newline at end of file diff --git a/app/src/main/res/values-b+ast/strings.xml b/app/src/main/res/values-b+ast/strings.xml index 4ea5dae26..08b22c616 100644 --- a/app/src/main/res/values-b+ast/strings.xml +++ b/app/src/main/res/values-b+ast/strings.xml @@ -206,7 +206,7 @@ Sotítulos Aceutar ¿Quies reafitar los valores\? - + El sirvidor nun aceuta descargues multifilu, volvi probar con @string/msg_threads = 1 Nun hai comentarios Llimpieza de datos @@ -243,4 +243,18 @@ Siguir cola reproducción Les llingüetes que s\'amuesen na páxina principal Entrugar ánde baxar - + Descargues + Descargues + + Vídeos + + + Control per xestos del reproductor + Cargando\'l conteníu solicitáu + Política de Privacidá de NewPipe + Control per xestos del volume + Control per xestos del brilléu + El ficheru nun pue crease + El sirvidor nun unvia datos + La llingua va camudar namái que se reanicie l\'aplicación. + \ No newline at end of file diff --git a/app/src/main/res/values-b+zh+HANS+CN/strings.xml b/app/src/main/res/values-b+zh+HANS+CN/strings.xml index 8714c6aca..078379683 100644 --- a/app/src/main/res/values-b+zh+HANS+CN/strings.xml +++ b/app/src/main/res/values-b+zh+HANS+CN/strings.xml @@ -6,7 +6,7 @@ 在浏览器中打开 在悬浮窗模式下打开 您是不是要找:%1$s? - 找不到串流播放器 (您可以安裝并使用VLC播放)。 + 找不到串流播放器 (您可以安装 VLC 进行播放)。 下载串流文件 安装 取消 @@ -16,7 +16,7 @@ 设置 分享给... 选择浏览器 - 视频下载文件夹 + 视频下载路径 已下载的视频存储在这里 请选择下载视频的保存位置 已下载的音频存储在这里 @@ -39,10 +39,10 @@ 网络错误 视频 - + 禁用 - 背景 + 后台播放 过滤器 刷新 搜索建议 @@ -157,10 +157,10 @@ 切换服务,当前选择: 找不到串流播放器。您想安装 VLC 吗? 旋转 - 使用第三方视频播放器 - 使用第三方视频播放器 + 使用外部视频播放器 + 使用外部音频播放器 音频下载文件夹 - 从其他应用打开 NewPipe 时就播放视频 + 从其他应用调用 NewPipe 时播放视频 默认分辨率 找不到Kore。是否安装? 显示“用Kodi播放”选项 @@ -180,7 +180,7 @@ 错误报告 错误 无法加载所有缩略图 - 无法解密视频 URL 的签名 + 无法解密视频的 URL 签名 无法解析网址 无法完全解析网址 内容不可用 @@ -209,7 +209,7 @@ \n需要此权限 reCAPTCHA验证 请求的新的CAPTCHA验证 - NewPipe悬浮窗模式 + NewPipe 悬浮窗模式 在悬浮窗中播放 默认悬浮窗分辨率 使用更高的分辨率 @@ -219,7 +219,7 @@ 记住最后一次使用悬浮窗的大小和位置 悬浮窗 调整大小 - 删除“某些”分辨率的音频 + 部分分辨率的视频将没有声音 播放器手势控制 使用手势控制播放器的亮度和音量 显示搜索建议 @@ -234,9 +234,9 @@ 取消订阅频道 无法修改订阅 无法更新订阅 - 主页面 + 主页 订阅 - 新增功能 + 最新 恢复前台焦点 中断后继续播放(例如突然来电后) 搜索历史记录 @@ -321,7 +321,7 @@ 警告:无法导入所有文件。 这将覆盖当前设置。 显示信息 - 已收藏 + 书签 确定要从观看历史记录中删除该项吗? 是否确实要从历史记录中删除所有项目? 最后播放 @@ -483,7 +483,7 @@ 命名冲突,已存在具有此名称文件 无法覆盖文件 有此名称的已暂停下载 - 处理文件时,NewPipe 已关闭 + NewPipe 在处理文件时被关闭 设备上没有剩余储存空间 进度丢失,文件已被删除 连接超时 @@ -507,12 +507,33 @@ 无人在线观看 %s 人在观看 - + 没人在听 - %s个听众 + %s 人在听 重新启动应用后,语言将更改。 + PeerTube 服务器 + 设置自己喜欢的PeerTube服务器 + 查找最适合你的服务器%s + 添加服务器 + 输入服务器网址 + 无法验证服务器 + 仅支持 https URL + 该服务器已存在 + 本地 + 最近添加 + 最喜欢的 + 自动生成的(未找到上传者) + 正在恢复 + 无法恢复此下载 + 选择一个服务器 + 快进 / 快退的单位时间 + 在锁屏界面显示视频缩略图 + 在后台播放时,锁屏界面将会显示视频的缩略图 + 清除下载历史记录 + 删除下载了的文件 + 已删除 %1$s 下载 \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index d72b3de29..53b9a52eb 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -14,7 +14,7 @@ Meintest du: %1$s\? Teilen mit Browser auswählen - Drehen des Geräts + Bildschirm drehen Downloadordner für Videos Heruntergeladene Videodateien werden hier gespeichert Wähle den Downloadordner für Videodateien aus @@ -79,7 +79,7 @@ Dein Kommentar (auf englisch): Konnte keinen Stream abrufen Automatische Wiedergabe - Wiedergabe eines Videos, wenn NewPipe von einer anderen App aufgerufen wurde + Video abspielen, wenn NewPipe von einer anderen App aufgerufen wird Einen Fehler melden Anwenderbericht LIVE @@ -123,7 +123,8 @@ Bevorzugtes Videoformat Im Pop-up Modus abspielen NewPipe-Pop-up-Modus - Diese Berechtigung ist für das Öffnen im Pop-up-Modus erforderlich + Diese Berechtigung ist für das +\nÖffnen im Pop-up-Modus erforderlich Standardauflösung des Pop-ups Höhere Auflösungen anzeigen Nur manche Geräte unterstützen das Abspielen von 2K-/4K-Videos @@ -202,8 +203,8 @@ Keine Videos - Video - Videos + %s Video + %s Videos Die meisten Sonderzeichen Element gelöscht @@ -278,7 +279,7 @@ Dies wird deine aktuellen Einstellungen überschreiben. Infos anzeigen Lesezeichen für Wiedergabelisten - Hinzufügen zu + Hinzufügen Zum Neuordnen ziehen Erstellen Einen löschen @@ -395,7 +396,7 @@ Keine Zum Hintergrund-Player minimieren Zum Popup-Player minimieren - Vorspulen während der Stille + Vorspulen bei Stille Schritt Zurücksetzen Kanäle @@ -488,7 +489,7 @@ NewPipe wurde während der Verarbeitung der Datei geschlossen Kein Speicherplatz mehr auf dem Gerät Vorgang abgebrochen, da die Datei gelöscht wurde - Bist Du sicher\? + Möchtest du deinen Downloadverlauf oder alle heruntergeladenen Dateien löschen\? Downloadwarteschlange begrenzen Ein Download wird zur gleichen Zeit ausgeführt Downloads starten @@ -517,4 +518,25 @@ %s Zuhörer Die Sprache ändert sich, sobald die App neu gestartet wird. + PeerTube-Instanzen + Finde auf %s die Instanzen, die am besten zu dir passen + Instanz hinzufügen + URL der Instanz eingeben + Validierung der Instanz fehlgeschlagen + Instanz existiert bereits + Lokal + Kürzlich hinzugefügt + Auto-generiert (kein Uploader gefunden) + Wähle eine Instanz + Bevorzugte Peertube-Instanzen auswählen + Es werden nur HTTPS-Adressen unterstützt + Dauer der Suche bei schnellem Vor-/Zurückspulen + Am beliebtesten + Wiederherstellen + Dieser Download kann nicht wiederhergestellt werden + Video-Vorschaubild für Sperrbildschirm aktivieren + Bei Verwendung des Hintergrundplayers wird ein Video-Miniaturbild auf dem Sperrbildschirm angezeigt + Downloadverlauf löschen + Heruntergeladene Dateien löschen + %1$s Downloads gelöscht \ No newline at end of file diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 142813119..3d2397a0c 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -206,7 +206,7 @@ Λυπούμαστε, αυτό δεν έπρεπε να έχει συμβεί. Αναφορά σφάλματος με ηλεκτρονικό ταχυδρομίο Λυπούμαστε, συνέβησαν κάποια σφάλματα. - What:\\nΑίτημα:\\nΓλώσσα περιεχομένου:\\nΥπηρεσία:\\nΏρα GMT:\\nΠακέτο:\\nΈκδοση:\\nΈκδοση λειτουργικού: + Τι:\\nΑίτημα:\\nΓλώσσα περιεχομένου:\\nΥπηρεσία:\\nΏρα GMT:\\nΠακέτο:\\nΈκδοση:\\nΈκδοση λειτουργικού συστήματος: Αναφορά χρήστη Κανένα αποτέλεσμα Δεν υπάρχει τίποτα εδώ @@ -516,4 +516,12 @@ Η γλώσσα θα αλλάξει μόλις θα επανεκκινηθεί η εφαρμογή. Προεπιλεγμένο περίπτερο + Υποστηρίζονται μόνο διευθύνσεις URL HTTPS + Τοπικό + Προστέθηκε πρόσφατα + Δημιουργήθηκε αυτόματα (δεν βρέθηκε χρήστης μεταφόρτωσης) + Ανάκτηση + Δεν είναι δυνατή η ανάκτηση αυτής της λήψης + Ενεργοποίηση μικρογραφίας βίντεο στην οθόνη κλειδώματος + Όταν χρησιμοποιείται αναπαραγωγή παρασκηνίου μια μικρογραφία βίντεο θα εμφανίζεται στην οθόνη κλειδώματος \ No newline at end of file diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index c14195276..224e8837e 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -15,9 +15,9 @@ turno Uzi eksteran filmetoludilon Uzi eksteran sonludilon - Defaŭlta distingivo - Legi per Kodi - Montri \"Legi per Kodi\"-opcion + Defaŭlta rezolucio + Ludi per Kodi + Montri \"Ludi per Kodi\"-opcion Sono Defaŭlta sondosierformo Etoso @@ -30,8 +30,8 @@ Filmeto kaj sono Apero Alia - Ludado fone - Legi + Ludanta fone + Ludi Eraro Reteraro Enhavo malhavebla @@ -41,12 +41,12 @@ Neniu elsendlflua ludilo trovita. Ĉu vi volas instali la aplikaĵon VLC\? La aplikaĵo Kore ne estas trovita. Ĉu instali ĝin? Montri la sekvan filmeton kaj similajn filmetojn - Ĉiuj miniaturoj ne ŝargeblas + Ĉiuj bildetoj ne ŝargeblas La subskribo de la ligilo de la filmeto ne malĉifreblas La retejo ne analizeblas - Miniaturo de la antaŭrigardo de la filmeto - Legi filmeton, daŭro: - Miniaturo de la bildo de la alŝutinto + Bildeto de la antaŭrigardo de la filmeto + Ludi filmeton, daŭro: + Bildeto de la alŝutinto La elŝutujo \'%1$s\' ne kreeblas Elŝutujo \'%1$s\' kreita Elŝutujo por filmetoj @@ -61,7 +61,7 @@ Signali eraron per retpoŝto SIGNALI Informoj: - Via komento (en la angla): + Vian komenton (angle): Detaloj: Signali eraron Filmeto @@ -69,9 +69,9 @@ Premu serĉo por komenci Neniu elsendlflua ludilo trovita (instalu VLC por ludi ĝin). Malfermi en ŝprucfenestron modon - Forigas aŭdion ĉe KELKAJ distingivoj + Forigas aŭdon ĉe KELKAJ rezolucioj NewPipe ŝprucfenestron modon - Abonu + Aboni Abonita Kanalo malabonita Ne povis ŝanĝi abonon @@ -80,16 +80,16 @@ Montri informojn Ĉefa Abonoj - Legosigno + Konservitaj ludlistoj Kio novas Fono Ŝprucfenestro Aldonu al Aŭtomata play - Legas filmeton kiam NewPipe vokas de alia programo - Defaŭlta distingivo de la ŝprucfenestro - Montri pli altajn distingivojn - Nur kelkaj aparatoj subtenas legante 2K / 4K filmetojn + Ludas filmeton kiam NewPipe vokas el alia programo + Defaŭlta rezolucio de la ŝprucfenestro + Montri pli altajn rezoluciojn + Nur kelkaj aparatoj subtenas ludi 2K / 4K filmetojn Defaŭlta fomato de filmeto Nigra Memoru ŝprucfenestron kaj pozicion @@ -122,7 +122,7 @@ Poste Tiu permeso estas necesa por \nmalfermi en ŝprucfenestro modo - Leganta en ŝprucfenestro modo + Ludanta en ŝprucfenestro modo Malaktiva Filtri Aktualigi @@ -133,13 +133,13 @@ Uzu gestojn por kontroli la brilon kaj volumenon de la ludilo Serĉi sugestojn Montri sugestojn kiam serĉanto - Plej bona distingivo + Plej bona rezolucio Libera malpeza torentado ĉe Android. Elŝuti Leteroj kaj ciferoj Plej specialaj karakteroj Rekomencu en fokusa gajno - Daŭrigi la legon post la interrompaĵoj (ekzemple telefonadoj) + Daŭrigi la ludon post la interrompaĵoj (ekzemple telefonadoj) Serĉa historio Konservi la historio de serĉo lokale Rigardu historion @@ -205,21 +205,21 @@ Ne povis forigi ludlisto. Malcimigi Auto-vico sekva fluo - Aŭto-aldoni rilatan enhavon kiam leganta la lasta enhavo en malrepetita atendovico + Aŭto-aldoni rilatan enhavon kiam ludanta la lasta enhavo en malrepetita atendovico Dosiero Tia dosierujo ne ekzistas Tia dosiero/enhavo ne ekzistas Dosiernomo ne povas esti malplena - Eraro okazis : %1$s - Importu Jutubajn abonaĵojn per elŝuti la dosieron de eksporto : -\n -\n1. Iru ĉe tie retpaĝo : %1$s -\n2. Ensalutu kiam oni petas vin + Eraro okazis: %1$s + Importu Jutubajn abonaĵojn per elŝuti la dosieron de eksporto : +\n +\n1. Iru ĉe tiu retpaĝo: %1$s +\n2. Ensalutu kiam oni petas vin \n3. Elŝuto devus komenci (ĝi estas la dosiero de eksporto) - Importu Soundcloud-n profilon per elŝuti la dosieron de eksporto : + Importu Soundcloud-n profilon tajpante ĉu la ligilon, ĉu vian ID : \n \n1. Ebligu komputilon modon en krozilo (la retejo malhaveblas por poŝtelefonoj) -\n2. Iru al tie retpaĝo : %1$s +\n2. Iru tien: %1$s \n3. Ensalutu kiam oni petas vin \n4. Kopiu la ligilon de profilo ke oni kondikis vin. Malŝaltu por malebligi ŝarĝajn bildetojn, konservi datumojn kaj uzadon de memoro. Ŝanĝoj forviŝas ambaŭ en-memoro kaj sur-disko bildo kaŝmemoro. @@ -236,13 +236,13 @@ Forviŝi la serĉajn ŝlosilvortojn Ĉu vi volas forviŝi la totalon de la historio de serĉo \? Historio de serĉo forviŝita. - Limigi distingivo kiam uzanta moveblan datumon + Limigi rezolucio kiam uzanta moveblan datumon Minimumigi al ŝprucfenestro ludilo Kanaloj Ludlistoj Spuroj Uzantoj - Malabonu + Malaboni Nova ongleto Elektu ongleton Kontrolo de volumena gesto @@ -265,7 +265,7 @@ Konferencoj Montri komentojn Malebligu por malvidigi komentojn - Aŭtolego + Aŭtoludo Komentoj @@ -291,8 +291,8 @@ Oni petos vin kie konservi ĉion elŝutaĵon. \nElektu AFM se vi volas elŝuti al ekstera SD-karto Uzu AFM - La Atinga Framo al la Memoro ebligas elŝuti al ekstera SD-karto. -\nKomento : kelkaj aparatoj ne kongruas + La Atinga Framo al la Memoro ebligas elŝuti al ekstera SD-karto. +\nKomento: kelkaj aparatoj ne kongruas Forviŝi ludajn poziciojn Forviŝi la totalon de ludaj pozicioj Ĉu vi volas forviŝi ĉiujn ludajn poziciojn \? @@ -342,7 +342,7 @@ Rigardu ĉe GitHub Permesilo de NewPipe Ĉu vi havas ideojn pri; traduko, desegnaĵoj ŝanĝoj, purigado de kodo, aŭ realaj masivaj ŝanĝoj—helpo estas ĉiam bonvena. Ju pli oni faras, des pli bonas! - Legu permesilon + Legi permesilon Kontribui Permesitaj karakteroj en dosiernomoj Nevalidaj karakteroj estas anstataŭigita kun ĉi tiu valoro @@ -375,7 +375,7 @@ Neniuj kanalaj abonoj ankoraŭ Elekti kioskon Komenci ludi ĉi tie - Komenci ludi en la fono + Komenci ludi fone Donaci NewPipe estas programada par volontuoj, elspezante tempo por alporti vin la plej bona sperto. Redonu por helpi programistojn plibonigi NewPipe dum ĝuante tason da kafo. Redoni @@ -413,7 +413,7 @@ La monitorado de la memorlikadoj povas frostigi la apon dum la hejta dumpingo Signali ekster-vivciklajn erarojn Perforti signalante neenretigaj Rx esceptoj eksere la fragmento aŭ aktiveco vivciklo post dispono - La dosiero ne ekzistas aŭ la legopermeso mankas + La dosiero ne ekzistas aŭ la ludopermeso mankas Importi/eksporti Importi Importi el @@ -437,13 +437,13 @@ Subtitoloj Modifi la dimension de la teksto kaj la fonajn stilojn de la subtitoloj de la ludilo. Ĝi bezonas restarto de la apo por efektiviĝi. 1 ero forviŝita. - NewPipe estas programaro sub rajtoceda permesilo: Vi povas uzi, studi, komuniki kaj plibonigi ĝin kiel vi volas. Precize, vi povas redistribui kaj/aŭ modifi ĝin sub la kondiĉojn de la Ĝenerala Publika Permesilo de GNU, kiel publikigita per la Free Software Foundation, ĉu en la versio 3, ĉu (se vi volas) ajna posta versio. + NewPipe estas programaro sub rajtoceda permesilo: Vi povas uzi, studi, komuniki kaj plibonigi ĝin kiel vi volas. Precize, vi povas redistribui kaj/aŭ modifi ĝin sub la kondiĉoj de la Ĝenerala Publika Permesilo de GNU, kiel publikigita per la Free Software Foundation, ĉu en la versio 3, ĉu (se vi volas) ajna posta versio. Ĉu vi volas ankaŭ importi agordojn\? Privateca politiko de NewPipe - La NewPipe projekto respektas vian privatecon serioze. Konsekvence, la apo ne kolektas ajnan datumo sen via konsento. + La NewPipe projekto serioze respektas vian privatecon. Konsekvence, la apo ne kolektas ajnan datumo sen via konsento. \nLa privateco politiko de Newpipe detale eksplikas kion datumon estas sendita kaj stokita kiam vi sendas falegosignalon. Legi la privatecan politikon - Por konformiĝi al la Ĝenerala Datum-Protekta Regularon (GDPR), ni allogas vian atento al la privateca politiko de NewPipe. Bonvolu legi ĝin atentive. + Por konformiĝi al la Ĝenerala Datum-Protekta Regularon (GDPR), ni allogas vian atenton al la privateca politiko de NewPipe. Bonvolu atentive legi ĝin. \nVi devas akcepti ĝin por sendi nin la cimsignalo. Akcepti Rifuzi @@ -455,7 +455,7 @@ Plirapidigi dum silentoj Paŝo Restarigi - Uzante defaŭltajn ongletojn, eraro dum leganta savajn ongletojn + Uzante defaŭltajn ongletojn, eraro ludante savajn ongletojn Restaŭri la defaŭltojn Ĉu vi volas restaŭri la defaŭltojn \? Kalkulo de abonantoj malhavebla @@ -516,4 +516,22 @@ %s aŭskultantoj La lingvo ŝanĝos kiam la apo restartos. + Rapida antaŭen / posten daŭron + Instancoj de PeerTube + Elekti viajn preferitajn instancojn de PeerTube + Trovu la instancojn kiu vi povus ŝati ĉe %s + Aldoni instanco + Eniri la ligilon de la instanco + Ne povis validigi instanco + Nur HTTPS ligiloj estas subtenitaj + La instanco jam ekzistas + Loka + Freŝdate ĝisdatigita + La plej ŝatitatj + Aŭtomate generita (neniu alŝutilo trovita) + Reakiranta + Ne povas reakiri tion elŝuton + Elektu instancon + Enablu bildeta filmeton ĉe ŝlosita ekrano + Uzante la fona ludilo, bildeta filmeto vidiĝos ĉe ŝlosita ekrano \ No newline at end of file diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 5691c2ab6..9f25208bb 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -518,4 +518,20 @@ %s escuchas El idioma cambiará luego de que la app sea reiniciada. + Duración de búsqueda al avanzar y/o retroceder + Instancias de PeerTube + Selecciona tus instancias favoritas de PeerTube + Encuentra las mejores instancias para ti en %s + Agregar instancia + Ingresar URL de la instancia + No se pudo validar la instancia + Sólo URLs con HTTPS son soportados + La instancia ya existe + Local + Agregados recientemente + Más gustados + Generado automáticamente (no se encontró creador) + Elige una instancia + Habilitar miniatura de video de la pantalla de bloqueo + Al usar el reproductor de fondo, se mostrará una miniatura de video en la pantalla de bloqueo \ No newline at end of file diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index adf7d6720..b376f1f6d 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -500,13 +500,13 @@ Aldatu deskargen karpetak indarrean jartzeko Ez dago inor ikusten - %s ikusten - %s ikusten + ikusle %s + %s ikusle Ez dago inor entzuten - %s entzuten - %s entzuten + entzule %s + %s entzule SAF erabili Biltegian Sartzeko Armazoiak kanpoko SD txartel betera jaitsierak egitea ahalbidetzen du. @@ -517,4 +517,20 @@ Aktibatu zerbitzua, orain hautatua: Hizkuntza aldatuko da aplikazioa berrabiarazterakoan. Kiosko Lehenetsia + Aurreratze/atzeratze bilaketaren iraupena + PeerTube instantziak + Hautatu zure gogoko PeerTube instantziak + Aurkitu instantziak hemen: %s + Gehitu instantzia + Sartu instantziaren URLa + Ezin izan da instantzia balioztatu + HTTPS URLak onartzen dira soilik + Instantzia badago aurretik + Lokala + Berriki gehitua + Gogokoenak + Automatikoki sortua (igotzailea ez da aurkitu) + berreskuratzen + Ezin da deskarga hau berreskuratu + Aukeratu instantzia \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index aecf113d1..444310aef 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -122,7 +122,7 @@ M Cette autorisation est nécessaire pour \nutiliser le mode flottant - Arrière-plan + Lire l\'audio Flottant Définition de la fenêtre flottante par défaut Afficher des définitions plus élevées @@ -185,7 +185,7 @@ Notification NewPipe Annuler Garde un suivi des vidéos vues - Reprendre à l’obtention de la cible de saisie + Reprendre lors du retour dans l\'application Lecteur Comportement Historique et cache @@ -310,7 +310,7 @@ Utiliser la recherche rapide approximative Permet au lecteur d’accéder plus rapidement à une position au détriment de la précision Charger les miniatures - Désactiver pour empêcher le chargement des miniatures afin d\'économiser vos données. Modifier cette option vide le cache en mémoire vive et sur le disque. + Désactivez pour empêcher le chargement des miniatures afin de réduire l’utilisation de la bande passante et de la mémoire. La modification de cette option, vide le cache en mémoire vive et sur le disque. Images en cache effacées Effacer les métadonnées en cache Efface toutes les données de pages Web en cache @@ -517,4 +517,22 @@ %s auditeurs La langue changera lors du redémarrage de l\'application. + Avance/rembobinage rapide sur une durée + Instances PeerTube + Choisissez vos instances PeerTube préférées + Cherchez des instances qui pourraient vous intéresser sur %s + Ajouter une instance + Entrez l’URL de l’instance + Échec de validation de l’instance + Sont prises en charge uniquement les URLs en HTTPS + L’instance existe déjà + Local + Ajoutées récemment + Les plus aimées + récupération + Impossible de récupérer ce téléchargement + Choisissez une instance + Généré automatiquement (pas de téléverseur trouvé) + Activer la vidéo miniaturisée sur l\'écran de verrouillage + En utilisant le lecteur audio, la miniature de la vidéo sera affichée sur l\'écran de verrouillage \ No newline at end of file diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index fbcf5ce63..7a1338f60 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -254,7 +254,7 @@ הוספה לתור בנגן צף חדש להתחיל לנגן מכאן להתחיל לנגן ברקע - להתחיל לנגן בחלון צף חדש + להתחיל לנגן בנגן צף חדש הורדת קובץ הזרמה הצגת מידע רשימות נגינה מסומנות @@ -490,13 +490,13 @@ מיקומי הנגינה נמחקו. הקובץ הועבר או נמחק כבר קיים קובץ בשם הזה - לא ניתן לשכתב על הקובץ + לא ניתן לשכתב את הקובץ כבר יש הורדה ממתינה בשם הזה NewPipe נסגר בזמן העבודה על הקובץ לא נשאר מקום במכשיר התהליך אבד כיוון שהקובץ נמחק החיבור המתין זמן רב מדי - בוודאות\? + למחוק את היסטוריית ההורדות שלך או למחוק את כל הקבצים שהורדת\? הגבלת תור ההורדה רק הורדה אחת תרוץ בו־זמנית התחלת הורדות @@ -529,4 +529,25 @@ השפה תוחלף עם הפעלת היישומון מחדש. קיוסק בררת מחדל + משך קפיצה מהירה קדימה/אחורה + מופעים של PeerTube + נא לבחור את מופעי ה־PeerTube המועדפים עליך + איתור המופעים שהכי מתאימים לך תחת %s + הוספת מופע + נא להכניס כתובת מופע + לא ניתן לאמת את המופע + יש תמיכה בכתובות HTTPS בלבד + המופע כבר קיים + מקומי + נוספו לאחרונה + האהובים ביותר + נוצרה אוטומטית (לא נמצא מעלה) + בשחזור + לא ניתן לשחזר את ההורדה הזאת + נא לבחור מופע + הפעלת תמונה מוקטנת של הסרטון במסך הנעילה + בעת השימוש בנגן הרקע תופיע תמונה מוקטנת של הסרטון על מסך הנעילה + מחיקת היסטוריית ההורדות + למחוק את הקבצים שהורדתי + נמחקו %1$s הורדות \ No newline at end of file diff --git a/app/src/main/res/values-ia/strings.xml b/app/src/main/res/values-ia/strings.xml new file mode 100644 index 000000000..6bbcac7b3 --- /dev/null +++ b/app/src/main/res/values-ia/strings.xml @@ -0,0 +1,37 @@ + + + Installar + Aperir in le navigator + Compartir + Discargar + Cercar + Configurationes + Compartir con + Seliger un navigator + Subscribite + Cancellar le subscription + Non poteva cambiar le subscription + Non poteva actualisar le subscription + Monstrar information + Principal + Subscriptiones + Nove scheda + Seliger le scheda + Novitates + Fundo + Emergente + Adder a + Dossier de discarga de video + Selige le dossier de discarga pro files de video + Dossier de discarga de audio + Cancellar + Subscriber + Selige le dossier de discarga pro files de audio + Thema + Monstrar le commentos + Initiar discargas + Pausar le discargas + Seliger un instantia + Non poteva connecter con le servitor + %1$s vistas + \ No newline at end of file diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index 938837bd5..8677df678 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -510,4 +510,21 @@ %s mendengarkan Bahasa akan diterapkan setelah aplikasi dimulai ulang. + Situs PeerTube + Pilih situs PeerTube favorit anda + Temukan situs yang sesuai dengan anda di %s + Tambah situs + Masukkan URL situs + Tidak bisa memvalidasi situs + Hanya mendukung URL HTTPS + Situs sudah ada + Lokal + Baru-baru ini ditambahkan + Disukai terbanyak + Dibuat otomatis (pengunggah tidak ditemukan) + memulihkan + Tidak bisa memulihkan unduhan ini + Pilih situs + Aktifkan kunci layar thumbnail video + Ketika menggunakan pemutar latar belakang, thumbnail video akan ditampilkan di tampilan kunci layar \ No newline at end of file diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 631922433..4942f4720 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -1,6 +1,6 @@ - %1$s visualizzazioni + %1$ visualizzazioni Pubblicato il %1$s Nessun lettore multimediale trovato. Vuoi installare VLC\? Installa @@ -14,21 +14,21 @@ Condividi con Scegli browser rotazione - Cartella dei video scaricati + Cartella Video Scaricati I video scaricati saranno salvati qui Scegli la cartella per i video scaricati - Risoluzione predefinita + Risoluzione Predefinita Riproduci con Kodi - L\'applicazione Kore non è stata trovata. Vuoi installarla? + L\'applicazione Kore non è stata trovata. Installarla\? Mostra l\'opzione \"Riproduci con Kodi\" Mostra l\'opzione per riprodurre i video tramite Kodi Audio - Formato audio predefinito + Formato Audio Predefinito Scarica Prossimo - Mostra video \'Prossimo\' e \'Simili\' + Mostra video \"Prossimo\" e \"Simili\" URL non supportato - Lingua predefinita per i contenuti + Lingua Predefinita per Contenuti Video e Audio Miniatura anteprima video Riproduci video, durata: @@ -39,7 +39,7 @@ Creata la cartella per i download \'%1$s\' Usa un lettore video esterno Usa un lettore audio esterno - Cartella degli audio scaricati + Cartella Audio Scaricati Gli audio scaricati saranno salvati qui Scegli la cartella per gli audio scaricati Tema @@ -47,7 +47,7 @@ Chiaro Aspetto Altro - Riproduzione in sottofondo + Riproduzione in Sottofondo Riproduci Errore Errore di connessione @@ -60,10 +60,10 @@ Impossibile impostare il menu di download I contenuti in diretta non sono al momento supportati Contenuti - Contenuti vietati ai minori + Contenuti Vietati ai Minori Mostra video riservati a un pubblico maggiorenne. Si possono abilitare dalle Impostazioni. Tocca Cerca per iniziare - Riproduzione automatica + Riproduzione Automatica Riproduci i video quando NewPipe viene aperto da un\'altra app IN DIRETTA Impossibile analizzare completamente il sito web @@ -84,7 +84,7 @@ È stato negato il permesso di accesso all\'archiviazione di massa Download Download - Segnalazione errori + Segnalazione Errori Inizia Pausa Riproduci @@ -102,7 +102,7 @@ Tocca per maggiori dettagli Attendi… Copiato negli appunti - Nelle impostazioni seleziona una cartella per i download + Seleziona una cartella per i download Impossibile caricare l\'immagine L\'app/UI si è interrotta Cosa:\\nRichiesta:\\nLingua contenuto:\\nServizio:\\nOrario GMT:\\nPacchetto:\\nVersione:\\nVersione SO: @@ -119,21 +119,21 @@ Più tardi Apri in modalità popup Modalità popup di NewPipe - Riproduzione in modalità popup + Riproduzione in Modalità Popup Disattivato - Non riproduce l\'audio con ALCUNE risoluzioni + L\'audio potrebbe non essere disponibile per ALCUNE risoluzioni In sottofondo Popup - Risoluzione predefinita per la modalità popup - Mostra risoluzioni più alte + Risoluzione Predefinita Popup + Mostra Altre Risoluzioni Solo alcuni dispositivi supportano la riproduzione video in 2K e 4K - Formato video predefinito - Ricorda dimensione e posizione del popup - Ricorda l\'ultima dimensione e posizione del popup - Controlli gestuali del lettore multimediale - Usa i gesti per controllare la luminosità e il volume del lettore multimediale - Suggerimenti di ricerca - Mostra i suggerimenti durante la ricerca + Formato Video Predefinito + Ricorda Dimensione e Posizione Popup + Ricorda l\'ultima dimensione e posizione della finestra popup + Controllo Movimenti Lettore Multimediale + Usa i movimenti per controllare luminosità e volume del lettore multimediale + Suggerimenti Ricerca + Mostra suggerimenti durante la ricerca Popup Filtra i risultati Ricarica @@ -144,18 +144,18 @@ \nper riprodurre in modalità popup Impostazioni Informazioni - Licenze di terze parti + Licenze di Terze Parti © %1$s di %2$s protetto da licenza %3$s Impossible caricare la licenza - Visita il sito + Visita il Sito Informazioni Contributori Licenze Streaming libero e leggero su Android. Mostra su GitHub Licenza di NewPipe - Un aiuto è sempre il benvenuto: nuove idee e funzionalità, traduzioni, modifiche al design o cambiamenti radicali del codice rendono l\'applicazione sempre migliore! - Leggi la licenza + Un aiuto è sempre gradito: traduzioni, modifiche al design, pulizia del codice, cambiamenti radicali. Più si fa, meglio è! + Leggi la Licenza Contribuisci Informazioni su NewPipe Iscriviti @@ -165,18 +165,18 @@ Impossibile aggiornare l\'iscrizione Iscrizioni Novità - Cronologia ricerche - Salva le ricerche - Visualizza storico + Cronologia Ricerche + Salva le ricerche localmente + Cronologia Visualizzazioni Salva la cronologia dei video visualizzati - Riprendi tornando in primo piano + Riprendi Riproduzione Continua a riprodurre dopo le interruzioni (es. chiamate) Scarica - Caratteri ammessi nei nomi dei file + Caratteri Ammessi per i Nomi dei File I caratteri non validi vengono sostituiti con - Carattere sostitutivo - Lettere e cifre - Caratteri speciali + Carattere Sostitutivo + Lettere e Cifre + La Maggio Parte dei Caratteri Speciali Cronologia Ricerche effettuate Visualizzati @@ -185,9 +185,9 @@ La cronologia è vuota Cronologia cancellata Principale - Lettore multimediale + Lettore Multimediale Comportamento - Cronologia e cache + Cronologia e Cache Playlist Annulla Notifiche NewPipe @@ -211,23 +211,23 @@ Elemento eliminato Nulla da mostrare Vuoi eliminare questo elemento dalla cronologia? - Contenuto della pagina principale - Pagina vuota - Locandina - Pagina iscrizione - Pagina feed - Pagina del canale - Seleziona un canale - Nessuna iscrizione ad un canale - Seleziona una locandina + Contenuto della Pagina Principale + Pagina Vuota + Contenuti in Evidenza Personalizzati + Iscrizioni + Feed Iscrizioni + Canale Personalizzato + Seleziona Canale + Nessuna Iscrizione + Seleziona Contenuto Locandina Tendenze Top 50 New & hot - Mostra il suggerimento \"Tenere premuto per aggiungere video alla coda\" - Mostra suggerimento quando il pulsante per la riproduzione popup o in sottofondo viene premuto nella pagina dei dettagli del video - In coda al lettore multimediale in sottofondo - In coda al lettore multimediale a comparsa + Mostra Suggerimento \"Tieni Premuto per Accocodare\" + Mostra suggerimento quando il pulsante per la riproduzione \"popup\" o \"in sottofondo\" viene premuto nella pagina dei dettagli del video + In Coda in Sottofondo + In Coda in Modalità Popup Riproduci tutto Impossibile riprodurre questo flusso Si è verificato un errore irreversibile @@ -245,14 +245,14 @@ Avvia riproduzione in sottofondo Avvia riproduzione a comparsa Dona - Sito web - Visita il sito web di NewPipe per maggiori informazioni e novità. - NewPipe è sviluppato da volontari che trascorrono il loro tempo libero per offrire la migliore esperienza. Restituisci il favore per aiutare gli sviluppatori a rendere NewPipe ancora più piacevole mentre si gustano una tazza di caffè. + Sito + Visita il sito di NewPipe per informazioni e novità. + NewPipe è sviluppato da volontari che impiegano il loro tempo libero per offrire un\'esperienza migliore. Restituisci il favore, aiutandoli a rendere NewPipe ancora più piacevole, mentre si gustano una tazza di caffè. Restituisci - Paese predefinito per i contenuti + Paese Predefinito per Contenuti Cambia orientamento Passa alla riproduzione in background - Passa alla visualizzazione popup + Passa a Popup Passa alla produzione predefinita Servizio Apri il menu @@ -292,21 +292,21 @@ Sei sicuro di voler eliminare tutti gli elementi dalla cronologia? Ultima riproduzione I più riprodotti - Chiedi sempre - Nuova scaletta - Elimina scaletta - Rinomina scaletta + Chiedi ogni volta + Nuova Playlist + Elimina + Rinomina Nome Aggiunti alla playlist Imposta come miniatura della playlist Segnalibri playlist Rimuovi segnalibro - Eliminare questa scaletta\? + Eliminare la playlist\? Playlist creata - Aggiunti alla scaletta - Miniatura della scaletta cambiata. - Impossibile eliminare la scaletta. - No sottotitoli + Aggiunto alla Playlist + Miniatura della Playlist cambiata. + Impossibile eliminare la Playlist. + Nessun Sottotitolo Rientrato Pieno Ingrandito @@ -317,10 +317,10 @@ Il monitoraggio delle perdite di memoria potrebbe causare la mancata risposta dell\'applicazione durante il dumping dell\'heap Segnala Errori \"Out-of-lifecycle\" Forza la segnalazione di eccezioni Rx non consegnabili al di fuori del ciclo di vita dell\'attività dopo la chiusura - Usa la ricerca rapida ma imprecisa - La ricerca imprecisa permette al lettore multimediale di spostarsi nelle posizioni più velocemente con una precisione ridotta - Metti in coda automaticamente il prossimo flusso - Aggiungi automaticamente un contenuto correlato raggiunta la fine della coda se la ripetizione è disattivata + Usa Ricerca Rapida (Imprecisa) + Consente al lettore multimediale di spostarsi più velocemente, ma con precisione ridotta + Accoda Automaticamente l\'Elemento Successivo + Accoda un contenuto consigliato quando è in corso la riproduzione dell\'ultimo elemento, in una coda non ripetitiva File Nessuna cartella Nessun file o cartella che contiene sorgenti @@ -352,12 +352,12 @@ Tieni presente che questa operazione può consumare una grande quantità di traffico dati. \n \nVuoi continuare? - Carica miniature - Disabilita per prevenire il caricamento delle miniature, risparmiando dati e memoria. La modifica di questa opzione cancellerà la cache delle immagini in memoria e sul disco. - Pulizia della cache delle immagini completata - Pulisci la cache dei metadati - Rimuovi tutti i dati delle pagine web memorizzati nella cache - Pulizia della cache dei metadati completata + Carica Anteprime + Disabilita per prevenire il caricamento delle anteprime, risparmiando dati e memoria. La modifica di questa opzione cancellerà la cache delle immagini in memoria e sul disco. + Cache immagini svuotata + Pulisci Cache Metadati + Rimuovi i dati delle pagine web memorizzati nella cache + Cache metadati svuotata Controlli della velocità di riproduzione Tempo Tono @@ -367,7 +367,7 @@ \'Apri\' preferibilmente con Azione predefinita all\'apertura del contenuto — %s Sottotitoli - Modifica la dimensione e gli stili di sfondo dei sottotitoli. Per applicare le modifiche è richesto un riavvio. + Modifica dimensione e stile dei sottotitoli. Riavviare per applicare le modifiche. Nessuna app installata per riprodurre questo file Pulisci cronologia visualizzazioni Elimina la cronologia dei flussi riprodotti e la posizione di riproduzione @@ -378,9 +378,9 @@ Elimina l\'intera cronologia delle ricerche\? Cronologia delle ricerche eliminata. 1 elemento eliminato. - NewPipe è un software libero con licenza copyleft: si può utilizzarlo, studiarlo, condividerlo e migliorarlo a proprio piacimento. In particolare, è possibile ridistribuirlo e/o modificarlo secondo i termini della GNU General Public License pubblicata dalla Free Software Foundation, sia nella versione 3 della Licenza, sia (a propria discrezione) in qualsiasi versione successiva. + NewPipe è un software libero con licenza copyleft: si può utilizzare, studiare, condividere e migliorare a proprio piacimento. In particolare, è possibile ridistribuirlo e/o modificarlo secondo i termini della GNU General Public License (Free Software Foundation), nella versione 3 o successiva, a propria discrezione. Vuoi anche importare le impostazioni? - Informativa sulla privacy + Informativa sulla Privacy Il progetto NewPipe tiene molto alla tua privacy. Perciò, l\'app non raccoglie alcun dato senza il tuo consenso. \nL\'informativa sulla privacy di NewPipe spiega in dettaglio quali dati vengono inviati e memorizzati quando si invia un rapporto sugli arresti anomali. Leggi l\'informativa sulla privacy @@ -405,45 +405,45 @@ Disiscriviti Nuova scheda Scegli scheda - Movimenti per il controllo del volume + Movimenti Controllo Volume Utilizza i movimenti per controllare il volume del riproduttore - Movimenti per la gestione della luminosità + Movimenti Controllo Luminosità Utilizza i movimenti per controllare la luminosità del riproduttore Aggiornamenti File eliminato Notifiche di aggiornamenti dell\'applicazione Notifiche per una nuova versione di NewPipe Archiviazione esterna non disponibile - Impossibile effettuare il download sulla memoria esterna SD. Reimpostare la posizione della cartella di download\? + Impossibile scaricare sulla scheda SD esterna. Ripristinare la cartella dei download\? Utilizzando le schede predefinite, c\'è stato un errore durante la lettura delle schede salvate Ripristina predefiniti Davvero ripristinare i predefiniti\? Contatore degli iscritti non disponibile - Quali schede sono mostrate nella pagina principale + Schede mostrate nella pagina principale Selezione Aggiornamenti Mostra una notifica per suggerire l\'aggiornamento dell\'app se una nuova versione è disponibile Visualizzazione a lista Lista Griglia - Automatico - Cambia vista + Automatica + Cambia Visualizzazione Aggiornamento di NewPipe disponibile! Premi per scaricare Finito - In attesa di + In attesa in pausa in coda post-processo Accoda Azione negata dal sistema Download fallito - Download finito - %s download finiti + Download terminato + %s download terminati Genera un nome unico Sovrascrivi Esiste già un file scaricato con lo stesso nome - C\'è un download in progresso con questo nome + C\'è un download in corso con questo nome Mostra errore Codice Impossibile creare il file @@ -458,16 +458,16 @@ Post-processing fallito Pulisci i download completati Ferma - Tentativi massimi - Tentativi massimi prima di cancellare il download + Numero Massimo Tentativi + Quante volte provare prima di annullare il download Interrompi con le connessioni a consumo Utile quando si passa alla connessione dati mobile, altrimenti alcuni download potrebbero essere sospesi Eventi Conferenze Connesione finita - Mostra commenti + Mostra Commenti Disattiva per non visualizzare i commenti - Riproduzione automatica + Riproduzione Automatica Commenti @@ -475,11 +475,11 @@ Nessun commento Impossibile caricare i commenti Chiudi - Recupera riproduzione + Riprendi la Riproduzione Recupera l\'ultima posizione di riproduzione - Posizioni in lista - Mostra l indicatore di posizione di riproduzione nelle liste - Pulisci dati + Posizioni nelle Liste + Mostra indicatore di posizione di riproduzione nelle liste + Pulisci Dati Posizione di riproduzione eliminata. File spostato o cancellato Esiste già un file con questo nome @@ -489,16 +489,16 @@ Spazio insufficiente sul dispositivo Progresso perso poiché il file è stato eliminato Sei sicuro\? - Un download si avvierà allo stesso tempo + Sarà avviato un solo dowload per volta Avvia downloads Metti in pausa i downloads - Chiedi dove scaricare - Ti sarà chiesto dove salvare i file ogni volta + Chiedi Dove Scaricare + Ogni volta verrà chiesta la destinazione dei file Utilizza SAF - Limite download coda - Ti verrà chiesto dove salvare ogni download. + Limita Coda Download + Ogni volta verrà chiesta la destinazione dei file. \nScegli SAF se vuoi scaricare su una scheda SD esterna - Lo Storage Access Framework permette scaricamenti su una scheda SD esterna. + Lo Storage Access Framework consente di scaricare su una scheda SD esterna. \nNota: alcuni dispositivi non sono compatibili Elimina posizioni di riproduzione Elimina tutte le posizioni di riproduzione @@ -516,5 +516,21 @@ %s ascoltatori La lingua verrà cambiata al riavvio dell\'applicazione. - Pagina predefinita + Contenuti in Evidenza Predefiniti + Durata Avanzamento e Riavvolgimento Rapidi + Istanze PeerTube + Imposta le tue istanze PeerTube preferite + Trova le istanze più adatte a te su https://joinpeertube.org/instances#instances-list + Aggiungi Istanza + Inserisci URL Istanza + Impossibile convalidare l\'istanza + Sono supportati solo gli URL HTTPS + L\'istanza esiste già + Locale + Aggiunti di Recente + Più Piaciuti + Generato Automaticamente (nessun uploader trovato) + recupero + Impossibile recuperare questo download + Scegli un\'Istanza \ No newline at end of file diff --git a/app/src/main/res/values-ku/strings.xml b/app/src/main/res/values-ku/strings.xml index 228849b33..50350e1b3 100644 --- a/app/src/main/res/values-ku/strings.xml +++ b/app/src/main/res/values-ku/strings.xml @@ -1,71 +1,541 @@ - -گرته‌ له‌ گه‌ڕان بكه‌ بۆ ده‌ستپێكردن + + + گرته‌ له‌ گه‌ڕان بكه‌ بۆ ده‌ستپێكردن %1$s بینراو بڵاوكراوه‌ته‌وه‌ له‌ %1$s - هیچ كارپێكه‌رێكی ڤیدیۆیی نه‌دۆزرایه‌وه‌، ده‌ته‌وێت VLC داگریت؟ - هیچ كارپێكه‌رێكی ڤیدیۆییت نییه‌ ده‌توانیت VLC داگریت بۆ لێدان - داگرتن + هیچ كارپێكه‌رێكی ڤیدیۆیی نه‌دۆزرایه‌وه‌. ده‌ته‌وێت VLC داگریت؟ + هیچ کارپێکەرێکی ڤیدیۆ نەدۆزرایەوە (دەتوانی کارپێکەری VLC دامەزرێنی) . + دامەزراندن پاشگه‌زبوونه‌وه‌ كردنه‌وه‌ له‌ وێبگه‌ر - كردنه‌وه‌ له‌ په‌نجه‌ره‌ی بچووك + كردنه‌وه‌ له‌ په‌نجه‌ره‌ی بچووک هاوبه‌شپێكردن داگرتن - .داگرتنی په‌ڕگه‌ + داگرتنی فایلی پەخش گه‌ڕان ڕێكخستنه‌كان - مه‌به‌ستت ئه‌مه‌یه‌: %1$s + مەبەستت ئەمەیە: +\n%1$s\? "هاوبه‌شپێكردن له‌گه‌ڵ " هه‌ڵبژاردنی وێبگه‌ر - سوڕان + لاربوونەوە به‌كارهێنانی كارپێكه‌ری ڤیدیۆی ده‌ره‌كی - هه‌نێ له‌ قه‌باره‌كان ده‌نگیان تێدا نابێت له‌حاڵه‌تی كارا كردنی ئه‌م بژارده‌یه‌ + هه‌نێ له‌ قه‌باره‌كان ده‌نگیان تێدا نابێت به‌كارهێنانی كارپێكه‌ری ده‌نگی ده‌ره‌كی - په‌نجه‌ره‌ی بچووك + په‌نجه‌ره‌ی بچووکی NewPipe به‌شداربوون به‌شداربوویت - به‌شدارنابیت له‌ كه‌ناڵ + به‌شداریت نەما له‌ كه‌ناڵ ناتوانیت گۆڕانكاری له‌م به‌شدارییه‌دا بكه‌یت ناتوانرێت به‌شداریكردنه‌كه‌ نوێبكرێته‌وه‌ پیشاندانی زانیاری - سه‌ره‌كی به‌شدارییه‌كان - نیشانكردنه‌كان - + لیستی کارپێکردنەکان نیشانەکران چی نوێ هه‌یه‌ - - له‌پشته‌وه‌ - په‌نجه‌ره‌ - ناردن بۆ - - شوێنی داگرتنی ڤیدیۆ - شوێنی ڤیدیۆ داگیراوه‌كان - نوسینی شوێنی داگرتنی ڤیدیۆكان - - شوێنی داگرتنی ده‌نگ - شوێنی ده‌نگه‌ داگیراوه‌كان - نوسینی شوێنی داگرتنی ده‌نگه‌كان - + لە پاشبنەما + په‌نجه‌ره‌ی بچووک + زیادکردن بۆ + فۆڵدەری داگرتنی ڤیدیۆ + ڤیدیۆ داگیراوەکان لێرەدا هەڵدەگیرێن + فۆڵدەری داگرتن بۆ ڤیدیۆکان هەڵبژێرە + فۆڵدەری داگرتنی ده‌نگ + دەنگە داگیراوەکان لێرەدا هەڵدەگیرێن + فۆڵدەری داگرتنی دەنگەکان هەڵبژێرە كاركردنی خۆكارانه‌ - قه‌باره‌ی سه‌ره‌كی - قه‌باره‌ی سه‌ره‌كی په‌نجه‌ره‌ + قه‌باره‌ی بنەڕەتی + قه‌باره‌ی بنەڕەتی په‌نجه‌ره‌ی بچووک پیشاندانی قه‌باره‌ی به‌رزتر - چه‌ند مۆبایلێك پشتگیری له‌ قه‌باره‌ی 2K/4K ده‌كه‌ن - كاركردن به‌ Kodi - نه‌رمه‌واڵا نه‌دۆزرایه‌وه‌. دابمه‌زرێت؟ - پیشاندانی بژارده‌ی “كاركردن به‌ Kodi” + تەنها چەند مۆبایلێک پشتگیری کارپێکردنی ڤیدیۆی 2K/4K دەکەن + كارپێكردن به‌ Kodi + ئەپەکە نه‌دۆزرایه‌وه‌. دابمه‌زرێت؟ + بژاردەی ”کارپێکردن بە Kodi“ پیشانبدرێت پیشاندانی بژارده‌ی كارپێكردنی ڤیدیۆ به‌ Kodi ده‌نگ - جۆری سه‌ره‌كی ده‌نگ - جۆری سه‌ره‌كی ڤیدیۆ + جۆری بنەڕەتی ده‌نگ + جۆری بنەڕەتی ڤیدیۆ ڕووكار - ڕووناك - تاریك + سپی + تاریک ڕه‌ش - بیرهاتنه‌وه‌ی شوێن و قه‌باره‌ی په‌نجه‌ره‌ + بیرهاتنه‌وه‌ی شوێن و قه‌باره‌ی په‌نجه‌ره‌ی بچووک بیرهاتنه‌وه‌ی كۆتا قه‌باره‌ و شوێنی په‌نجه‌ره‌ی بچووك باركردنی وێنۆچكه‌كان ناچالاكی بكه‌ بۆ ڕاگرتنی وێنۆچكه‌كان له‌ باركردن و پاشه‌كه‌وتبوون له‌سه‌ر بیرگه‌ی ئامێره‌كه‌ت. \nگۆڕینی ئه‌مه‌ ده‌بێته‌ هۆی سڕینه‌وه‌یان له‌سه‌ر بیرگه‌ی مۆبایله‌كه‌ت. پاشماوه‌ی وێنۆچكه‌كان سڕایه‌وه‌ - + ڤیدیۆ کارپێبکرێ کاتێ NewPipe لە ئەپێکیتر کرایەوە + بەکارهێنانی بەدواگەڕانی ناتەواوی خێرا + خاوێنکردنەوەی پاشماوەی داتا + سڕینەوەی پاشماوەی هەموو داتاکان + پاشماوەی داتاکان سڕانەوە + ڕیزکردنی خۆکاری کارپێکردنی دواتر + کۆنتڕۆڵی کارپێکەر بەجوڵەی پەنجە + جوڵەی پەنجەت لەسەر ڕونما بەکاربهێنە بۆ گۆڕینی ئاستی دەنگ و ڕووناکی + گەڕانی پێشنیارکراوەکان + پیشاندانی پێشنیارەکان لەکاتی گەڕان + مێژووی گەڕان + مێژووی تەماشاکردن + هێشتنەوەی تراکی ڤیدیۆ کارپێکراوەکان + بەردەوام بوونی ڤیدیۆ لەدوای هەبوونی هەر بڕینێک (وەک پەیوەندی تەلەفۆنی) + داگرتن + دواتر + پیشاندانی ’دواتر’ و ڤیدیۆ ’هاوشێوەکان’ + بەستەرەکە پشتگیری نەکراوە + وڵاتی بنەڕەتی + خزمەتگوزاری + کارپێکەری ڤیدیۆ + ڤیدیۆ & دەنگ + مێژوو & پاشماوە + پەنجەرەی بچووک + ڕووکار + هیتر + ڕاستکردنەوە + کارپێکردن لە پاشبنەما + کارپێکردن لە پەنجەرەی بچووک + ڕیزکرا لە کارپێکردن لە پاشبنەما + ڕیزکرا لە کارپێکردن لە پەنجەرەی بچووک + کارپێکردن + ناوەڕۆک + سنوردانانی تەمەن + زیندو + داگرتنەکان + داگرتنەکان + ناتوانرێ سکاڵابکرێ + هەمووی + کەناڵ + لیستی کارپێکردن + بەڵێ + دواتر + ناچالاککراوە + فلتەر + نوێکردنەوە + سڕینەوە + قەبارە دانانەوە + باشترین قەبارە + گەڕانەوە + کارپێکردنی هەمووی + هەمیشە + تەنها ئێستا + فایل + ئاگانامەکانی NewPipe + ئاگانامەکانی NewPipe بۆ پاشبنەما و کارپێکردنەکانی پەنجەرەی بچووک + (نەزانراو) + چەسپاندنی لاربوونەوە + گۆڕین بۆ پاشبنەما + گۆڕین بۆ پەنجەرەی بچووک + گۆڕین بۆ سەرەکی + هێنانەوەی بنکەی زانیاریەکان + دەرکردنی بنکەی زانیارییەکان + لەسەر مێژوو و بەشداربووەکانی ئێستات جێگیردەبێت + خەزنکردنی مێژوو و بەشداربوون و لیستەکان + هەڵەیەک ڕوویدا + کێشە لە هێڵەکەتدا هەیە + ناتوانرێ هەموو وێنۆچکەکان باربکرێن + ناتوانرێ ماڵپەڕ شیبکرێتەوە + ناتوانرێ ماڵپەڕ بەتەواوی شیبکرێتەوە + ناوەڕۆک بوونی نییە + ناتوانرێ لیستی داگرتن دابنرێ + پەخشی ڕاستەوخۆ پشتگیری ناکرێ لەئێستادا + هیچ پەخشێ نەدۆزرایەوە + ناتوانرێ وێنە باربکرێ + ئەپ/ڕووکار ڕاوەستا + ناتوانرێ ئەم پەخشە لێبدرێ + کارپێکەرە ڤیدیۆییە دەرەکییەکان پشتگیری ئەم جۆرە بەستەرانە ناکەن + بەستەر هەڵەیە + هیچ پەخشێکی ڤیدیۆیی نەدۆزرایەوە + پەخشی هیچ دەنگێک نەدۆزرایەوە + ئەو فایلە بوونی نییە یان دەسەڵاتی خوێندنەوە و نوسینی لاوازە + ناوی فایل ناکرێ بەتاڵ بێت + هەڵەیەک ڕوویدا : %1$s + ببوورە، ناتوانرێ ئەوە ڕووبدات. + سکاڵا لەسەر کێشە لەڕێگای ئیمێڵ + ببورە، هەندێ کێشە ڕوویدا. + سکاڵا + زانیاری: + چی ڕوویدا: + لێدوانەکەت (بە ئینگلیزی): + وردەکارییەکان: + وێنۆچکەی پیشاندانی ڤیدیۆ + کارپێکردنی ڤیدیۆ، ماوەی: + وێنۆچکەی کەسی بەرزکەرەوە + بەدڵبوون + بەدڵنەبوون + بەکارهێنانی Tor + سکاڵا لەبوونی کێشە + سکاڵا لەبەکاربەر + هیچ ئەنجامێک نییە + هیچ شتێک لێرەدا نییە + ڕاکێشان بۆ دووبارە داواکردنەوە + ناتوانرێ شوێنی داگرتن دروستبکرێ \'%1$s\' + شوێنی داگرتن دانرا \'%1$s\' + ڤیدیۆ + دەنگ + هەوڵدانەوە + دەسەڵاتی گەیشتن بە بیرگە نەدرا + هەزار + ملیۆن + بلیۆن + هیچ بەشداربوویەک نییە + + %s بەشداربوو + %s بەشداربوون + + هیچ بینراوێک نییە + + %s بینرااو + %s بینراو + + هیچ ڤیدیۆیەک نییە + + ڤیدیۆ + ڤیدیۆکان + + دەستپێکردن + ڕاگرتن + کارپێکردن + دروستکردن + سڕینەوە + سڕینەوەی یەک دانە + سڕینەوەی هەمووی + تاقیکردنەوەی هێڵێک + ڕێپێنەدان + دانانەوەی ناو + ئەرکی نوێ + باشە + ناوی فایل + دابەشکراوەکان + کێشە ڕوویدا + سێرڤەر پشتگیرینەکراوە + فایل بوونی هەیە + داگرتنەکانی NewPipe + گرتەبکە بۆ وردەکاری + تکایە چاوەڕێبکە… + لەبەرگیرایەوە + تکایە فۆڵدەرێک بۆ شوێنی داگرتن دیاریبکە لە ڕێکخستنەکان + ئەم دەسەڵاتە پێویستە بۆ +\nکردنەوەی پەنجەرەی بچووک + reCAPTCHA + reCAPTCHA داواکاری + reCAPTCHA داواکراوە + داگرتن + پیت و ژمارەکان + هێما تایبەتییەکان + دەربارەی NewPipe + ڕێکخستنەکان + دەربارە + © %1$s لەلایەن %2$s لەژێر %3$s + ناتوانرێ مۆڵەت باربکرێ + کردنەوەی ماڵپەڕ + دەربارە + هاوبەشەکان + مۆڵەتەکان + هاوبەشبوون + هەرکاتێ بیرۆکەیەکت هەبوو وەک ; وەرگێڕان، گۆڕینی دیزاین ، سڕینەوەی کۆد ،یان هەر گۆڕانکارییەکیتر ئەوا یارمەتییەکەت لەسەرچاوانمانە. ئێمە هەمیشە دەمانەوێ ئەپەکە زیاتر بەرەوپێش ببەین! + بینین لە GitHub + بەخشین + ئەم ئەپە لەلایەن چەند خۆبەخشێکەوە دروستکراوە کەکاتی خۆیان پێ بەخشیووە تاکو باشترین خزمەتگوزاریت پێشکەش بکەن. هیچ نەبێت بە کڕینی کوپێک قاوە یارمەتی گەشەپێدەرەکانمان بدە بۆ ئەوەی کاتی زیاتر تەرخان بکەین بۆ بەرەوپێشبردنی NewPipe. + پێدانەوە + ماڵپەڕ + سەردانی ماڵپەڕی NewPipe بکە بۆ زانیاری و هەواڵی نوێ. + خوێندنەوەی مۆڵەتنامە + مێژوو + گەڕا + تەماشاکراوە + مێژوو ناچالاکە + مێژوو + مێژوو بەتاڵە + مێژوو سڕایەوە + بابەت سڕایەوە + ئایا دەتەوێ ئەم بابەتە لە مێژووی گەڕان بسڕدرێتەوە؟ + ئایا دەتەوێ ئەم بابەتە لە مێژووی تەماشاکردن بسڕدرێتەوە؟ + ئایا دڵنیای لە سڕینەوەی هەموو بابەتەکان لە مێژوودا؟ + دواین کارپێکراو + زۆرترین کارپێکردن + ناوەڕۆکی پەڕەی سەرەکی + کارپێکەری پەنجەرەی بچووک + لادان + وردەکارییەکان + ڕێکخستنەکانی دەنگ + دەستپێکردنی لێدان لێرەوە + دەستپێکردنی لێدان لە پاشبنەماوە + دەستپێکردنی لێدان لە پەنجەرەی بچووکەوە + بەمزووانە شتێک لێرەدا دەردەکەوێ :D + کارپێکەری ڤیدیۆیی + کارپێکەری پاشبنەما + کارپێکەری پەنجەرەی بچووک + هەمیشە بپرسە + دەستکەوتنی زانیاری… + بارکردنی ناوەڕۆکی داواکراو + لیستی نوێ + سڕینەوە + ناوںْوسینەوە + ناو + زیادکردن بۆ لیست + دانان لەسەر وێنۆچکەی لیست + لیستی نیشانەکراو + لادانی نیشانەکراو + ئەم لیستە بسڕدرێتەوە؟ + لیست دروستکرا + لیست دانرا + وێنۆچکەی لیست گۆڕدرا. + ناتوانی ئەم لیستە بسڕیتەوە. + هیچ ژێرنووسێک نییە + گونجاو بە ڕونما + پڕ بە ڕونما + هێنانەپێش + دانانی خۆکاری + چالاککردنی LeakCanary + سکاڵا لەسەر کێشەکان + سکاڵاکردن لەسەر نەگەیاندنی Rx ی پەسەندنەکرا لە دەرەوەی پارچە یان چالاکی لەدوای پوختەکردن + هێنانەوە/خەزنکردن + هێنانەوە + هێنانەوە لە + خەزنکردن بۆ + دەهێنرێتەوە… + خەزندەکرێ… + هێنانەوەی فایل + خەزنی پێشووتر + ناتوانرێ بەشدارییەکان بهێنرێتەوە + ناتوانرێ بەشدارییەکان خەزن بکرێن + بۆ هێنانەوەی بەشداربوونەکانی یوتوب پێویستە فایلی خەزن بوو بگەڕێنیتەوە: +\n +\n1. ئەم بەستەرە بکەوە: %1$ +\n2. بچۆرەژوورەوە گەر داوای‌ کرد +\n3. داگرتنێک دەست پێدەکات (ئەمە فایلی خەزنکراوە) + هێنانەوەی پەڕەی کەسی SoundCloud بەدانانی بەستەر یاخوود ئایدی: +\n +\n1. دۆخی ”Desktop mode” لە وێبگەرەکەتدا چالاک بکە (ئەم ماڵپەڕە بۆ وێبگەری مۆبایلەکان بەردەست نییە) +\n2. ئەم بەستەرە بکەرەوە : %1$s +\n3. بچۆرە ژوورەوە گەر داواکرا +\n4. بەستەری پەڕەی کەسییەکەت دابنێ. + ئایدییەکەت , soundcloud.com/yourid + ئەوە بزانە ئەم کردارە پێویستی بە هێڵێکی گران هەیە. +\n +\nدەتەوێ بەردەوامبیت؟ + کۆنترۆڵی خێرایی + خێراییەکان + شەپۆلی دەنگ + سڕینەوەی بەستەر (ڕەنگە ببێتە هۆی تێکدان) + هیچ پەخشێک نییە بۆ داگرتن + ژێرنووس + بەهۆی گۆڕانکاری لە شێوەی ژێرنووسکردنەکە. پێویستە ئەپەکە دابخەیت و دیسانەوە بیکەیتەوە. + هیچ ئەپێک دانەمەزراوە بۆ کارپێکردنی ئەم فایلە + سڕینەوەی مێژووی تەماشاکردن + مێژوو دەسڕێتەوە لەگەڵ ڤیدیۆ کارپێکراوەکان و شوێنی لیستە ڤیدیۆییەکان + سڕینەوەی تەواوی مێژووی تەماشاکردن؟ + سڕینەوەی مێژووی گەڕان + مێژووی گەڕانەکانت دەسڕێتەوە + تەواوی گەڕانەکانت بسڕدرێنەوە؟ + مێژووی گەڕانەکانت سڕانەوە. + 1 بابەت سڕایەوە. + ئەم ئەپە سەرچاوە کراوەیە : دەتوانی بەکاریبهێنی، بیخوێنیتەوە و هاوبەشی پێبکەیت و بەرەوپێشی ببەیت. +\nبەتایبەتی دەتوانی دابەشیبکەیتەوە یاخوود بگۆڕیت بەپێی مەرجەکانی GNU مۆڵەتنامەی گشتی وەک ئەپێکی بڵاوی خۆڕایی! + سیاسەتی تایبەتی NewPipe + پڕۆژەی NewPipe زانیارییە تایبەتییەکانت بەوردی دەپارێزێ. هەروەها ئەپەکە هیچ داتایەک بەبێ ئاگاداری تۆ بەکارنابات. +\nسیاسەتی تایبەتی NewPipe بەوردەکاری ڕوونکردنەوەت دەداتێ لەسەر ئەو داتایانەی وەریاندەگرێ و بەکاریاندەبات. + خوێندنەوەی سیاسەتی تایبەتی + کەناڵەکان + لیستی کارپێکردنەکان + تراکەکان + بەکاربەرەکان + بەشدارنەبوون + پەڕەیەکی نوێ + هەڵبژاردنی پەڕە + کۆنترۆڵی دەنگ بەجوڵەی پەنجە + جوڵەی پەنجەت لەسەر ڕونما بەکاربهێنە بۆ گۆڕینی ئاستی دەنگ + کۆنترۆڵی ڕووناکی بەجوڵەی پەنجە + جوڵەی پەنجەت لەسەر ڕونما بەکاربهێنە بۆ گۆڕینی ئاستی ڕووناکی ڕونما + زمانی بنەڕەتی ئەپ + نوێکارییەکان + فایل سڕایەوە + ئاگانامەی نوێکاری ئەپ + ئاگانامەکانی وەشانی نوێی NewPipe + بیرگەی دەرەکی بەردەست نییە + داگرتن لە بیرگەی دەرەکی ناکرێت. +\nشوێنی فۆڵدەری داگرتنەکان دابنرێتەوە؟ + گێڕانەوە بۆ بنەڕەتی + ئایا دەتەوێ بگەڕێنرێتەوە بۆ شێوازی بنەڕەتی؟ + ژمارەی بەشداربووان نادیارە + داگرتنێکیترت هەیە بەهەمان ناو + پیشاندانی کێشە + کۆد + فۆڵدەری مەبەست ناتوانرێ دروست بکرێ + فایل ناتوانرێ دروستبکرێ + ڕێگەپێدان ڕەتکرایەوە لەلایەن سیستەمەوە + پەیوەستبوونی پارێزراو شکستی هێنا + ناتوانرێ ڕاژە بدۆزرێتەوە + ناتوانرێ بە ڕاژەوە پەیوەست بیت + ڕاژەکە هیچ داتایەک نانێرێت + ئەم ڕاژەیە ناتوانێ چەندین داگرتن لەیەک کاتدا بکات + ڕووداوەکان + پیشاندانی لێدوانەکان + ناچالاککردن بۆ پیشان نەدانی لێدوانەکان + کارپێکردنی خۆکاری + + لێدوان + لێدوانەکان + + هیچ لێدوانێک نییە + کارپێکردنەوەی لیست + گێڕانەوەی لیست بۆ شوێنی پێشووتر + شوێنەکان لە لیستدا + سڕینەوەی داتا + مێژووی تەماشاکردن سڕایەوە. + شوێنی کارپێکراوەکان سڕانەوە. + شوێنی فایل گۆڕدراوە یان سڕاوەتەوە + داگرتنێکیتر هەیە بەهەمان ناو + سڕینەوەی شوێنی کارپێکراوەکان + شوێنی هەموو کارپێکراوەکان دەسڕێتەوە + شوێنی هەموو کارپێکراوەکان بسڕدرێتەوە؟ + فۆڵدەری داگرتن بگۆڕە بۆ ئەنجامدانی کاریگەری + خزمەتگوزاری چەسپاو، ئێستا هەڵبژێردراو: + هیچ کەسێک تەماشای ناکات + + %s تەماشا دەکات + %s تەماشا دەکەن + + هیچ کەسێ گوێی لێ ناگرێ + + %s گوێی لێدەگرێ + %s گوێی لێدەگرن + + داواکردنی ناتەواو وا لە کارپێکەرەکە دەکات زۆر بەخێرایی شوێنەکان بگۆڕێت لەگەڵ وردییەکی داشکێنراو + پاشکۆی خۆکاری پەخشێکی بەستراوە لەکاتی کارپێکردنی کۆتا پەخشدا + کۆگای گەڕانی نێوخۆیی + گێڕانەوە لەدۆخی سەرنج + پیشاندانی ڕێنمایی ”داگرتن تا پاشکۆ” + پیشاندانی ڕێنمایی کاتێ لە پاشبنەما یاخوود پەنجەرەی بچووکدا گرتە دەکرێ لەسەر وردەکاری ڤیدیۆیەک + ڕەفتار + پیشاندانی ئەو ڤیدیۆیانەی سنوری تەمەنیان بۆ دانراوە. لە ڕێکخستنەکانەوە ڕێگەی پێدەدرێت. + ناتوانرێ واژووی بەستەری ڤیدیۆ بخوێنرێتەوە + نەگێڕانەوەی کارپێکەر بۆ پێش کێشە ڕوویدا + گێڕانەوەی کارپێکەر بۆکاتی پێش کێشە + هەمان فۆڵدەر بوونی نییە + هەمان فایل/بابەت بوونی نییە + چی:\\nداواکراو:\\nناوەڕۆک:\\nلانگ:\\nخزمەتگوزاری:\\nGMT:\\nکات:\\nپاکێج:\\nوەشان:\\nوەشانی سیستەم: + |(تاقیکاری) داگرتنی خێرا بەبەکارهێنانی Tor بۆ زیادکردنی تایبەتێتی (پشتگیری پەخشە ڕاستەوخۆکان ناکات) . + بەستەر هەڵەیە یاخوود بەئینتەرنێتەوە پەیوەست نەبوویت + هێما ڕێگەپێدراوەکان لە فایلێکی ناویدا + هێما نادروستەکان بەم بەهایە جێگۆڕکێ دەکرێن + هێمای جێگۆڕین + مۆڵەتنامەی ئەپ + ئەپێکی خۆڕایی و کێشی کەم بۆ پەخشی ڕاستەوخۆ لەسەر ئەندرۆید. + مۆڵەتنامەی NewPipe + پەڕەی بەتاڵ + پەڕەی کیۆسک + پەڕەی بەشدارییەکان + پەڕەی نوێترینەکان + پەڕەی کەناڵەکان + هەڵبژاردنی کەناڵ + هیچ کەناڵێکی بەشداری نییە + هەڵبژاردنی کیۆسک + خەزنکرا + هێنرایەوە + فایلی ZIP دروست نییە + ئاگاداربە: ناتوانرێ هەمان فایلەکان بهێنرێنەوە. + ئەمە لەسەر ڕێکخستنەکانی ئێستات جێگیردەبێت. + کیۆسک + پڕبینەرەکان + باشترین 50 + نوێ & چالاک + کارپێکەری پاشبنەما + پەنجەت داگرە بۆ ڕیزنەبوون + ڕیزنەبوون لە پاشبنەما + ڕیزنەبوون لە پەنجەرەی بچووک + کردنەوەی پلیکانە + داخستنی پلیکانە + چاودێری دزەکردنی بیرگە ڕەنگە ببێتە هۆی وەڵامنەدانەوەی لەکاتی گەرمبوون + کرداری ’کردنەوە’ی پێشنیارکراو + کرداری بنەڕەتی لەکاتی کردنەوەی بابەت — %s + ئایا دەتەوێت ڕێکخستنەکانیش بهێنرێنەوە؟ + بۆ جێبەجێکردنی فرمانەکان لەگەڵ یاسای پاراستنی داتای گشتی ئەوروپیدا (GDPR) , ئێمە سەرنجت ڕادەکێشین بۆ سیاسەتە تایبەتییەکانی ئەپەکەمان. تکایە بەئاگادارییەوە بیخوێنەوە. +\nپێویستە قبوڵی بکەیت بۆ ناردنی سکاڵاکانت. + قبوڵکردن + ڕەتکردنەوە + بێ سنوور + سنووری قەبارە لەکاتی بەکارهێنانی داتای مۆبایل + بچوکبوونەوە لەکاتی گۆڕینی ئەپ + کرداری کاتی گۆڕین بۆ ئەپێکیتر لە کارپێکەری ڤیدیۆییەوە — %s + هیچیان + بچوککردنەوە بۆ کارپێکەری پاشبنەما + بچووککردنەوە بۆ پەنجەرەی بچووک + بردنەپێشەوەی خێرا لەکاتی بێدەنگکردن + هەنگاو + ڕێکخستنەوە + پەڕە بنەڕەتییەکان بەکاردەبردرێن, ناتوانرێ پەڕە پاشەکەوتکراوەکان بخوێنرێنەوە + چ پەڕەیەک نیشانبدرێ لە پەڕەی سەرەکی + هەڵبژاردن + نوێکارییەکان + پیشاندانی ئاگانامەیەک بۆ ئامادەبوونی ئەپ لەکاتی بەردەست بوونی وەشانی نوێ + لیستی شێوازی بینین + لیست + چوار خانە + خۆکار + گۆڕینی شێواز + وەشانی نوێی ئەپ بەردەستە! + گرتەبکە بۆ داگرتن + تەواوبوو + لە چاوەڕوانیدایە + ڕاگیراوە + لەڕیزدایە + چارەسەردەکرێت + لە ڕیز + کردار ڕەتکرایەوە لەلایەن سیستەمەوە + داگرتن شکستی هێنا + داگرتن تەواوبوو + %s داگرتن تەواوبوون + دانانی ناوی نوێ + جێگیرکردن + کۆنفرانسەکان + ناتوانرێ لێدوانەکان باربکرێ + پیشاندانی نیشانەکەری شوێنی کارپێکراو لە لیستەکان + فایلێک بەهەمان ناو هەیە + فایلێکی داگیراو بەم ناوەوە هەیە + ناتوانرێ لەسەر ئەو فایلە جێگیربکرێ + زمان دەگۆڕدرێ لەدوای داخستن و پاشان کردنەوەی ئەپ. + کیۆسکی بنەڕەتی + خێرا بردنە پێشەوە\\ گێڕانەوە بۆکاتی سەرەتا + دۆخی PeerTube + ئارەزوومەندییەکانی دۆخی پێرتوبی ڕێکبخە + ئەو دۆخانە بدۆزەرەوە کە لەگەڵ خۆتدا دەگونجێن لە %s + زیادکردنی دۆخ + بەستەری دۆخ دابنێ + ناتوانرێ پشتگیری دۆخەکە بکرێ + تەنها بەستەرەکانی https پشتگیریکراون + هەمان دۆخ کاراکراوە + نەدۆزرایەوە + چارەسەرکردن شکستی هێنا + سڕینەوەی داگرتنە تەواوبووەکان + ڕاوەستان + زیاترین هەوڵدانەکان + زۆرترین ژمارەی هەوڵدان پێش پاشگەزبوونەوە لە داگرتنەکە + ڕاوەستا لەسەر کێشەی هێڵ + بەسوودە بۆ کاتی گۆڕینی هێڵ بۆ داتای مۆبایل, لەگەڵ ئەوەشدا زۆربەی داگرتنەکان ڕاناگرێت + داخستن + NewPipe داخرا لەکاتی کارکردن لەسەر ئەو فایلە + بیرگەی ناوەکیت پڕبووە + کردارەکە شکستی هێنا, چونکە ئەو فایلە سڕاوەتەوە + هێڵی ئینتەرنێت نەما + ئایا دڵنیای؟ + سنوری ڕیزبوونی داگرتنەکان + تەنها یەک داگرتن کاردەکات لەیەک کاتدا + دەستپێکردنەوەی داگرتنەکان + ڕاگرتنی داگرتنەکان + پرسیاربکرێ لەکوێ دابگیرێ + پرسیارت لێ دەکرێت بۆ شوێنی داگرتنی هەر فایلێک + پرسیارت لێ دەکرێت بۆ شوێنی داگرتنی هەر فایلێک +\nدەتوانیت SAF بەکاربهێنیت گەر دەتەوێ لە بیرگەی دەرەکیدا فایلەکان دابگریت + بەکارهێنانی SAF + چوارچێوەی گەیشتن بە بیرگە ڕێگەدەدات بە داگرتنی فایلەکان لە بیرگەی دەرەکیدا. +\nتێبینی: هەندێ لە مۆبایلەکان پشتگیری ناکرێن + ناوخۆ + لەم ماوەیەدا بڵاوکرابێتەوە + زۆرترین بەدڵبوون + خۆکاری دانرا (هیچ بەرزکەرەوەیەک نەدۆزرایەوە) + دەگەڕێنرێتەوە + ناتوانرێ ئەم داگرتنە بهێنرێتەوە + دۆخێک هەڵبژێرە + چالاککردنی وێنۆچکەی ڤیدیۆی داخستنی ڕوونما + کاتێ کارپێکەری پاشبنەما کاردەکات ئەوا وێنۆچکەی ڤیدیۆکە لە ڕوونما داخراوەکەدا نیشاندەدرێت + \ No newline at end of file diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index d874e9b0e..d01647f5d 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -516,4 +516,14 @@ Språk vil ikke bli endret før programmet startes på ny. Forvalgt kiosk + PeerTube-instanser + Lokal + Nylig lagt til + Mest likt + Velg en instans + Tøm nedlastingshistorikk + Slett nedlastede filer + Slettet %1$s nedlastninger + Aktiver videominiatyrbilde med låseskjerm + Når du bruker bakgrunnsspilleren, vises en videominiaturbilde på låseskjermen \ No newline at end of file diff --git a/app/src/main/res/values-oc/strings.xml b/app/src/main/res/values-oc/strings.xml index 0e5b7ccd6..e69e43b44 100644 --- a/app/src/main/res/values-oc/strings.xml +++ b/app/src/main/res/values-oc/strings.xml @@ -1,2 +1,76 @@ - - + + + %1$s vistas + Publicat lo %1$s + Cap de legidor de flus trobat. Volètz installar VLC\? + Cap de legidor de flus trobat (podètz installar VLC per lo legir). + Installar + Anullar + Dobrir dins lo navegador + Dobrir en mòde fenestron + Partejar + Telecargar + Telecargar lo fichièr de flus + Recercar + Paramètres + Voliatz dire: %1$s\? + Partejar amb + Causir un navegador + rotacion + Utilizar un legidor de vidèo extèrne + Mòde fenestron de NewPipe + S\'abonar + Abonat + Anullar abonament + Impossible de cambiar l\'abonament + Impossible d\'actualizar l\'abonament + Afichar las informacions + Principal + Abonaments + Clicatz sul boton de recèrca per començar + Lèva l\'àudio per CÈRTAS resolucions + Utilizar lo legidor àudio extèrne + Abonament a la cadena anullat + Listas de lectura enregistradas + Onglet novèl + Causir un onglet + Çò novèl + Rèireplan + Fenestron + Apondre a + Dorsièr de telecargament de vidèos + Los fichièrs vidèo telecargats son aquí + Causissètz lo dorsièr de telecargament de las vidèos + Dorsièr de telecargament dels àudios + Los fichièrs àudio telecargats son estremats aicí + Causissètz lo dorsièr de telecargament pels àudios + Cambiatz los dorsièrs de telecargament per venga efectiu + Lectura automatica + Legís una vidèo quand NewPIpe es apelat dempuèi una autra aplicacion + Resolucion per defaut + Resolucion per defaut dels fenestrons + Afichar de resolucions mai nautas + Totes los dispositius pòdon pas legir de vidèos 2K/4K + Jogar amb Kodi + Trobam pas l\'aplicacion Kore. La volètz installar\? + Afichar l\'opcion \"Legir amb Kodi\" + Activar la vidèo miniatura sus l\'ecran de blocatge + Afichar una opcion per legir una vidèo dempuèi Kodi + En utilizant lo legidor de rèireplan, una vidèo miniatura s\'aficharà sus l\'ecran de blocatge + Àudio + Format àudio per defaut + Format vidèo per defaut + Tèma + Clar + Escur + Negre + Se remembrar la talha e la posicion del fenestron + Se remembrar las darrièras talha e posicion del fenestron + Utilzar la recèrca rapida inexacta + La recèrca inexacta permet a l\'utilizaire de recercar mai rapidament una posicion amb mens de precision + Durada d\'avançada/reculada rapida + Cargar las miniaturas + Afichar los comentaris + Desactivar per afichar pas mai los comentaris + Apondre la vidèo seguenta dins la coa de lectura + \ No newline at end of file diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 769fa67a6..0da89ad48 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -491,7 +491,7 @@ NewPipe został zamknięty podczas pracy nad plikiem Brak miejsca na urządzeniu Postęp został utracony ze wzgledu na usunięcie pliku - Czy jesteś pewien\? + Czy chcesz wyczyścić historię pobierania lub usunąć wszystkie pobrane pliki\? Ogranicz kolejkę pobierania Tylko jedno pobieranie będzie realizowane jednocześnie Rozpocznij pobieranie @@ -523,4 +523,25 @@ %s słuchaczy Język zmieni się po ponownym uruchomieniu aplikacji. + Krok czasu przewijania + Wystąpienia PeerTube + Wybierz swoje ulubione instancje PeerTube + Znajdź wystąpienia, które najbardziej Ci odpowiadają na %s + Dodaj instancję + Wprowadź adres URL instancji + Nie można sprawdzić poprawności instancji + Obsługiwane są tylko adresy URL HTTPS + Instancja już istnieje + Lokalny + Ostatnio dodane + Ulubione + Generowane automatycznie (nie znaleziono uploadera) + odzyskiwanie + Nie można odzyskać tego pobrania + Wybierz instancję + Włącz miniaturę wideo na ekranie blokady + Podczas korzystania z odtwarzacza w tle na ekranie blokady zostanie wyświetlona miniatura filmu + Wyczyść historię pobierania + Usuń pobrane pliki + Usunięte% 1$s pobrania \ No newline at end of file diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index febc9ef41..45fe51010 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -23,7 +23,7 @@ Noite Formato de áudio padrão Resolução padrão - Excluir + Apagar Não curtidas Curtidas Baixar @@ -134,7 +134,7 @@ abrir em modo popup Popup Segundo plano Lembrar tamanho e posição do popup - Lembrar do último tamanho e posição definido para o popup + Lembra da última posição e o tamanho usado no popup Popup Redimensionando Remove o áudio em ALGUMAS resoluções @@ -256,7 +256,7 @@ abrir em modo popup Sempre Uma vez Alterar orientação - Alterar para segundo plano + Trocar para segundo plano Trocar para popup Trocar para principal Players externos não suportam estes tipos de links @@ -271,7 +271,7 @@ abrir em modo popup Importar base de dados Exportar base de dados Sobrescreve seus dados como históricos e inscrições - Exportar históricos, inscrições e playlists + Exporta históricos, inscrições e playlists Exportado Importado Não há nenhum arquivo ZIP válido @@ -318,7 +318,7 @@ abrir em modo popup Usar pesquisa rápida A pesquisa rápida permite que o player procure resultados mais rapidamente porém com precisão reduzida Adicionar o próximo vídeo à fila automaticamente - Adicionar automaticamente um vídeo relacionado ao último da lista quando a repetição estiver desativada + Adiciona automaticamente um vídeo relacionado ao último da lista quando a repetição estiver desativada Arquivo Pasta não encontrada Origem do arquivo/conteúdo não encontrada @@ -361,7 +361,7 @@ abrir em modo popup Carregar capas Cache de imagens limpo Limpar metadados em cache - Exclui todos os dados de páginas em cache + Apaga todos os dados de páginas em cache Cache de metadados limpo Controles de velocidade de reprodução "Tempo " @@ -377,7 +377,7 @@ abrir em modo popup Altere o tamanho da legenda e o estilo da tela de fundo. É necessário reiniciar o aplicativo para ter efeito. Nenhum player instalado para reproduzir este arquivo Limpar histórico de assistidos - Apaga o histórico de vídeos assistidos e a lista de reprodução + Apaga o histórico de vídeos assistidos e a posição nas reproduções Apagar todo o histórico de assistidos\? Histórico de assistidos limpo. Limpar histórico de pesquisas @@ -485,9 +485,9 @@ abrir em modo popup Retomar a reprodução Retorna para a última posição em reprodução Posições em listas - Mostrar indicadores de posição em listas + Mostra indicadores de posição em listas Limpar dados - Posições de reprodução apagadas. + Posição nas reproduções apagadas. Arquivo movido ou excluído Já existe um arquivo com este nome Não foi possível sobrescrever o arquivo @@ -508,9 +508,9 @@ abrir em modo popup Usar SAF A Estrutura de Acesso ao Armazenamento permite baixar para um cartão SD. \nAviso: alguns dispositivos não são compatíveis - Apagar lista de reprodução - Deletar todo o histórico de reprodução - Deletar todo o histórico de reprodução\? + Limpar posição nas reproduções + Apaga o histórico de posição nas reproduções + Apagar toda posição nas reproduções\? Mude as pastas de download para surtir efeito Alterar serviço, selecionados: Quiosque Padrão @@ -525,4 +525,22 @@ abrir em modo popup %s ouvintes O idioma será atualizado assim que o aplicativo for reiniciado. + Duração do avançar/retroceder rápido + Instâncias PeerTube + Selecione instâncias PeerTube favoritas + Encontre instâncias PeerTube em %s + Adicionar instância + Insira o link aqui + Não foi possível acessá-la + Apenas HTTPS são suportados + Instância já existe + Local + Recentes + Em alta + Gerado automaticamente (sem criador) + recuperando + Não foi possível recuperar o download + Escolha uma instância + Ativar capa do vídeo na tela de bloqueio + Mostra capa do vídeo na tela de bloqueio ao usar player em segundo plano \ No newline at end of file diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index c26c57aad..98b85bcab 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -516,4 +516,22 @@ %s ouvintes O idioma mudará quando a app for reiniciada. + Duração da busca de avanço/retrocesso rápido + Instâncias do PeerTube + Defina as suas instâncias favoritas de PeerTube + Encontre as instâncias que lhe melhor convêm em %s + Adicionar instância + Digite o URL da instância + Falha ao validar a instância + Somente URLs HTTPS são suportada + A instância já existe + Local + Recentemente adicionado + Os mais apreciados + Geração automática (não foi encontrado nenhum enviador) + recuperando + Não é possível recuperar este descarregamento + Escolha uma instância + Ativar miniatura do vídeo no ecrã de bloqueio + Ao usar o reprodutor de fundo, uma miniatura de vídeo será exibida no ecrã de bloqueio \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 9e28d4ff6..1da98cc74 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -265,7 +265,7 @@ Неверная ссылка Видеопотоки не найдены Аудиопотоки не найдены - Пожертвовать + Пожертвование Разработчики NewPipe ценой своего свободного времени делают вашу жизнь чуть удобнее. Отплатите им тем же — наслаждаясь чашечкой кофе, они смогут сделать NewPipe ещё круче. Воздать должное Веб-сайт @@ -326,7 +326,7 @@ Добавлено в плейлист Миниатюра плейлиста изменена Не удалось удалить плейлист - Без титров + Без субтитров Подогнать Заполнить Приблизить @@ -372,9 +372,9 @@ Удалить все загруженные данные веб-страниц При открытии ссылки на контент — %s Нет потоков для загрузки - Титры + Субтитры Приложение для воспроизведения этого файла не установлено - Изменить размер текста и стиль титров. Нужен перезапуск + Изменить размер текста и стиль субтитров. Нужен перезапуск Очистить историю Удалить всю историю просмотров\? История просмотров удалена @@ -492,7 +492,7 @@ NewPipe была закрыта во время работы над файлом Закончилось свободное место на устройстве Прогресс потерян, так как файл был удалён - Вы уверены\? + Действительно удалить историю загрузок и загруженные файлы\? Ограничить очередь загрузки Только одна одновременная загрузка Начать загрузку @@ -522,4 +522,25 @@ %s слушателей Язык будет изменён после перезапуска + Шаг перемотки + Серверы PeerTube + Выберите предпочтительные серверы + Каталог серверов: %s + Новый сервер + URL сервера + Не удалось проверить сервер + Поддерживается только HTTPS + Сервер уже существует + Локальное + Новое + Популярное + Создан автоматически (автор не найден) + восстановление + Не удалось восстановить загрузку + Выберите сервер + Миниатюра на экране блокировки + Показать миниатюру видео на экране блокировки при воспроизведении в фоне + Очистить историю загрузок + Удаление загруженных файлов + Удалено загрузок: %1$s \ No newline at end of file diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 06bb3946c..c6603382d 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -5,7 +5,7 @@ Yayınlanma: %1$s Akış oynatıcısı bulunamadı. VLC\'yi yüklemek ister misiniz\? Yükle - İptal et + Vazgeç Tarayıcıda aç Paylaş İndir @@ -15,7 +15,7 @@ Şununla paylaş Tarayıcı seçin döndürme - Harici video oynatıcı kullanın + Harici video oynatıcı kullan Harici ses oynatıcı kullanın Video indirme dizini İndirilen video dosyaları burada depolanır @@ -29,7 +29,7 @@ Kodi ile oynat Kore uygulaması bulunamadı. Yüklensin mi\? \"Kodi ile oynat\" seçeneğini göster - Kodi ortam merkezi üzerinden video oynatmak için bir seçenek görüntüleyin + Kodi ortam merkezi üzerinden video oynatmak için bir seçenek göster Varsayılan ses formatı Tema Koyu @@ -175,7 +175,7 @@ Arama geçmişi Arama sorgularını yerel olarak saklayın İzleme geçmişi - İzlenen videoların kaydını tutun + İzlenen videoların kaydını tut Odaklanıldığında sürdür Kesintilerden sonra (örneğin telefon çağrısı) oynatmaya devam et Oynatıcı @@ -208,7 +208,7 @@ Öge silindi Bu ögeyi arama geçmişinden silmek istiyor musunuz\? \"Eklemek için basılı tutun\" ipucunu göster - Vidyo ayrıntıları sayfasında arka plan veya açılır pencere düğmesine basıldığında ipucu gösterilir + Video ayrıntıları sayfasında arka plan veya açılır pencere düğmesine basıldığında ipucu göster Arka plan oynatıcısı kuyruğuna eklendi Açılır pencere oynatıcısı kuyruğuna eklendi Tümünü Oynat @@ -484,7 +484,7 @@ Aygıt üzerinde yer yok İlerleme kaybedildi, çünkü dosya silinmiş Bağlantı zaman aşımı - Emin misiniz\? + İndirme geçmişinizi temizlemek veya indirilen tüm dosyaları silmek istiyor musunuz\? İndirme kuyruğunu sınırla Aynı anda yalnızca bir indirme yürütülecek İndirmeleri başlat @@ -517,4 +517,25 @@ %s dinleyici Uygulama yeniden başlatıldıktan sonra dil değişecektir. + Hızlı ileri/geri sarma süresi + PeerTube örnekleri + Favori PeerTube örneklerinizi seçin + %s adresinde size en uygun örnekleri bulun + Örnek ekle + Örnek URL\'sini girin + Örnek doğrulanamadı + Yalnızca HTTPS URL\'leri desteklenmektedir + Örnek zaten var + Yerel + Son eklenen + En çok beğenilen + Otomatik oluşturulan (yükleyen bulunamadı) + kurtarılıyor + Bu indirme kurtarılamıyor + Bir örnek seçin + Kilit ekranı video küçük resmini etkinleştir + Arka plan oynatıcıyı kullanırken kilit ekranında bir video küçük resmi görüntülenecektir + İndirme geçmişini temizle + İndirilen dosyaları sil + %1$s indirme silindi \ No newline at end of file diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index ff9907890..6aea1ad79 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -522,4 +522,10 @@ %s слухачів Мова зміниться після перезапуску програми. + Швидке перемотування + Не вдалося перевірити екземпляр + Оберіть ваш улюблений екземпляр peertube. + Знайдіть екземпляри, які найбільше підходять вам на https://joinpeertube.org/instance#instance-list + Додати екземпляр + Введіть посилання на екземпляр \ No newline at end of file diff --git a/app/src/main/res/values-ur/strings.xml b/app/src/main/res/values-ur/strings.xml index 089b793c8..724c9c3ed 100644 --- a/app/src/main/res/values-ur/strings.xml +++ b/app/src/main/res/values-ur/strings.xml @@ -8,7 +8,7 @@ بانٹیں ڈاؤن لوڈکریں تلاش کریں - کیا آپ کا مطلب تھا: %1$s \? + کیا آپ کا مطلب تھا: s$1%\? انٹرنیٹ میں کھولیں ترتیبات کوئیstream پلیئر نہیں ملا.کیا آپ VLC انسٹال کرنا چاہتے ہیں؟ @@ -159,7 +159,7 @@ ایسی کوئی فائل / مواد کا ذریعہ نہیں فائل موجود نہیں ہے اور نہ ہی اسے پڑھنے یا لکھنے کی اجازت ہے فائل کا نام ضروری ہے - ایک خامی پیش آگئی:٪ 1 $ s + ایک خامی پیش آگئی: s$1% کوئی اسٹریمز ڈاؤن لوڈ کرنے کے لئے دستیاب نہیں معذرت ، ایسا نہیں ہونا چاہئے تھا۔ ای میل کے ذریعے غلطی کی اطلاع دیں @@ -182,8 +182,8 @@ کوئی نتیجہ نہیں یہاں کچھ نہیں مگر اداسی کے دوبارہ ترتیب دینے کیلئے کھینچں - ڈاؤن لوڈ ڈائریکٹری \'٪ 1 $ s\' تشکیل نہیں دے سکتے - ڈاؤن لوڈ ڈائریکٹری \'٪ 1 $ s\' بن گئی + ڈاؤن لوڈ ڈائریکٹری \'s$1%\' تشکیل نہیں دے سکتے + ڈاؤن لوڈ ڈائریکٹری \'s$1%\' بن گئی ویڈیو آڈیو دوبارہ کوشش کریں @@ -193,18 +193,18 @@ بی کوئی صارفین نہیں - % s صارف - % s صارفین + s% صارف + s% صارفین کوئی مناظر نہیں - % s منظر - % s مناظر + s% منظر + s% مناظر ویڈیوز دستیاب نہیں ویڈیوز - + شروع کریں توقف @@ -306,7 +306,7 @@ دراز بند کریں یہاں جلد ہی کچھ نظر آئے گا D D ترجیح \' کھلی \' عمل - مواد کھولنے پر ڈیفالٹ کارروائی -٪ s + مواد کھولنے پر ڈیفالٹ کارروائی — s% ویڈیو پلیئر پس منظر پلیئر پوپ اپ پلیئر @@ -345,16 +345,16 @@ پچھلی برآمد سبسکرپشنز کو درآمد نہیں کیا جاسکا رکنیت برآمد نہیں کر سکا - برآمد فائل کو ڈاؤن لوڈ کرکے YouTube کی رکنیت کو درآمد کریں: -\n -\n1. اس یو آر ایل پر جائیں:٪ 1 $ s -\n2. جب پوچھا جائے تو لاگ ان کریں + برآمد فائل کو ڈاؤن لوڈ کرکے YouTube کی رکنیت کو درآمد کریں: +\n +\n1. اس یو آر ایل پر جائیں:s$1% +\n2. جب پوچھا جائے تو لاگ ان کریں \nA. ڈاؤن لوڈ شروع ہونا چاہئے (یہ برآمد فائل ہے) - URL یا آپ کی ID ٹائپ کرکے ایک SoundCloud پروفائل درآمد کریں: -\n -\n1. ویب براؤزر میں \"ڈیسک ٹاپ موڈ\" کو فعال کریں (سائٹ موبائل آلات کے لئے دستیاب نہیں ہے) -\n2. اس URL پر جائیں: %1 $ s -\n3. پوچھا گیا میں لاگ ان کریں + URL یا آپ کی ID ٹائپ کرکے ایک SoundCloud پروفائل درآمد کریں: +\n +\n1. ویب براؤزر میں \"ڈیسک ٹاپ موڈ\" کو فعال کریں (سائٹ موبائل آلات کے لئے دستیاب نہیں ہے) +\n2. اس URL پر جائیں: s$1% +\n3. پوچھا گیا میں لاگ ان کریں \n4. پروفائل یو آر ایل کاپی کریں جو آپ کو ہدایت کی گئی تھی. yourID، soundcloud.com/yourid یاد رکھیں کہ یہ آپریشن نیٹ ورک مہنگا ہوسکتا ہے۔ @@ -388,7 +388,7 @@ کوئی حد نہیں موبائل ڈیٹا کا استعمال کرتے وقت ریذولوشن کو محدود کریں ایپ سوئچ کو کم سے کم کریں - اہم ویڈیو پلیئر سے دوسرے ایپ میں سوئچنگ کرتے وقت کارروائی-% s + اہم ویڈیو پلیئر سے دوسرے ایپ میں سوئچنگ کرتے وقت کارروائی — %s کوئی نہیں پس منظری پلیر میں کم کریں پاپ اپ پلیر میں کم کریں @@ -437,7 +437,7 @@ سسٹم نےکارروائی سے انکار کیا گیا ڈاؤن لوڈ ناکام ڈاؤن لوڈ تکمیل - ٪ s ڈاؤن لوڈ مکمل ہوگئے + s% ڈاؤن لوڈ مکمل ہوگئے منفرد نام بنائیں برتحریر اس نام کے ساتھ ایک ڈاؤن لوڈ جاری ہے @@ -466,7 +466,7 @@ آٹوپلے تبصرے - + کوئی تبصرہ نہیں تبصرے لوڈ نہیں ہوسکے diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index cc0dbe639..6cb16623f 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -513,4 +513,22 @@ 語言將會在重新啟動應用程式後變更。 + 快轉/快退搜尋持續時間 + PeerTube 站臺 + 選取您最愛的 PeerTube 站臺 + 在 %s 上找到最適合您的站臺 + 新增站臺 + 輸入站臺 URL + 無法驗證站臺 + 僅支援 HTTPS URL + 站臺已存在 + 本機 + 最近新增 + 最喜歡 + 自動生成(未找到上傳者) + 正在恢復 + 無法復原此下載 + 選擇一個站臺 + 啟用鎖定畫面影片縮圖 + 使用背景播放器時,鎖定畫面上將會顯示影片縮圖 \ No newline at end of file diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index 6aaaa0630..4813833d1 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -175,6 +175,7 @@ main_page_content enable_playback_resume enable_playback_state_lists + enable_lock_screen_video_thumbnail import_data export_data diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6021df15e..e1b2cc0a4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -58,7 +58,9 @@ Kore app not found. Install it? org.xbmc.kore Show \"Play with Kodi\" option + Enable lock screen video thumbnail Display an option to play a video via Kodi media center + When using the background player a video thumbnail will be displayed on the lock screen Audio Default audio format Default video format @@ -111,13 +113,13 @@ Service Default content language PeerTube instances - Set your favorite peertube instances + Select your favorite PeerTube instances Find the instances that best suit you on %s https://joinpeertube.org/instances#instances-list Add instance - Enter instance url - Failed to validate instance - Only https urls are supported + Enter instance URL + Could not validate instance + Only HTTPS URLs are supported Instance already exists Player Behavior @@ -567,8 +569,10 @@ Progress lost, because the file was deleted Connection timeout Cannot recover this download - Clear finished downloads - Are you sure? + Clear download history + Do you want to clear your download history or delete all downloaded files? + Delete downloaded files + Deleted %1$s downloads Stop Maximum retries Maximum number of attempts before canceling the download @@ -585,5 +589,4 @@ Use SAF The Storage Access Framework allows downloads to an external SD card.\nNote: some devices are not compatible Choose an instance - diff --git a/app/src/main/res/xml/video_audio_settings.xml b/app/src/main/res/xml/video_audio_settings.xml index 0ff43ce90..d1757919b 100644 --- a/app/src/main/res/xml/video_audio_settings.xml +++ b/app/src/main/res/xml/video_audio_settings.xml @@ -81,6 +81,13 @@ android:summary="@string/show_play_with_kodi_summary" android:title="@string/show_play_with_kodi_title"/> + +