From 23d14ab443695252feab35cfddf6a2e2899930e9 Mon Sep 17 00:00:00 2001 From: TacoTheDank Date: Fri, 21 Jan 2022 16:25:11 -0500 Subject: [PATCH 001/119] Fix some gradle deprecations --- app/build.gradle | 10 +++++----- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 7bac807a3..4cebcb7f5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,14 +8,14 @@ plugins { } android { - compileSdkVersion 30 + compileSdk 30 buildToolsVersion '30.0.3' defaultConfig { applicationId "org.schabi.newpipe" resValue "string", "app_name", "NewPipe" - minSdkVersion 19 - targetSdkVersion 29 + minSdk 19 + targetSdk 29 versionCode 981 versionName "0.21.15" @@ -65,7 +65,7 @@ android { } } - lintOptions { + lint { checkReleaseBuilds false // Or, if you prefer, you can continue to check for errors in release builds, // but continue the build even when errors are found: @@ -98,7 +98,7 @@ android { } ext { - checkstyleVersion = '9.2' + checkstyleVersion = '9.2.1' androidxLifecycleVersion = '2.3.1' androidxRoomVersion = '2.3.0' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0d8da6971..3bb947249 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-all.zip -distributionSha256Sum=b75392c5625a88bccd58a574552a5a323edca82dab5942d2d41097f809c6bcce +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip +distributionSha256Sum=c9490e938b221daf0094982288e4038deed954a3f12fb54cbf270ddf4e37d879 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 3a40759cd2cc062424bb8709f40e9bfa8987bad2 Mon Sep 17 00:00:00 2001 From: vkay94 Date: Sat, 7 Nov 2020 15:29:07 +0100 Subject: [PATCH 002/119] SeekOverlay: Add Views --- .../newpipe/views/player/CircleClipTapView.kt | 106 +++++++ .../newpipe/views/player/PlayerSeekOverlay.kt | 264 ++++++++++++++++++ .../newpipe/views/player/SecondsView.kt | 171 ++++++++++++ .../res/drawable/ic_play_seek_triangle.xml | 11 + .../main/res/layout/player_seek_overlay.xml | 28 ++ .../res/layout/player_seek_seconds_view.xml | 50 ++++ 6 files changed, 630 insertions(+) create mode 100644 app/src/main/java/org/schabi/newpipe/views/player/CircleClipTapView.kt create mode 100644 app/src/main/java/org/schabi/newpipe/views/player/PlayerSeekOverlay.kt create mode 100644 app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt create mode 100644 app/src/main/res/drawable/ic_play_seek_triangle.xml create mode 100644 app/src/main/res/layout/player_seek_overlay.xml create mode 100644 app/src/main/res/layout/player_seek_seconds_view.xml diff --git a/app/src/main/java/org/schabi/newpipe/views/player/CircleClipTapView.kt b/app/src/main/java/org/schabi/newpipe/views/player/CircleClipTapView.kt new file mode 100644 index 000000000..cbb4df738 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/views/player/CircleClipTapView.kt @@ -0,0 +1,106 @@ +package org.schabi.newpipe.views.player + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.Path +import android.util.AttributeSet +import android.view.View +import org.schabi.newpipe.player.event.DisplayPortion + +class CircleClipTapView(context: Context?, attrs: AttributeSet) : View(context, attrs) { + + companion object { + const val COLOR_DARK = 0x40000000 + const val COLOR_DARK_TRANSPARENT = 0x30000000 + const val COLOR_LIGHT_TRANSPARENT = 0x25EEEEEE + + fun calculateArcSize(view: View): Float = view.height / 11.4f + } + + private var backgroundPaint = Paint() + + private var widthPx = 0 + private var heightPx = 0 + + // Background + + private var shapePath = Path() + private var isLeft = true + + init { + requireNotNull(context) { "Context is null." } + + backgroundPaint.apply { + style = Paint.Style.FILL + isAntiAlias = true + color = COLOR_LIGHT_TRANSPARENT + } + + val dm = context.resources.displayMetrics + widthPx = dm.widthPixels + heightPx = dm.heightPixels + + updatePathShape() + } + + var arcSize: Float = 80f + set(value) { + field = value + updatePathShape() + } + + var circleBackgroundColor: Int + get() = backgroundPaint.color + set(value) { + backgroundPaint.color = value + } + + /* + Background + */ + + fun updatePosition(portion: DisplayPortion) { + val newIsLeft = portion == DisplayPortion.LEFT + if (isLeft != newIsLeft) { + isLeft = newIsLeft + updatePathShape() + } + } + + private fun updatePathShape() { + val halfWidth = widthPx * 0.5f + + shapePath.reset() + + val w = if (isLeft) 0f else widthPx.toFloat() + val f = if (isLeft) 1 else -1 + + shapePath.moveTo(w, 0f) + shapePath.lineTo(f * (halfWidth - arcSize) + w, 0f) + shapePath.quadTo( + f * (halfWidth + arcSize) + w, + heightPx.toFloat() / 2, + f * (halfWidth - arcSize) + w, + heightPx.toFloat() + ) + shapePath.lineTo(w, heightPx.toFloat()) + + shapePath.close() + invalidate() + } + + override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { + super.onSizeChanged(w, h, oldw, oldh) + widthPx = w + heightPx = h + updatePathShape() + } + + override fun onDraw(canvas: Canvas?) { + super.onDraw(canvas) + + canvas?.clipPath(shapePath) + canvas?.drawPath(shapePath, backgroundPaint) + } +} diff --git a/app/src/main/java/org/schabi/newpipe/views/player/PlayerSeekOverlay.kt b/app/src/main/java/org/schabi/newpipe/views/player/PlayerSeekOverlay.kt new file mode 100644 index 000000000..5bdf0c97b --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/views/player/PlayerSeekOverlay.kt @@ -0,0 +1,264 @@ +package org.schabi.newpipe.views.player + +import android.content.Context +import android.util.AttributeSet +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import androidx.annotation.* +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.constraintlayout.widget.ConstraintSet +import androidx.constraintlayout.widget.ConstraintSet.* +import androidx.core.content.ContextCompat +import androidx.core.widget.TextViewCompat +import androidx.preference.PreferenceManager +import kotlinx.android.synthetic.main.player_seek_overlay.view.* +import org.schabi.newpipe.MainActivity +import org.schabi.newpipe.R +import org.schabi.newpipe.player.event.DisplayPortion +import org.schabi.newpipe.player.event.DoubleTapListener + +class PlayerSeekOverlay(context: Context?, private val attrs: AttributeSet?) : + ConstraintLayout(context, attrs), DoubleTapListener { + + private var secondsView: SecondsView + private var circleClipTapView: CircleClipTapView + + private var isForwarding: Boolean? = null + + init { + LayoutInflater.from(context).inflate(R.layout.player_seek_overlay, this, true) + + secondsView = findViewById(R.id.seconds_view) + circleClipTapView = findViewById(R.id.circle_clip_tap_view) + + initializeAttributes() + secondsView.isForward = true + isForwarding = null + changeConstraints(true) + } + + private fun initializeAttributes() { + circleBackgroundColorInt(CircleClipTapView.COLOR_LIGHT_TRANSPARENT) + iconAnimationDuration(SecondsView.ICON_ANIMATION_DURATION) + icon(R.drawable.ic_play_seek_triangle) + + val prefs = PreferenceManager.getDefaultSharedPreferences(context) + val durationKey = context.getString(R.string.seek_duration_key) + val seekValue = prefs.getString( + durationKey, context.getString(R.string.seek_duration_default_value) + ) + seekSeconds(seekValue?.toInt()?.div(1000) ?: 10) + } + + private var performListener: PerformListener? = null + + fun performListener(listener: PerformListener) = apply { + performListener = listener + } + + var seekSeconds: Int = 0 + private set + + fun seekSeconds(seconds: Int) = apply { + seekSeconds = seconds + } + + var circleBackgroundColor: Int + get() = circleClipTapView.circleBackgroundColor + private set(value) { + circleClipTapView.circleBackgroundColor = value + } + + fun circleBackgroundColorRes(@ColorRes resId: Int) = apply { + circleBackgroundColor = ContextCompat.getColor(context, resId) + } + + fun circleBackgroundColorInt(@ColorInt color: Int) = apply { + circleBackgroundColor = color + } + + var arcSize: Float + get() = circleClipTapView.arcSize + internal set(value) { + circleClipTapView.arcSize = value + } + + fun arcSize(@DimenRes resId: Int) = apply { + arcSize = context.resources.getDimension(resId) + } + + fun arcSize(px: Float) = apply { + arcSize = px + } + + var showCircle: Boolean = true + private set(value) { + circleClipTapView.visibility = if (value) View.VISIBLE else View.GONE + field = value + } + + fun showCircle(show: Boolean) = apply { + showCircle = show + } + + var iconAnimationDuration: Long = SecondsView.ICON_ANIMATION_DURATION + get() = secondsView.cycleDuration + private set(value) { + secondsView.cycleDuration = value + field = value + } + + fun iconAnimationDuration(duration: Long) = apply { + iconAnimationDuration = duration + } + + @DrawableRes + var icon: Int = 0 + get() = secondsView.icon + private set(value) { + secondsView.stop() + secondsView.icon = value + field = value + } + + fun icon(@DrawableRes resId: Int) = apply { + icon = resId + } + + @StyleRes + var textAppearance: Int = 0 + private set(value) { + TextViewCompat.setTextAppearance(secondsView.textView, value) + field = value + } + + fun textAppearance(@StyleRes resId: Int) = apply { + textAppearance = resId + } + + // Indicates whether this (double) tap is the first of a series + // Decides whether to call performListener.onAnimationStart or not + private var initTap: Boolean = false + + override fun onDoubleTapStarted(portion: DisplayPortion) { + if (DEBUG) + Log.d(TAG, "onDoubleTapStarted called with portion = [$portion]") + + initTap = false + performListener?.onPrepare() + + changeConstraints(secondsView.isForward) + if (showCircle) circleClipTapView.updatePosition(portion) + + isForwarding = null + + if (this.alpha == 0f) + secondsView.stop() + } + + override fun onDoubleTapProgressDown(portion: DisplayPortion) { + val shouldForward: Boolean = performListener?.shouldFastForward(portion) ?: return + + if (DEBUG) + Log.d(TAG,"onDoubleTapProgressDown called with " + + "shouldForward = [$shouldForward], " + + "isForwarding = [$isForwarding], " + + "secondsView#isForward = [${secondsView.isForward}], " + + "initTap = [$initTap], ") + + // Using this check prevents from fast switching (one touches) + if (isForwarding != null && isForwarding != shouldForward) { + isForwarding = shouldForward + return + } + isForwarding = shouldForward + + if (this.visibility != View.VISIBLE || !initTap) { + if (!initTap) { + secondsView.seconds = 0 + performListener?.onAnimationStart() + secondsView.start() + initTap = true + } + } + + if (shouldForward) + forwarding() + else + rewinding() + } + + override fun onDoubleTapFinished() { + if (DEBUG) + Log.d(TAG, "onDoubleTapFinished called with initTap = [$initTap]") + + if (initTap) performListener?.onAnimationEnd() + initTap = false + } + + private fun forwarding() { + if (DEBUG) + Log.d(TAG, "forwarding called") + + // First time tap or switched + if (!secondsView.isForward) { + changeConstraints(true) + if (showCircle) circleClipTapView.updatePosition(DisplayPortion.RIGHT) + secondsView.apply { + isForward = true + seconds = 0 + } + } + secondsView.seconds += seekSeconds + performListener?.seek(forward = true) + } + + private fun rewinding() { + if (DEBUG) + Log.d(TAG, "rewinding called") + + // First time tap or switched + if (secondsView.isForward) { + changeConstraints(false) + if (showCircle) circleClipTapView.updatePosition(DisplayPortion.LEFT) + secondsView.apply { + isForward = false + seconds = 0 + } + } + secondsView.seconds += seekSeconds + performListener?.seek(forward = false) + } + + private fun changeConstraints(forward: Boolean) { + val constraintSet = ConstraintSet() + with(constraintSet) { + clone(root_constraint_layout) + if (forward) { + clear(seconds_view.id, START) + connect(seconds_view.id, END, + PARENT_ID, END) + } else { + clear(seconds_view.id, END) + connect(seconds_view.id, START, + PARENT_ID, START) + } + secondsView.start() + applyTo(root_constraint_layout) + } + } + + interface PerformListener { + fun onPrepare() {} + fun onAnimationStart() + fun onAnimationEnd() + fun shouldFastForward(portion: DisplayPortion): Boolean? + fun seek(forward: Boolean) + } + + companion object { + private const val TAG = "PlayerSeekOverlay" + private val DEBUG = MainActivity.DEBUG + } +} diff --git a/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt b/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt new file mode 100644 index 000000000..30bfe1217 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt @@ -0,0 +1,171 @@ +package org.schabi.newpipe.views.player + +import android.animation.Animator +import android.animation.ValueAnimator +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.TextView +import androidx.annotation.DrawableRes +import androidx.constraintlayout.widget.ConstraintLayout +import kotlinx.android.synthetic.main.player_seek_seconds_view.view.* +import org.schabi.newpipe.R + +class SecondsView(context: Context?, attrs: AttributeSet?) : + ConstraintLayout(context, attrs) { + + companion object { + const val ICON_ANIMATION_DURATION = 750L + } + + var cycleDuration: Long = ICON_ANIMATION_DURATION + set(value) { + firstAnimator.duration = value / 5 + secondAnimator.duration = value / 5 + thirdAnimator.duration = value / 5 + fourthAnimator.duration = value / 5 + fifthAnimator.duration = value / 5 + field = value + } + + var seconds: Int = 0 + set(value) { + tv_seconds.text = context.resources.getQuantityString( + R.plurals.seconds, value, value + ) + field = value + } + + var isForward: Boolean = true + set(value) { + triangle_container.rotation = if (value) 0f else 180f + field = value + } + + val textView: TextView + get() = tv_seconds + + + @DrawableRes + var icon: Int = R.drawable.ic_play_seek_triangle + set(value) { + if (value > 0) { + icon_1.setImageResource(value) + icon_2.setImageResource(value) + icon_3.setImageResource(value) + } + field = value + } + + init { + LayoutInflater.from(context).inflate(R.layout.player_seek_seconds_view, this, true) + } + + fun start() { + stop() + firstAnimator.start() + } + + fun stop() { + firstAnimator.cancel() + secondAnimator.cancel() + thirdAnimator.cancel() + fourthAnimator.cancel() + fifthAnimator.cancel() + + reset() + } + + private fun reset() { + icon_1.alpha = 0f + icon_2.alpha = 0f + icon_3.alpha = 0f + } + + private val firstAnimator: ValueAnimator = CustomValueAnimator( + { + icon_1.alpha = 0f + icon_2.alpha = 0f + icon_3.alpha = 0f + }, { + icon_1.alpha = it + }, { + secondAnimator.start() + } + ) + + private val secondAnimator: ValueAnimator = CustomValueAnimator( + { + icon_1.alpha = 1f + icon_2.alpha = 0f + icon_3.alpha = 0f + }, { + icon_2.alpha = it + }, { + thirdAnimator.start() + } + ) + + private val thirdAnimator: ValueAnimator = CustomValueAnimator( + { + icon_1.alpha = 1f + icon_2.alpha = 1f + icon_3.alpha = 0f + }, { + icon_1.alpha = 1f - icon_3.alpha + icon_3.alpha = it + }, { + fourthAnimator.start() + } + ) + + private val fourthAnimator: ValueAnimator = CustomValueAnimator( + { + icon_1.alpha = 0f + icon_2.alpha = 1f + icon_3.alpha = 1f + }, { + icon_2.alpha = 1f - it + }, { + fifthAnimator.start() + } + ) + + private val fifthAnimator: ValueAnimator = CustomValueAnimator( + { + icon_1.alpha = 0f + icon_2.alpha = 0f + icon_3.alpha = 1f + }, { + icon_3.alpha = 1f - it + }, { + firstAnimator.start() + } + ) + + private inner class CustomValueAnimator( + start: () -> Unit, update: (value: Float) -> Unit, end: () -> Unit + ): ValueAnimator() { + + init { + duration = cycleDuration / 5 + setFloatValues(0f, 1f) + + addUpdateListener { update(it.animatedValue as Float) } + addListener(object : AnimatorListener { + override fun onAnimationStart(animation: Animator?) { + start() + } + + override fun onAnimationEnd(animation: Animator?) { + end() + } + + override fun onAnimationCancel(animation: Animator?) = Unit + + override fun onAnimationRepeat(animation: Animator?) = Unit + + }) + } + } +} diff --git a/app/src/main/res/drawable/ic_play_seek_triangle.xml b/app/src/main/res/drawable/ic_play_seek_triangle.xml new file mode 100644 index 000000000..1aee026db --- /dev/null +++ b/app/src/main/res/drawable/ic_play_seek_triangle.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/src/main/res/layout/player_seek_overlay.xml b/app/src/main/res/layout/player_seek_overlay.xml new file mode 100644 index 000000000..f4e9f1707 --- /dev/null +++ b/app/src/main/res/layout/player_seek_overlay.xml @@ -0,0 +1,28 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/player_seek_seconds_view.xml b/app/src/main/res/layout/player_seek_seconds_view.xml new file mode 100644 index 000000000..14c9eaa2d --- /dev/null +++ b/app/src/main/res/layout/player_seek_seconds_view.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + From 72eb3b441596f93f7f1f14bdc7e98c296d4ef726 Mon Sep 17 00:00:00 2001 From: vkay94 Date: Mon, 18 Jan 2021 19:56:08 +0100 Subject: [PATCH 003/119] SeekOverlay: Add seek overlay logic to player --- .../main/java/org/schabi/newpipe/ktx/View.kt | 11 +- .../org/schabi/newpipe/player/Player.java | 121 +++++++++++++++--- .../player/event/PlayerGestureListener.java | 7 +- .../newpipe/views/player/CircleClipTapView.kt | 2 +- .../newpipe/views/player/PlayerSeekOverlay.kt | 48 ++++--- .../newpipe/views/player/SecondsView.kt | 40 +++--- app/src/main/res/layout-large-land/player.xml | 17 ++- app/src/main/res/layout/player.xml | 17 ++- 8 files changed, 206 insertions(+), 57 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/ktx/View.kt b/app/src/main/java/org/schabi/newpipe/ktx/View.kt index a1a96b20d..5adb4e3ef 100644 --- a/app/src/main/java/org/schabi/newpipe/ktx/View.kt +++ b/app/src/main/java/org/schabi/newpipe/ktx/View.kt @@ -54,7 +54,7 @@ fun View.animate( ) Log.d(TAG, "animate(): $msg") } - if (isVisible && enterOrExit) { + if (isVisible && enterOrExit && alpha == 1f && animationType == AnimationType.ALPHA) { if (MainActivity.DEBUG) { Log.d(TAG, "animate(): view was already visible > view = [$this]") } @@ -75,8 +75,15 @@ fun View.animate( } animate().setListener(null).cancel() isVisible = true + + val alphaRelativeDuration = if (enterOrExit && alpha < 1.0f) { + (duration * (1 - alpha)).toLong() + } else { + (duration * alpha).toLong() + } + when (animationType) { - AnimationType.ALPHA -> animateAlpha(enterOrExit, duration, delay, execOnEnd) + AnimationType.ALPHA -> animateAlpha(enterOrExit, alphaRelativeDuration, delay, execOnEnd) AnimationType.SCALE_AND_ALPHA -> animateScaleAndAlpha(enterOrExit, duration, delay, execOnEnd) AnimationType.LIGHT_SCALE_AND_ALPHA -> animateLightScaleAndAlpha(enterOrExit, duration, delay, execOnEnd) AnimationType.SLIDE_AND_ALPHA -> animateSlideAndAlpha(enterOrExit, duration, delay, execOnEnd) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 81ef25db1..de8bffaf7 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -136,6 +136,7 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.squareup.picasso.Picasso; import com.squareup.picasso.Target; +import org.jetbrains.annotations.NotNull; import org.schabi.newpipe.DownloaderImpl; import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; @@ -154,6 +155,7 @@ import org.schabi.newpipe.info_list.StreamSegmentAdapter; import org.schabi.newpipe.ktx.AnimationType; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.player.MainPlayer.PlayerType; +import org.schabi.newpipe.player.event.DisplayPortion; import org.schabi.newpipe.player.event.PlayerEventListener; import org.schabi.newpipe.player.event.PlayerGestureListener; import org.schabi.newpipe.player.event.PlayerServiceEventListener; @@ -188,6 +190,8 @@ import org.schabi.newpipe.util.StreamTypeUtil; import org.schabi.newpipe.util.external_communication.KoreUtils; import org.schabi.newpipe.util.external_communication.ShareUtils; import org.schabi.newpipe.views.ExpandableSurfaceView; +import org.schabi.newpipe.views.player.CircleClipTapView; +import org.schabi.newpipe.views.player.PlayerSeekOverlay; import java.io.IOException; import java.util.ArrayList; @@ -365,6 +369,7 @@ public final class Player implements private int maxGestureLength; // scaled private GestureDetectorCompat gestureDetector; + private PlayerGestureListener playerGestureListener; /*////////////////////////////////////////////////////////////////////////// // Listeners and disposables @@ -525,9 +530,10 @@ public final class Player implements binding.resizeTextView.setOnClickListener(this); binding.playbackLiveSync.setOnClickListener(this); - final PlayerGestureListener listener = new PlayerGestureListener(this, service); - gestureDetector = new GestureDetectorCompat(context, listener); - binding.getRoot().setOnTouchListener(listener); + playerGestureListener = new PlayerGestureListener(this, service); + gestureDetector = new GestureDetectorCompat(context, playerGestureListener); + binding.getRoot().setOnTouchListener(playerGestureListener); + setupPlayerSeekOverlay(); binding.queueButton.setOnClickListener(this); binding.segmentsButton.setOnClickListener(this); @@ -578,6 +584,83 @@ public final class Player implements v.getPaddingRight(), v.getPaddingBottom())); } + + private void setupPlayerSeekOverlay() { + final int fadeDurations = 450; + binding.seekOverlay.showCircle(true) + .circleBackgroundColorInt(CircleClipTapView.COLOR_DARK_TRANSPARENT) + .seekSeconds(retrieveSeekDurationFromPreferences(this) / 1000) + .performListener(new PlayerSeekOverlay.PerformListener() { + + @Override + public void onPrepare() { + if (invalidSeekConditions()) { + playerGestureListener.endMultiDoubleTap(); + return; + } + binding.seekOverlay.arcSize( + CircleClipTapView.Companion.calculateArcSize(getSurfaceView()) + ); + } + + @Override + public void onAnimationStart() { + animate(binding.seekOverlay, true, fadeDurations); + animate(binding.playbackControlsShadow, + !simpleExoPlayer.getPlayWhenReady(), fadeDurations); + animate(binding.playerTopShadow, false, fadeDurations); + animate(binding.playerBottomShadow, false, fadeDurations); + animate(binding.playbackControlRoot, false, fadeDurations); + hideSystemUIIfNeeded(); + } + + @Override + public void onAnimationEnd() { + animate(binding.seekOverlay, false, fadeDurations); + if (!simpleExoPlayer.getPlayWhenReady()) { + showControls(fadeDurations); + } else { + showHideShadow(false, fadeDurations); + } + } + + @Override + public Boolean shouldFastForward(@NotNull final DisplayPortion portion) { + // Null indicates an invalid area or condition e.g. the middle portion + // or video start or end was reached during double tap seeking + if (invalidSeekConditions()) { + return null; + } + if (portion == DisplayPortion.LEFT + // Small puffer to eliminate infinite rewind seeking + && simpleExoPlayer.getCurrentPosition() > 500L) { + return false; + } else if (portion == DisplayPortion.RIGHT) { + return true; + } else /* portion == DisplayPortion.MIDDLE */ { + return null; + } + } + + @Override + public void seek(final boolean forward) { + playerGestureListener.keepInDoubleTapMode(); + if (forward) { + fastForward(); + } else { + fastRewind(); + } + } + + private boolean invalidSeekConditions() { + return simpleExoPlayer.getCurrentPosition() == simpleExoPlayer.getDuration() + || currentState == STATE_COMPLETED + || !isPrepared; + } + }); + playerGestureListener.doubleTapControls(binding.seekOverlay); + } + //endregion @@ -1905,6 +1988,7 @@ public final class Player implements } private void showHideShadow(final boolean show, final long duration) { + animate(binding.playbackControlsShadow, show, duration, AnimationType.ALPHA, 0, null); animate(binding.playerTopShadow, show, duration, AnimationType.ALPHA, 0, null); animate(binding.playerBottomShadow, show, duration, AnimationType.ALPHA, 0, null); } @@ -2179,18 +2263,21 @@ public final class Player implements stopProgressLoop(); } - showControls(400); - binding.loadingPanel.setVisibility(View.GONE); - - animate(binding.playPauseButton, false, 80, AnimationType.SCALE_AND_ALPHA, 0, - () -> { - binding.playPauseButton.setImageResource(R.drawable.ic_play_arrow); - animatePlayButtons(true, 200); - if (!isQueueVisible) { - binding.playPauseButton.requestFocus(); - } - }); + // Don't let UI elements popup during double tap seeking. This state is entered sometimes + // during seeking/loading. This if-else check ensures that the controls aren't popping up. + if (!playerGestureListener.isDoubleTapping()) { + showControls(400); + binding.loadingPanel.setVisibility(View.GONE); + animate(binding.playPauseButton, false, 80, AnimationType.SCALE_AND_ALPHA, 0, + () -> { + binding.playPauseButton.setImageResource(R.drawable.ic_play_arrow); + animatePlayButtons(true, 200); + if (!isQueueVisible) { + binding.playPauseButton.requestFocus(); + } + }); + } changePopupWindowFlags(IDLE_WINDOW_FLAGS); // Remove running notification when user does not want minimization to background or popup @@ -2838,7 +2925,6 @@ public final class Player implements } seekBy(retrieveSeekDurationFromPreferences(this)); triggerProgressUpdate(); - showAndAnimateControl(R.drawable.ic_fast_forward, true); } public void fastRewind() { @@ -2847,7 +2933,6 @@ public final class Player implements } seekBy(-retrieveSeekDurationFromPreferences(this)); triggerProgressUpdate(); - showAndAnimateControl(R.drawable.ic_fast_rewind, true); } //endregion @@ -4279,6 +4364,10 @@ public final class Player implements return binding.currentDisplaySeek; } + public PlayerSeekOverlay getSeekOverlay() { + return binding.seekOverlay; + } + @Nullable public WindowManager.LayoutParams getPopupLayoutParams() { return popupLayoutParams; diff --git a/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java b/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java index 25ace1c05..b215584e8 100644 --- a/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java +++ b/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java @@ -55,12 +55,10 @@ public class PlayerGestureListener player.hideControls(0, 0); } - if (portion == DisplayPortion.LEFT) { - player.fastRewind(); + if (portion == DisplayPortion.LEFT || portion == DisplayPortion.RIGHT) { + startMultiDoubleTap(event); } else if (portion == DisplayPortion.MIDDLE) { player.playPause(); - } else if (portion == DisplayPortion.RIGHT) { - player.fastForward(); } } @@ -236,6 +234,7 @@ public class PlayerGestureListener player.getLoadingPanel().setVisibility(View.GONE); player.hideControls(0, 0); + animate(player.getSeekOverlay(), false, 0); animate(player.getCurrentDisplaySeek(), false, 0, ALPHA, 0); } diff --git a/app/src/main/java/org/schabi/newpipe/views/player/CircleClipTapView.kt b/app/src/main/java/org/schabi/newpipe/views/player/CircleClipTapView.kt index cbb4df738..6b22538e0 100644 --- a/app/src/main/java/org/schabi/newpipe/views/player/CircleClipTapView.kt +++ b/app/src/main/java/org/schabi/newpipe/views/player/CircleClipTapView.kt @@ -11,7 +11,7 @@ import org.schabi.newpipe.player.event.DisplayPortion class CircleClipTapView(context: Context?, attrs: AttributeSet) : View(context, attrs) { companion object { - const val COLOR_DARK = 0x40000000 + const val COLOR_DARK = 0x45000000 const val COLOR_DARK_TRANSPARENT = 0x30000000 const val COLOR_LIGHT_TRANSPARENT = 0x25EEEEEE diff --git a/app/src/main/java/org/schabi/newpipe/views/player/PlayerSeekOverlay.kt b/app/src/main/java/org/schabi/newpipe/views/player/PlayerSeekOverlay.kt index 5bdf0c97b..d61989d92 100644 --- a/app/src/main/java/org/schabi/newpipe/views/player/PlayerSeekOverlay.kt +++ b/app/src/main/java/org/schabi/newpipe/views/player/PlayerSeekOverlay.kt @@ -5,24 +5,30 @@ import android.util.AttributeSet import android.util.Log import android.view.LayoutInflater import android.view.View -import androidx.annotation.* +import androidx.annotation.ColorInt +import androidx.annotation.ColorRes +import androidx.annotation.DimenRes +import androidx.annotation.DrawableRes +import androidx.annotation.StyleRes import androidx.constraintlayout.widget.ConstraintLayout +import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.END +import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.PARENT_ID +import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.START import androidx.constraintlayout.widget.ConstraintSet -import androidx.constraintlayout.widget.ConstraintSet.* import androidx.core.content.ContextCompat import androidx.core.widget.TextViewCompat import androidx.preference.PreferenceManager -import kotlinx.android.synthetic.main.player_seek_overlay.view.* import org.schabi.newpipe.MainActivity import org.schabi.newpipe.R import org.schabi.newpipe.player.event.DisplayPortion import org.schabi.newpipe.player.event.DoubleTapListener -class PlayerSeekOverlay(context: Context?, private val attrs: AttributeSet?) : +class PlayerSeekOverlay(context: Context, private val attrs: AttributeSet?) : ConstraintLayout(context, attrs), DoubleTapListener { private var secondsView: SecondsView private var circleClipTapView: CircleClipTapView + private var rootConstraintLayout: ConstraintLayout private var isForwarding: Boolean? = null @@ -31,6 +37,7 @@ class PlayerSeekOverlay(context: Context?, private val attrs: AttributeSet?) : secondsView = findViewById(R.id.seconds_view) circleClipTapView = findViewById(R.id.circle_clip_tap_view) + rootConstraintLayout = findViewById(R.id.root_constraint_layout) initializeAttributes() secondsView.isForward = true @@ -161,11 +168,14 @@ class PlayerSeekOverlay(context: Context?, private val attrs: AttributeSet?) : val shouldForward: Boolean = performListener?.shouldFastForward(portion) ?: return if (DEBUG) - Log.d(TAG,"onDoubleTapProgressDown called with " + - "shouldForward = [$shouldForward], " + - "isForwarding = [$isForwarding], " + - "secondsView#isForward = [${secondsView.isForward}], " + - "initTap = [$initTap], ") + Log.d( + TAG, + "onDoubleTapProgressDown called with " + + "shouldForward = [$shouldForward], " + + "isForwarding = [$isForwarding], " + + "secondsView#isForward = [${secondsView.isForward}], " + + "initTap = [$initTap], " + ) // Using this check prevents from fast switching (one touches) if (isForwarding != null && isForwarding != shouldForward) { @@ -234,18 +244,22 @@ class PlayerSeekOverlay(context: Context?, private val attrs: AttributeSet?) : private fun changeConstraints(forward: Boolean) { val constraintSet = ConstraintSet() with(constraintSet) { - clone(root_constraint_layout) + clone(rootConstraintLayout) if (forward) { - clear(seconds_view.id, START) - connect(seconds_view.id, END, - PARENT_ID, END) + clear(secondsView.id, START) + connect( + secondsView.id, END, + PARENT_ID, END + ) } else { - clear(seconds_view.id, END) - connect(seconds_view.id, START, - PARENT_ID, START) + clear(secondsView.id, END) + connect( + secondsView.id, START, + PARENT_ID, START + ) } secondsView.start() - applyTo(root_constraint_layout) + applyTo(rootConstraintLayout) } } diff --git a/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt b/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt index 30bfe1217..fa2dbd63e 100644 --- a/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt +++ b/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt @@ -11,7 +11,7 @@ import androidx.constraintlayout.widget.ConstraintLayout import kotlinx.android.synthetic.main.player_seek_seconds_view.view.* import org.schabi.newpipe.R -class SecondsView(context: Context?, attrs: AttributeSet?) : +class SecondsView(context: Context, attrs: AttributeSet?) : ConstraintLayout(context, attrs) { companion object { @@ -45,7 +45,6 @@ class SecondsView(context: Context?, attrs: AttributeSet?) : val textView: TextView get() = tv_seconds - @DrawableRes var icon: Int = R.drawable.ic_play_seek_triangle set(value) { @@ -87,9 +86,11 @@ class SecondsView(context: Context?, attrs: AttributeSet?) : icon_1.alpha = 0f icon_2.alpha = 0f icon_3.alpha = 0f - }, { + }, + { icon_1.alpha = it - }, { + }, + { secondAnimator.start() } ) @@ -99,9 +100,11 @@ class SecondsView(context: Context?, attrs: AttributeSet?) : icon_1.alpha = 1f icon_2.alpha = 0f icon_3.alpha = 0f - }, { + }, + { icon_2.alpha = it - }, { + }, + { thirdAnimator.start() } ) @@ -111,10 +114,12 @@ class SecondsView(context: Context?, attrs: AttributeSet?) : icon_1.alpha = 1f icon_2.alpha = 1f icon_3.alpha = 0f - }, { + }, + { icon_1.alpha = 1f - icon_3.alpha icon_3.alpha = it - }, { + }, + { fourthAnimator.start() } ) @@ -124,9 +129,11 @@ class SecondsView(context: Context?, attrs: AttributeSet?) : icon_1.alpha = 0f icon_2.alpha = 1f icon_3.alpha = 1f - }, { + }, + { icon_2.alpha = 1f - it - }, { + }, + { fifthAnimator.start() } ) @@ -136,16 +143,20 @@ class SecondsView(context: Context?, attrs: AttributeSet?) : icon_1.alpha = 0f icon_2.alpha = 0f icon_3.alpha = 1f - }, { + }, + { icon_3.alpha = 1f - it - }, { + }, + { firstAnimator.start() } ) private inner class CustomValueAnimator( - start: () -> Unit, update: (value: Float) -> Unit, end: () -> Unit - ): ValueAnimator() { + start: () -> Unit, + update: (value: Float) -> Unit, + end: () -> Unit + ) : ValueAnimator() { init { duration = cycleDuration / 5 @@ -164,7 +175,6 @@ class SecondsView(context: Context?, attrs: AttributeSet?) : override fun onAnimationCancel(animation: Animator?) = Unit override fun onAnimationRepeat(animation: Animator?) = Unit - }) } } diff --git a/app/src/main/res/layout-large-land/player.xml b/app/src/main/res/layout-large-land/player.xml index f3b1056d2..cdb5849ab 100644 --- a/app/src/main/res/layout-large-land/player.xml +++ b/app/src/main/res/layout-large-land/player.xml @@ -54,11 +54,19 @@ tools:ignore="ContentDescription" tools:visibility="visible" /> + + @@ -754,4 +762,11 @@ android:textColor="@color/white" android:visibility="gone" /> + + diff --git a/app/src/main/res/layout/player.xml b/app/src/main/res/layout/player.xml index c2d1c84ff..e71ffdd96 100644 --- a/app/src/main/res/layout/player.xml +++ b/app/src/main/res/layout/player.xml @@ -54,11 +54,19 @@ tools:ignore="ContentDescription" tools:visibility="visible" /> + + @@ -751,4 +759,11 @@ android:textColor="@color/white" android:visibility="gone" /> + + From 3aebfa22e9a04582dd4117064fe6b7c62be45960 Mon Sep 17 00:00:00 2001 From: vkay94 Date: Mon, 18 Jan 2021 23:12:03 +0100 Subject: [PATCH 004/119] SeekOverlay: Switch to merge for SecondsView and other adjustments --- .../main/java/org/schabi/newpipe/ktx/View.kt | 2 +- .../org/schabi/newpipe/player/Player.java | 20 +++++++++---------- .../newpipe/views/player/SecondsView.kt | 7 ++++--- app/src/main/res/layout-large-land/player.xml | 2 +- app/src/main/res/layout/player.xml | 2 +- .../res/layout/player_seek_seconds_view.xml | 13 ++++++------ 6 files changed, 24 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/ktx/View.kt b/app/src/main/java/org/schabi/newpipe/ktx/View.kt index 5adb4e3ef..ae1b4388c 100644 --- a/app/src/main/java/org/schabi/newpipe/ktx/View.kt +++ b/app/src/main/java/org/schabi/newpipe/ktx/View.kt @@ -54,7 +54,7 @@ fun View.animate( ) Log.d(TAG, "animate(): $msg") } - if (isVisible && enterOrExit && alpha == 1f && animationType == AnimationType.ALPHA) { + if (isVisible && enterOrExit) { if (MainActivity.DEBUG) { Log.d(TAG, "animate(): view was already visible > view = [$this]") } diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index de8bffaf7..14b5f9316 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -251,6 +251,7 @@ public final class Player implements public static final int DEFAULT_CONTROLS_DURATION = 300; // 300 millis public static final int DEFAULT_CONTROLS_HIDE_TIME = 2000; // 2 Seconds public static final int DPAD_CONTROLS_HIDE_TIME = 7000; // 7 Seconds + public static final int SEEK_OVERLAY_DURATION = 450; // 450 millis /*////////////////////////////////////////////////////////////////////////// // Other constants @@ -586,10 +587,9 @@ public final class Player implements } private void setupPlayerSeekOverlay() { - final int fadeDurations = 450; binding.seekOverlay.showCircle(true) .circleBackgroundColorInt(CircleClipTapView.COLOR_DARK_TRANSPARENT) - .seekSeconds(retrieveSeekDurationFromPreferences(this) / 1000) + .seekSeconds((int) (retrieveSeekDurationFromPreferences(this) / 1000.0f)) .performListener(new PlayerSeekOverlay.PerformListener() { @Override @@ -605,22 +605,22 @@ public final class Player implements @Override public void onAnimationStart() { - animate(binding.seekOverlay, true, fadeDurations); + animate(binding.seekOverlay, true, SEEK_OVERLAY_DURATION); animate(binding.playbackControlsShadow, - !simpleExoPlayer.getPlayWhenReady(), fadeDurations); - animate(binding.playerTopShadow, false, fadeDurations); - animate(binding.playerBottomShadow, false, fadeDurations); - animate(binding.playbackControlRoot, false, fadeDurations); + !simpleExoPlayer.getPlayWhenReady(), SEEK_OVERLAY_DURATION); + animate(binding.playerTopShadow, false, SEEK_OVERLAY_DURATION); + animate(binding.playerBottomShadow, false, SEEK_OVERLAY_DURATION); + animate(binding.playbackControlRoot, false, SEEK_OVERLAY_DURATION); hideSystemUIIfNeeded(); } @Override public void onAnimationEnd() { - animate(binding.seekOverlay, false, fadeDurations); + animate(binding.seekOverlay, false, SEEK_OVERLAY_DURATION); if (!simpleExoPlayer.getPlayWhenReady()) { - showControls(fadeDurations); + showControls(SEEK_OVERLAY_DURATION); } else { - showHideShadow(false, fadeDurations); + showHideShadow(false, SEEK_OVERLAY_DURATION); } } diff --git a/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt b/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt index fa2dbd63e..f01b116ce 100644 --- a/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt +++ b/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt @@ -5,14 +5,13 @@ import android.animation.ValueAnimator import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater +import android.widget.LinearLayout import android.widget.TextView import androidx.annotation.DrawableRes -import androidx.constraintlayout.widget.ConstraintLayout import kotlinx.android.synthetic.main.player_seek_seconds_view.view.* import org.schabi.newpipe.R -class SecondsView(context: Context, attrs: AttributeSet?) : - ConstraintLayout(context, attrs) { +class SecondsView(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) { companion object { const val ICON_ANIMATION_DURATION = 750L @@ -58,6 +57,8 @@ class SecondsView(context: Context, attrs: AttributeSet?) : init { LayoutInflater.from(context).inflate(R.layout.player_seek_seconds_view, this, true) + orientation = VERTICAL + layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT) } fun start() { diff --git a/app/src/main/res/layout-large-land/player.xml b/app/src/main/res/layout-large-land/player.xml index cdb5849ab..10f5a60a0 100644 --- a/app/src/main/res/layout-large-land/player.xml +++ b/app/src/main/res/layout-large-land/player.xml @@ -767,6 +767,6 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="invisible" - android:alpha="0" /> + android:alpha="0" /> diff --git a/app/src/main/res/layout/player.xml b/app/src/main/res/layout/player.xml index e71ffdd96..3625e0e69 100644 --- a/app/src/main/res/layout/player.xml +++ b/app/src/main/res/layout/player.xml @@ -764,6 +764,6 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="invisible" - android:alpha="0" /> + android:alpha="0" /> diff --git a/app/src/main/res/layout/player_seek_seconds_view.xml b/app/src/main/res/layout/player_seek_seconds_view.xml index 14c9eaa2d..8aed15594 100644 --- a/app/src/main/res/layout/player_seek_seconds_view.xml +++ b/app/src/main/res/layout/player_seek_seconds_view.xml @@ -1,11 +1,12 @@ - + tools:ignore="ContentDescription" + tools:layout_height="wrap_content" + tools:layout_width="match_parent" + tools:orientation="vertical" + tools:parentTag="android.widget.LinearLayout"> - + From ee827407aafeb3b2d05fe5fd9afc806da66f864e Mon Sep 17 00:00:00 2001 From: Stypox Date: Sat, 31 Jul 2021 10:33:57 +0200 Subject: [PATCH 005/119] Fix seek triangles not visible on API 19 --- app/src/main/res/layout/player_seek_seconds_view.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/layout/player_seek_seconds_view.xml b/app/src/main/res/layout/player_seek_seconds_view.xml index 8aed15594..57f5aa787 100644 --- a/app/src/main/res/layout/player_seek_seconds_view.xml +++ b/app/src/main/res/layout/player_seek_seconds_view.xml @@ -15,21 +15,21 @@ android:gravity="center_horizontal" android:orientation="horizontal"> - - - Date: Tue, 31 Aug 2021 19:08:40 +0200 Subject: [PATCH 006/119] Convert SecondsView from kotlin synthetics to view binding --- .../newpipe/views/player/SecondsView.kt | 65 ++++++++++--------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt b/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt index f01b116ce..8574d607f 100644 --- a/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt +++ b/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt @@ -8,8 +8,8 @@ import android.view.LayoutInflater import android.widget.LinearLayout import android.widget.TextView import androidx.annotation.DrawableRes -import kotlinx.android.synthetic.main.player_seek_seconds_view.view.* import org.schabi.newpipe.R +import org.schabi.newpipe.databinding.PlayerSeekSecondsViewBinding class SecondsView(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) { @@ -29,7 +29,7 @@ class SecondsView(context: Context, attrs: AttributeSet?) : LinearLayout(context var seconds: Int = 0 set(value) { - tv_seconds.text = context.resources.getQuantityString( + binding.tvSeconds.text = context.resources.getQuantityString( R.plurals.seconds, value, value ) field = value @@ -37,26 +37,27 @@ class SecondsView(context: Context, attrs: AttributeSet?) : LinearLayout(context var isForward: Boolean = true set(value) { - triangle_container.rotation = if (value) 0f else 180f + binding.triangleContainer.rotation = if (value) 0f else 180f field = value } + val binding = PlayerSeekSecondsViewBinding.inflate(LayoutInflater.from(context), this) + val textView: TextView - get() = tv_seconds + get() = binding.tvSeconds @DrawableRes var icon: Int = R.drawable.ic_play_seek_triangle set(value) { if (value > 0) { - icon_1.setImageResource(value) - icon_2.setImageResource(value) - icon_3.setImageResource(value) + binding.icon1.setImageResource(value) + binding.icon2.setImageResource(value) + binding.icon3.setImageResource(value) } field = value } init { - LayoutInflater.from(context).inflate(R.layout.player_seek_seconds_view, this, true) orientation = VERTICAL layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT) } @@ -77,19 +78,19 @@ class SecondsView(context: Context, attrs: AttributeSet?) : LinearLayout(context } private fun reset() { - icon_1.alpha = 0f - icon_2.alpha = 0f - icon_3.alpha = 0f + binding.icon1.alpha = 0f + binding.icon2.alpha = 0f + binding.icon3.alpha = 0f } private val firstAnimator: ValueAnimator = CustomValueAnimator( { - icon_1.alpha = 0f - icon_2.alpha = 0f - icon_3.alpha = 0f + binding.icon1.alpha = 0f + binding.icon2.alpha = 0f + binding.icon3.alpha = 0f }, { - icon_1.alpha = it + binding.icon1.alpha = it }, { secondAnimator.start() @@ -98,12 +99,12 @@ class SecondsView(context: Context, attrs: AttributeSet?) : LinearLayout(context private val secondAnimator: ValueAnimator = CustomValueAnimator( { - icon_1.alpha = 1f - icon_2.alpha = 0f - icon_3.alpha = 0f + binding.icon1.alpha = 1f + binding.icon2.alpha = 0f + binding.icon3.alpha = 0f }, { - icon_2.alpha = it + binding.icon2.alpha = it }, { thirdAnimator.start() @@ -112,13 +113,13 @@ class SecondsView(context: Context, attrs: AttributeSet?) : LinearLayout(context private val thirdAnimator: ValueAnimator = CustomValueAnimator( { - icon_1.alpha = 1f - icon_2.alpha = 1f - icon_3.alpha = 0f + binding.icon1.alpha = 1f + binding.icon2.alpha = 1f + binding.icon3.alpha = 0f }, { - icon_1.alpha = 1f - icon_3.alpha - icon_3.alpha = it + binding.icon1.alpha = 1f - binding.icon3.alpha + binding.icon3.alpha = it }, { fourthAnimator.start() @@ -127,12 +128,12 @@ class SecondsView(context: Context, attrs: AttributeSet?) : LinearLayout(context private val fourthAnimator: ValueAnimator = CustomValueAnimator( { - icon_1.alpha = 0f - icon_2.alpha = 1f - icon_3.alpha = 1f + binding.icon1.alpha = 0f + binding.icon2.alpha = 1f + binding.icon3.alpha = 1f }, { - icon_2.alpha = 1f - it + binding.icon2.alpha = 1f - it }, { fifthAnimator.start() @@ -141,12 +142,12 @@ class SecondsView(context: Context, attrs: AttributeSet?) : LinearLayout(context private val fifthAnimator: ValueAnimator = CustomValueAnimator( { - icon_1.alpha = 0f - icon_2.alpha = 0f - icon_3.alpha = 1f + binding.icon1.alpha = 0f + binding.icon2.alpha = 0f + binding.icon3.alpha = 1f }, { - icon_3.alpha = 1f - it + binding.icon3.alpha = 1f - it }, { firstAnimator.start() From a454a41b51bd6c0a154225b1e1e8174238dcbcd6 Mon Sep 17 00:00:00 2001 From: Stypox Date: Wed, 1 Sep 2021 17:24:10 +0200 Subject: [PATCH 007/119] Fix controls not hiding correctly when switching player --- app/src/main/java/org/schabi/newpipe/player/Player.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 14b5f9316..b859d9997 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -2186,8 +2186,8 @@ public final class Player implements startProgressLoop(); } - controlsVisibilityHandler.removeCallbacksAndMessages(null); - animate(binding.playbackControlRoot, false, DEFAULT_CONTROLS_DURATION); + // if we are e.g. switching players, hide controls + hideControls(DEFAULT_CONTROLS_DURATION, 0); binding.playbackSeekBar.setEnabled(false); binding.playbackSeekBar.getThumb() From 03d53725258a55234fad5a66d29e3c2e205a4ebc Mon Sep 17 00:00:00 2001 From: Stypox Date: Wed, 1 Sep 2021 19:51:52 +0200 Subject: [PATCH 008/119] Fix buttons' selectable item background not working in player --- app/src/main/res/layout-large-land/player.xml | 2 ++ app/src/main/res/layout/player.xml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/app/src/main/res/layout-large-land/player.xml b/app/src/main/res/layout-large-land/player.xml index 10f5a60a0..5ffb7e0fb 100644 --- a/app/src/main/res/layout-large-land/player.xml +++ b/app/src/main/res/layout-large-land/player.xml @@ -63,10 +63,12 @@ android:background="@color/video_overlay_color" tools:visibility="visible" /> + diff --git a/app/src/main/res/layout/player.xml b/app/src/main/res/layout/player.xml index 3625e0e69..22817c4e6 100644 --- a/app/src/main/res/layout/player.xml +++ b/app/src/main/res/layout/player.xml @@ -63,10 +63,12 @@ android:background="@color/video_overlay_color" tools:visibility="visible" /> + From 83a3d11f38154b03d6fa398bf375d8ad088308a9 Mon Sep 17 00:00:00 2001 From: Stypox Date: Wed, 1 Sep 2021 18:34:37 +0200 Subject: [PATCH 009/119] Small improvements to player --- .../java/org/schabi/newpipe/player/Player.java | 1 + app/src/main/res/layout-large-land/player.xml | 18 +++++++++--------- app/src/main/res/layout/player.xml | 4 ++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index b859d9997..467d1e757 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -533,6 +533,7 @@ public final class Player implements playerGestureListener = new PlayerGestureListener(this, service); gestureDetector = new GestureDetectorCompat(context, playerGestureListener); + //noinspection ClickableViewAccessibility binding.getRoot().setOnTouchListener(playerGestureListener); setupPlayerSeekOverlay(); diff --git a/app/src/main/res/layout-large-land/player.xml b/app/src/main/res/layout-large-land/player.xml index 5ffb7e0fb..520c165cb 100644 --- a/app/src/main/res/layout-large-land/player.xml +++ b/app/src/main/res/layout-large-land/player.xml @@ -58,9 +58,9 @@ android:id="@+id/playbackControlsShadow" android:layout_width="match_parent" android:layout_height="match_parent" - android:visibility="gone" android:layout_alignBottom="@+id/playbackControlRoot" android:background="@color/video_overlay_color" + android:visibility="gone" tools:visibility="visible" /> @@ -479,8 +479,8 @@ android:padding="@dimen/player_main_buttons_padding" android:scaleType="fitCenter" android:visibility="gone" - app:tint="@color/white" app:srcCompat="@drawable/ic_fullscreen" + app:tint="@color/white" tools:ignore="ContentDescription,RtlHardcoded" tools:visibility="visible" /> @@ -503,8 +503,8 @@ android:clickable="true" android:focusable="true" android:scaleType="fitCenter" - app:tint="@color/white" app:srcCompat="@drawable/ic_previous" + app:tint="@color/white" tools:ignore="ContentDescription" /> @@ -515,8 +515,8 @@ android:layout_weight="1" android:background="?attr/selectableItemBackgroundBorderless" android:scaleType="fitCenter" - app:tint="@color/white" app:srcCompat="@drawable/ic_pause" + app:tint="@color/white" tools:ignore="ContentDescription" /> @@ -582,8 +582,8 @@ android:focusable="true" android:padding="10dp" android:scaleType="fitXY" - app:tint="@color/white" - app:srcCompat="@drawable/ic_close" /> + app:srcCompat="@drawable/ic_close" + app:tint="@color/white" /> + android:alpha="0" + android:visibility="invisible" /> diff --git a/app/src/main/res/layout/player.xml b/app/src/main/res/layout/player.xml index 22817c4e6..27b8936a3 100644 --- a/app/src/main/res/layout/player.xml +++ b/app/src/main/res/layout/player.xml @@ -765,7 +765,7 @@ android:id="@+id/seekOverlay" android:layout_width="match_parent" android:layout_height="match_parent" - android:visibility="invisible" - android:alpha="0" /> + android:alpha="0" + android:visibility="invisible" /> From dac47d9f5244ff1d159e9ec0edfbc90e1c94b106 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Mon, 11 Oct 2021 23:02:36 +0200 Subject: [PATCH 010/119] Replace NotNull annotation with NonNull annotation --- app/src/main/java/org/schabi/newpipe/player/Player.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 467d1e757..8e340302a 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -136,7 +136,6 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.squareup.picasso.Picasso; import com.squareup.picasso.Target; -import org.jetbrains.annotations.NotNull; import org.schabi.newpipe.DownloaderImpl; import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; @@ -626,7 +625,7 @@ public final class Player implements } @Override - public Boolean shouldFastForward(@NotNull final DisplayPortion portion) { + public Boolean shouldFastForward(@NonNull final DisplayPortion portion) { // Null indicates an invalid area or condition e.g. the middle portion // or video start or end was reached during double tap seeking if (invalidSeekConditions()) { From fe42206e94913c3a35301ac10de2b29e333f98ee Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 3 Dec 2021 20:29:18 +0100 Subject: [PATCH 011/119] Code cleanup and minimization * Deduplicated and simplified a lot of code * Fixed ``invalidSeekConditions`` so that it's possible to seek while the player is loading (like currently the case) --- .../org/schabi/newpipe/player/Player.java | 129 ++------ .../player/event/BasePlayerGestureListener.kt | 6 +- .../player/event/PlayerGestureListener.java | 3 +- .../newpipe/views/player/CircleClipTapView.kt | 33 +-- .../views/player/PlayerFastSeekOverlay.kt | 136 +++++++++ .../newpipe/views/player/PlayerSeekOverlay.kt | 278 ------------------ .../newpipe/views/player/SecondsView.kt | 30 +- app/src/main/res/layout-large-land/player.xml | 22 +- app/src/main/res/layout/player.xml | 22 +- ...erlay.xml => player_fast_seek_overlay.xml} | 3 +- ....xml => player_fast_seek_seconds_view.xml} | 0 11 files changed, 185 insertions(+), 477 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt delete mode 100644 app/src/main/java/org/schabi/newpipe/views/player/PlayerSeekOverlay.kt rename app/src/main/res/layout/{player_seek_overlay.xml => player_fast_seek_overlay.xml} (93%) rename app/src/main/res/layout/{player_seek_seconds_view.xml => player_fast_seek_seconds_view.xml} (100%) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 8e340302a..fbfaf7b95 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -51,8 +51,6 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; -import android.animation.ObjectAnimator; -import android.animation.PropertyValuesHolder; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.content.BroadcastReceiver; @@ -189,8 +187,7 @@ import org.schabi.newpipe.util.StreamTypeUtil; import org.schabi.newpipe.util.external_communication.KoreUtils; import org.schabi.newpipe.util.external_communication.ShareUtils; import org.schabi.newpipe.views.ExpandableSurfaceView; -import org.schabi.newpipe.views.player.CircleClipTapView; -import org.schabi.newpipe.views.player.PlayerSeekOverlay; +import org.schabi.newpipe.views.player.PlayerFastSeekOverlay; import java.io.IOException; import java.util.ArrayList; @@ -454,6 +451,8 @@ public final class Player implements initPlayer(true); } initListeners(); + + setupPlayerSeekOverlay(); } private void initViews(@NonNull final PlayerBinding playerBinding) { @@ -530,12 +529,6 @@ public final class Player implements binding.resizeTextView.setOnClickListener(this); binding.playbackLiveSync.setOnClickListener(this); - playerGestureListener = new PlayerGestureListener(this, service); - gestureDetector = new GestureDetectorCompat(context, playerGestureListener); - //noinspection ClickableViewAccessibility - binding.getRoot().setOnTouchListener(playerGestureListener); - setupPlayerSeekOverlay(); - binding.queueButton.setOnClickListener(this); binding.segmentsButton.setOnClickListener(this); binding.repeatButton.setOnClickListener(this); @@ -586,26 +579,26 @@ public final class Player implements v.getPaddingBottom())); } + /** + * Initializes the Fast-For/Backward overlay. + */ private void setupPlayerSeekOverlay() { - binding.seekOverlay.showCircle(true) - .circleBackgroundColorInt(CircleClipTapView.COLOR_DARK_TRANSPARENT) + playerGestureListener = new PlayerGestureListener(this, service); + gestureDetector = new GestureDetectorCompat(context, playerGestureListener); + binding.getRoot().setOnTouchListener(playerGestureListener); + + binding.fastSeekOverlay .seekSeconds((int) (retrieveSeekDurationFromPreferences(this) / 1000.0f)) - .performListener(new PlayerSeekOverlay.PerformListener() { + .performListener(new PlayerFastSeekOverlay.PerformListener() { @Override - public void onPrepare() { - if (invalidSeekConditions()) { - playerGestureListener.endMultiDoubleTap(); - return; - } - binding.seekOverlay.arcSize( - CircleClipTapView.Companion.calculateArcSize(getSurfaceView()) - ); + public void onDoubleTabStart() { + // TODO } @Override - public void onAnimationStart() { - animate(binding.seekOverlay, true, SEEK_OVERLAY_DURATION); + public void onDoubleTab() { + animate(binding.fastSeekOverlay, true, SEEK_OVERLAY_DURATION); animate(binding.playbackControlsShadow, !simpleExoPlayer.getPlayWhenReady(), SEEK_OVERLAY_DURATION); animate(binding.playerTopShadow, false, SEEK_OVERLAY_DURATION); @@ -615,8 +608,8 @@ public final class Player implements } @Override - public void onAnimationEnd() { - animate(binding.seekOverlay, false, SEEK_OVERLAY_DURATION); + public void onDoubleTabEnd() { + animate(binding.fastSeekOverlay, false, SEEK_OVERLAY_DURATION); if (!simpleExoPlayer.getPlayWhenReady()) { showControls(SEEK_OVERLAY_DURATION); } else { @@ -629,6 +622,7 @@ public final class Player implements // Null indicates an invalid area or condition e.g. the middle portion // or video start or end was reached during double tap seeking if (invalidSeekConditions()) { + playerGestureListener.endMultiDoubleTap(); return null; } if (portion == DisplayPortion.LEFT @@ -637,9 +631,9 @@ public final class Player implements return false; } else if (portion == DisplayPortion.RIGHT) { return true; - } else /* portion == DisplayPortion.MIDDLE */ { - return null; } + /* portion == DisplayPortion.MIDDLE */ + return null; } @Override @@ -653,12 +647,13 @@ public final class Player implements } private boolean invalidSeekConditions() { - return simpleExoPlayer.getCurrentPosition() == simpleExoPlayer.getDuration() - || currentState == STATE_COMPLETED - || !isPrepared; + return exoPlayerIsNull() + || simpleExoPlayer.getPlaybackState() == SimpleExoPlayer.STATE_ENDED + || simpleExoPlayer.getCurrentPosition() >= simpleExoPlayer.getDuration() + || currentState == STATE_COMPLETED; } }); - playerGestureListener.doubleTapControls(binding.seekOverlay); + playerGestureListener.doubleTapControls(binding.fastSeekOverlay); } //endregion @@ -1879,71 +1874,6 @@ public final class Player implements return binding != null && binding.playbackControlRoot.getVisibility() == View.VISIBLE; } - /** - * Show a animation, and depending on goneOnEnd, will stay on the screen or be gone. - * - * @param drawableId the drawable that will be used to animate, - * pass -1 to clear any animation that is visible - * @param goneOnEnd will set the animation view to GONE on the end of the animation - */ - public void showAndAnimateControl(final int drawableId, final boolean goneOnEnd) { - if (DEBUG) { - Log.d(TAG, "showAndAnimateControl() called with: " - + "drawableId = [" + drawableId + "], goneOnEnd = [" + goneOnEnd + "]"); - } - if (controlViewAnimator != null && controlViewAnimator.isRunning()) { - if (DEBUG) { - Log.d(TAG, "showAndAnimateControl: controlViewAnimator.isRunning"); - } - controlViewAnimator.end(); - } - - if (drawableId == -1) { - if (binding.controlAnimationView.getVisibility() == View.VISIBLE) { - controlViewAnimator = ObjectAnimator.ofPropertyValuesHolder( - binding.controlAnimationView, - PropertyValuesHolder.ofFloat(View.ALPHA, 1.0f, 0.0f), - PropertyValuesHolder.ofFloat(View.SCALE_X, 1.4f, 1.0f), - PropertyValuesHolder.ofFloat(View.SCALE_Y, 1.4f, 1.0f) - ).setDuration(DEFAULT_CONTROLS_DURATION); - controlViewAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(final Animator animation) { - binding.controlAnimationView.setVisibility(View.GONE); - } - }); - controlViewAnimator.start(); - } - return; - } - - final float scaleFrom = goneOnEnd ? 1f : 1f; - final float scaleTo = goneOnEnd ? 1.8f : 1.4f; - final float alphaFrom = goneOnEnd ? 1f : 0f; - final float alphaTo = goneOnEnd ? 0f : 1f; - - - controlViewAnimator = ObjectAnimator.ofPropertyValuesHolder( - binding.controlAnimationView, - PropertyValuesHolder.ofFloat(View.ALPHA, alphaFrom, alphaTo), - PropertyValuesHolder.ofFloat(View.SCALE_X, scaleFrom, scaleTo), - PropertyValuesHolder.ofFloat(View.SCALE_Y, scaleFrom, scaleTo) - ); - controlViewAnimator.setDuration(goneOnEnd ? 1000 : 500); - controlViewAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(final Animator animation) { - binding.controlAnimationView.setVisibility(goneOnEnd ? View.GONE : View.VISIBLE); - } - }); - - - binding.controlAnimationView.setVisibility(View.VISIBLE); - binding.controlAnimationView.setImageDrawable( - AppCompatResources.getDrawable(context, drawableId)); - controlViewAnimator.start(); - } - public void showControlsThenHide() { if (DEBUG) { Log.d(TAG, "showControlsThenHide() called"); @@ -2214,8 +2144,6 @@ public final class Player implements updateStreamRelatedViews(); - showAndAnimateControl(-1, true); - binding.playbackSeekBar.setEnabled(true); binding.playbackSeekBar.getThumb() .setColorFilter(new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC_IN)); @@ -2295,7 +2223,6 @@ public final class Player implements if (DEBUG) { Log.d(TAG, "onPausedSeek() called"); } - showAndAnimateControl(-1, true); animatePlayButtons(false, 100); binding.getRoot().setKeepScreenOn(true); @@ -4364,8 +4291,8 @@ public final class Player implements return binding.currentDisplaySeek; } - public PlayerSeekOverlay getSeekOverlay() { - return binding.seekOverlay; + public PlayerFastSeekOverlay getFastSeekOverlay() { + return binding.fastSeekOverlay; } @Nullable diff --git a/app/src/main/java/org/schabi/newpipe/player/event/BasePlayerGestureListener.kt b/app/src/main/java/org/schabi/newpipe/player/event/BasePlayerGestureListener.kt index 29ae7c5c3..c89eabb47 100644 --- a/app/src/main/java/org/schabi/newpipe/player/event/BasePlayerGestureListener.kt +++ b/app/src/main/java/org/schabi/newpipe/player/event/BasePlayerGestureListener.kt @@ -411,7 +411,7 @@ abstract class BasePlayerGestureListener( var doubleTapControls: DoubleTapListener? = null private set - val isDoubleTapEnabled: Boolean + private val isDoubleTapEnabled: Boolean get() = doubleTapDelay > 0 var isDoubleTapping = false @@ -459,10 +459,6 @@ abstract class BasePlayerGestureListener( doubleTapControls?.onDoubleTapFinished() } - fun enableMultiDoubleTap(enable: Boolean) = apply { - doubleTapDelay = if (enable) DOUBLE_TAP_DELAY else 0 - } - // /////////////////////////////////////////////////////////////////// // Utils // /////////////////////////////////////////////////////////////////// diff --git a/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java b/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java index b215584e8..794fe9b3c 100644 --- a/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java +++ b/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java @@ -230,11 +230,10 @@ public class PlayerGestureListener if (DEBUG) { Log.d(TAG, "onPopupResizingStart called"); } - player.showAndAnimateControl(-1, true); player.getLoadingPanel().setVisibility(View.GONE); player.hideControls(0, 0); - animate(player.getSeekOverlay(), false, 0); + animate(player.getFastSeekOverlay(), false, 0); animate(player.getCurrentDisplaySeek(), false, 0, ALPHA, 0); } diff --git a/app/src/main/java/org/schabi/newpipe/views/player/CircleClipTapView.kt b/app/src/main/java/org/schabi/newpipe/views/player/CircleClipTapView.kt index 6b22538e0..e3d142916 100644 --- a/app/src/main/java/org/schabi/newpipe/views/player/CircleClipTapView.kt +++ b/app/src/main/java/org/schabi/newpipe/views/player/CircleClipTapView.kt @@ -6,18 +6,9 @@ import android.graphics.Paint import android.graphics.Path import android.util.AttributeSet import android.view.View -import org.schabi.newpipe.player.event.DisplayPortion class CircleClipTapView(context: Context?, attrs: AttributeSet) : View(context, attrs) { - companion object { - const val COLOR_DARK = 0x45000000 - const val COLOR_DARK_TRANSPARENT = 0x30000000 - const val COLOR_LIGHT_TRANSPARENT = 0x25EEEEEE - - fun calculateArcSize(view: View): Float = view.height / 11.4f - } - private var backgroundPaint = Paint() private var widthPx = 0 @@ -26,6 +17,7 @@ class CircleClipTapView(context: Context?, attrs: AttributeSet) : View(context, // Background private var shapePath = Path() + private var arcSize: Float = 80f private var isLeft = true init { @@ -34,7 +26,7 @@ class CircleClipTapView(context: Context?, attrs: AttributeSet) : View(context, backgroundPaint.apply { style = Paint.Style.FILL isAntiAlias = true - color = COLOR_LIGHT_TRANSPARENT + color = 0x30000000 } val dm = context.resources.displayMetrics @@ -44,24 +36,15 @@ class CircleClipTapView(context: Context?, attrs: AttributeSet) : View(context, updatePathShape() } - var arcSize: Float = 80f - set(value) { - field = value + fun updateArcSize(baseView: View) { + val newArcSize = baseView.height / 11.4f + if (arcSize != newArcSize) { + arcSize = newArcSize updatePathShape() } + } - var circleBackgroundColor: Int - get() = backgroundPaint.color - set(value) { - backgroundPaint.color = value - } - - /* - Background - */ - - fun updatePosition(portion: DisplayPortion) { - val newIsLeft = portion == DisplayPortion.LEFT + fun updatePosition(newIsLeft: Boolean) { if (isLeft != newIsLeft) { isLeft = newIsLeft updatePathShape() diff --git a/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt b/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt new file mode 100644 index 000000000..90384264b --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt @@ -0,0 +1,136 @@ +package org.schabi.newpipe.views.player + +import android.content.Context +import android.util.AttributeSet +import android.util.Log +import android.view.LayoutInflater +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.END +import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.PARENT_ID +import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.START +import androidx.constraintlayout.widget.ConstraintSet +import org.schabi.newpipe.MainActivity +import org.schabi.newpipe.R +import org.schabi.newpipe.player.event.DisplayPortion +import org.schabi.newpipe.player.event.DoubleTapListener + +class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : + ConstraintLayout(context, attrs), DoubleTapListener { + + private var secondsView: SecondsView + private var circleClipTapView: CircleClipTapView + private var rootConstraintLayout: ConstraintLayout + + private var wasForwarding: Boolean = false + + init { + LayoutInflater.from(context).inflate(R.layout.player_fast_seek_overlay, this, true) + + secondsView = findViewById(R.id.seconds_view) + circleClipTapView = findViewById(R.id.circle_clip_tap_view) + rootConstraintLayout = findViewById(R.id.root_constraint_layout) + + addOnLayoutChangeListener { view, _, _, _, _, _, _, _, _ -> + circleClipTapView.updateArcSize(view) + } + } + + private var performListener: PerformListener? = null + + fun performListener(listener: PerformListener) = apply { + performListener = listener + } + + var seekSeconds: Int = 0 + private set + + fun seekSeconds(seconds: Int) = apply { + seekSeconds = seconds + } + + // Indicates whether this (double) tap is the first of a series + // Decides whether to call performListener.onAnimationStart or not + private var initTap: Boolean = false + + override fun onDoubleTapStarted(portion: DisplayPortion) { + if (DEBUG) + Log.d(TAG, "onDoubleTapStarted called with portion = [$portion]") + + initTap = false + performListener?.onDoubleTabStart() + + secondsView.stop() + } + + override fun onDoubleTapProgressDown(portion: DisplayPortion) { + val shouldForward: Boolean = performListener?.shouldFastForward(portion) ?: return + + if (DEBUG) + Log.d( + TAG, + "onDoubleTapProgressDown called with " + + "shouldForward = [$shouldForward], " + + "wasForwarding = [$wasForwarding], " + + "initTap = [$initTap], " + ) + + /* + * Check if a initial tab occurred or if direction was switched + */ + if (!initTap || wasForwarding != shouldForward) { + // Reset seconds and update position + secondsView.seconds = 0 + changeConstraints(shouldForward) + circleClipTapView.updatePosition(!shouldForward) + secondsView.setForwarding(shouldForward) + + wasForwarding = shouldForward + + if (!initTap) { + // Start animation + secondsView.start() + initTap = true + } + } + + performListener?.onDoubleTab() + + secondsView.seconds += seekSeconds + performListener?.seek(forward = shouldForward) + } + + override fun onDoubleTapFinished() { + if (DEBUG) + Log.d(TAG, "onDoubleTapFinished called with initTap = [$initTap]") + + if (initTap) performListener?.onDoubleTabEnd() + initTap = false + } + + private fun changeConstraints(forward: Boolean) { + val constraintSet = ConstraintSet() + with(constraintSet) { + clone(rootConstraintLayout) + clear(secondsView.id, if (forward) START else END) + connect( + secondsView.id, if (forward) END else START, + PARENT_ID, if (forward) END else START + ) + secondsView.start() + applyTo(rootConstraintLayout) + } + } + + interface PerformListener { + fun onDoubleTabStart() {} + fun onDoubleTab() + fun onDoubleTabEnd() + fun shouldFastForward(portion: DisplayPortion): Boolean? + fun seek(forward: Boolean) + } + + companion object { + private const val TAG = "PlayerSeekOverlay" + private val DEBUG = MainActivity.DEBUG + } +} diff --git a/app/src/main/java/org/schabi/newpipe/views/player/PlayerSeekOverlay.kt b/app/src/main/java/org/schabi/newpipe/views/player/PlayerSeekOverlay.kt deleted file mode 100644 index d61989d92..000000000 --- a/app/src/main/java/org/schabi/newpipe/views/player/PlayerSeekOverlay.kt +++ /dev/null @@ -1,278 +0,0 @@ -package org.schabi.newpipe.views.player - -import android.content.Context -import android.util.AttributeSet -import android.util.Log -import android.view.LayoutInflater -import android.view.View -import androidx.annotation.ColorInt -import androidx.annotation.ColorRes -import androidx.annotation.DimenRes -import androidx.annotation.DrawableRes -import androidx.annotation.StyleRes -import androidx.constraintlayout.widget.ConstraintLayout -import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.END -import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.PARENT_ID -import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.START -import androidx.constraintlayout.widget.ConstraintSet -import androidx.core.content.ContextCompat -import androidx.core.widget.TextViewCompat -import androidx.preference.PreferenceManager -import org.schabi.newpipe.MainActivity -import org.schabi.newpipe.R -import org.schabi.newpipe.player.event.DisplayPortion -import org.schabi.newpipe.player.event.DoubleTapListener - -class PlayerSeekOverlay(context: Context, private val attrs: AttributeSet?) : - ConstraintLayout(context, attrs), DoubleTapListener { - - private var secondsView: SecondsView - private var circleClipTapView: CircleClipTapView - private var rootConstraintLayout: ConstraintLayout - - private var isForwarding: Boolean? = null - - init { - LayoutInflater.from(context).inflate(R.layout.player_seek_overlay, this, true) - - secondsView = findViewById(R.id.seconds_view) - circleClipTapView = findViewById(R.id.circle_clip_tap_view) - rootConstraintLayout = findViewById(R.id.root_constraint_layout) - - initializeAttributes() - secondsView.isForward = true - isForwarding = null - changeConstraints(true) - } - - private fun initializeAttributes() { - circleBackgroundColorInt(CircleClipTapView.COLOR_LIGHT_TRANSPARENT) - iconAnimationDuration(SecondsView.ICON_ANIMATION_DURATION) - icon(R.drawable.ic_play_seek_triangle) - - val prefs = PreferenceManager.getDefaultSharedPreferences(context) - val durationKey = context.getString(R.string.seek_duration_key) - val seekValue = prefs.getString( - durationKey, context.getString(R.string.seek_duration_default_value) - ) - seekSeconds(seekValue?.toInt()?.div(1000) ?: 10) - } - - private var performListener: PerformListener? = null - - fun performListener(listener: PerformListener) = apply { - performListener = listener - } - - var seekSeconds: Int = 0 - private set - - fun seekSeconds(seconds: Int) = apply { - seekSeconds = seconds - } - - var circleBackgroundColor: Int - get() = circleClipTapView.circleBackgroundColor - private set(value) { - circleClipTapView.circleBackgroundColor = value - } - - fun circleBackgroundColorRes(@ColorRes resId: Int) = apply { - circleBackgroundColor = ContextCompat.getColor(context, resId) - } - - fun circleBackgroundColorInt(@ColorInt color: Int) = apply { - circleBackgroundColor = color - } - - var arcSize: Float - get() = circleClipTapView.arcSize - internal set(value) { - circleClipTapView.arcSize = value - } - - fun arcSize(@DimenRes resId: Int) = apply { - arcSize = context.resources.getDimension(resId) - } - - fun arcSize(px: Float) = apply { - arcSize = px - } - - var showCircle: Boolean = true - private set(value) { - circleClipTapView.visibility = if (value) View.VISIBLE else View.GONE - field = value - } - - fun showCircle(show: Boolean) = apply { - showCircle = show - } - - var iconAnimationDuration: Long = SecondsView.ICON_ANIMATION_DURATION - get() = secondsView.cycleDuration - private set(value) { - secondsView.cycleDuration = value - field = value - } - - fun iconAnimationDuration(duration: Long) = apply { - iconAnimationDuration = duration - } - - @DrawableRes - var icon: Int = 0 - get() = secondsView.icon - private set(value) { - secondsView.stop() - secondsView.icon = value - field = value - } - - fun icon(@DrawableRes resId: Int) = apply { - icon = resId - } - - @StyleRes - var textAppearance: Int = 0 - private set(value) { - TextViewCompat.setTextAppearance(secondsView.textView, value) - field = value - } - - fun textAppearance(@StyleRes resId: Int) = apply { - textAppearance = resId - } - - // Indicates whether this (double) tap is the first of a series - // Decides whether to call performListener.onAnimationStart or not - private var initTap: Boolean = false - - override fun onDoubleTapStarted(portion: DisplayPortion) { - if (DEBUG) - Log.d(TAG, "onDoubleTapStarted called with portion = [$portion]") - - initTap = false - performListener?.onPrepare() - - changeConstraints(secondsView.isForward) - if (showCircle) circleClipTapView.updatePosition(portion) - - isForwarding = null - - if (this.alpha == 0f) - secondsView.stop() - } - - override fun onDoubleTapProgressDown(portion: DisplayPortion) { - val shouldForward: Boolean = performListener?.shouldFastForward(portion) ?: return - - if (DEBUG) - Log.d( - TAG, - "onDoubleTapProgressDown called with " + - "shouldForward = [$shouldForward], " + - "isForwarding = [$isForwarding], " + - "secondsView#isForward = [${secondsView.isForward}], " + - "initTap = [$initTap], " - ) - - // Using this check prevents from fast switching (one touches) - if (isForwarding != null && isForwarding != shouldForward) { - isForwarding = shouldForward - return - } - isForwarding = shouldForward - - if (this.visibility != View.VISIBLE || !initTap) { - if (!initTap) { - secondsView.seconds = 0 - performListener?.onAnimationStart() - secondsView.start() - initTap = true - } - } - - if (shouldForward) - forwarding() - else - rewinding() - } - - override fun onDoubleTapFinished() { - if (DEBUG) - Log.d(TAG, "onDoubleTapFinished called with initTap = [$initTap]") - - if (initTap) performListener?.onAnimationEnd() - initTap = false - } - - private fun forwarding() { - if (DEBUG) - Log.d(TAG, "forwarding called") - - // First time tap or switched - if (!secondsView.isForward) { - changeConstraints(true) - if (showCircle) circleClipTapView.updatePosition(DisplayPortion.RIGHT) - secondsView.apply { - isForward = true - seconds = 0 - } - } - secondsView.seconds += seekSeconds - performListener?.seek(forward = true) - } - - private fun rewinding() { - if (DEBUG) - Log.d(TAG, "rewinding called") - - // First time tap or switched - if (secondsView.isForward) { - changeConstraints(false) - if (showCircle) circleClipTapView.updatePosition(DisplayPortion.LEFT) - secondsView.apply { - isForward = false - seconds = 0 - } - } - secondsView.seconds += seekSeconds - performListener?.seek(forward = false) - } - - private fun changeConstraints(forward: Boolean) { - val constraintSet = ConstraintSet() - with(constraintSet) { - clone(rootConstraintLayout) - if (forward) { - clear(secondsView.id, START) - connect( - secondsView.id, END, - PARENT_ID, END - ) - } else { - clear(secondsView.id, END) - connect( - secondsView.id, START, - PARENT_ID, START - ) - } - secondsView.start() - applyTo(rootConstraintLayout) - } - } - - interface PerformListener { - fun onPrepare() {} - fun onAnimationStart() - fun onAnimationEnd() - fun shouldFastForward(portion: DisplayPortion): Boolean? - fun seek(forward: Boolean) - } - - companion object { - private const val TAG = "PlayerSeekOverlay" - private val DEBUG = MainActivity.DEBUG - } -} diff --git a/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt b/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt index 8574d607f..69dd09a07 100644 --- a/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt +++ b/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt @@ -6,10 +6,8 @@ import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater import android.widget.LinearLayout -import android.widget.TextView -import androidx.annotation.DrawableRes import org.schabi.newpipe.R -import org.schabi.newpipe.databinding.PlayerSeekSecondsViewBinding +import org.schabi.newpipe.databinding.PlayerFastSeekSecondsViewBinding class SecondsView(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) { @@ -35,33 +33,17 @@ class SecondsView(context: Context, attrs: AttributeSet?) : LinearLayout(context field = value } - var isForward: Boolean = true - set(value) { - binding.triangleContainer.rotation = if (value) 0f else 180f - field = value - } - - val binding = PlayerSeekSecondsViewBinding.inflate(LayoutInflater.from(context), this) - - val textView: TextView - get() = binding.tvSeconds - - @DrawableRes - var icon: Int = R.drawable.ic_play_seek_triangle - set(value) { - if (value > 0) { - binding.icon1.setImageResource(value) - binding.icon2.setImageResource(value) - binding.icon3.setImageResource(value) - } - field = value - } + val binding = PlayerFastSeekSecondsViewBinding.inflate(LayoutInflater.from(context), this) init { orientation = VERTICAL layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT) } + fun setForwarding(isForward: Boolean) { + binding.triangleContainer.rotation = if (isForward) 0f else 180f + } + fun start() { stop() firstAnimator.start() diff --git a/app/src/main/res/layout-large-land/player.xml b/app/src/main/res/layout-large-land/player.xml index 520c165cb..71a325cf3 100644 --- a/app/src/main/res/layout-large-land/player.xml +++ b/app/src/main/res/layout-large-land/player.xml @@ -647,24 +647,6 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - - - - - - - - - - - + android:focusable="false" /> Date: Tue, 14 Dec 2021 20:44:01 +0100 Subject: [PATCH 012/119] Refactored code --- app/src/main/java/org/schabi/newpipe/player/Player.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index fbfaf7b95..653b226df 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -529,6 +529,10 @@ public final class Player implements binding.resizeTextView.setOnClickListener(this); binding.playbackLiveSync.setOnClickListener(this); + playerGestureListener = new PlayerGestureListener(this, service); + gestureDetector = new GestureDetectorCompat(context, playerGestureListener); + binding.getRoot().setOnTouchListener(playerGestureListener); + binding.queueButton.setOnClickListener(this); binding.segmentsButton.setOnClickListener(this); binding.repeatButton.setOnClickListener(this); @@ -583,10 +587,6 @@ public final class Player implements * Initializes the Fast-For/Backward overlay. */ private void setupPlayerSeekOverlay() { - playerGestureListener = new PlayerGestureListener(this, service); - gestureDetector = new GestureDetectorCompat(context, playerGestureListener); - binding.getRoot().setOnTouchListener(playerGestureListener); - binding.fastSeekOverlay .seekSeconds((int) (retrieveSeekDurationFromPreferences(this) / 1000.0f)) .performListener(new PlayerFastSeekOverlay.PerformListener() { From c25e523df6cbb0a39893d4d1ca4b68248a4ddb5e Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Tue, 14 Dec 2021 20:44:39 +0100 Subject: [PATCH 013/119] Removed all animations to be consistent with the current behavior --- .../java/org/schabi/newpipe/player/Player.java | 16 ---------------- .../views/player/PlayerFastSeekOverlay.kt | 2 -- 2 files changed, 18 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 653b226df..8eadbc821 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -591,30 +591,14 @@ public final class Player implements .seekSeconds((int) (retrieveSeekDurationFromPreferences(this) / 1000.0f)) .performListener(new PlayerFastSeekOverlay.PerformListener() { - @Override - public void onDoubleTabStart() { - // TODO - } - @Override public void onDoubleTab() { animate(binding.fastSeekOverlay, true, SEEK_OVERLAY_DURATION); - animate(binding.playbackControlsShadow, - !simpleExoPlayer.getPlayWhenReady(), SEEK_OVERLAY_DURATION); - animate(binding.playerTopShadow, false, SEEK_OVERLAY_DURATION); - animate(binding.playerBottomShadow, false, SEEK_OVERLAY_DURATION); - animate(binding.playbackControlRoot, false, SEEK_OVERLAY_DURATION); - hideSystemUIIfNeeded(); } @Override public void onDoubleTabEnd() { animate(binding.fastSeekOverlay, false, SEEK_OVERLAY_DURATION); - if (!simpleExoPlayer.getPlayWhenReady()) { - showControls(SEEK_OVERLAY_DURATION); - } else { - showHideShadow(false, SEEK_OVERLAY_DURATION); - } } @Override diff --git a/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt b/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt index 90384264b..f185f5861 100644 --- a/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt +++ b/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt @@ -57,7 +57,6 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : Log.d(TAG, "onDoubleTapStarted called with portion = [$portion]") initTap = false - performListener?.onDoubleTabStart() secondsView.stop() } @@ -122,7 +121,6 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : } interface PerformListener { - fun onDoubleTabStart() {} fun onDoubleTab() fun onDoubleTabEnd() fun shouldFastForward(portion: DisplayPortion): Boolean? From 452fe3a8e2b8b0824a35347679b6617055e142a1 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Tue, 14 Dec 2021 20:52:46 +0100 Subject: [PATCH 014/119] Respect disabled animations --- .../views/player/PlayerFastSeekOverlay.kt | 8 +++---- .../newpipe/views/player/SecondsView.kt | 24 +++++++++++++++---- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt b/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt index f185f5861..a1ea3d901 100644 --- a/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt +++ b/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt @@ -58,7 +58,7 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : initTap = false - secondsView.stop() + secondsView.stopAnimation() } override fun onDoubleTapProgressDown(portion: DisplayPortion) { @@ -86,8 +86,6 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : wasForwarding = shouldForward if (!initTap) { - // Start animation - secondsView.start() initTap = true } } @@ -104,6 +102,8 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : if (initTap) performListener?.onDoubleTabEnd() initTap = false + + secondsView.stopAnimation() } private fun changeConstraints(forward: Boolean) { @@ -115,7 +115,7 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : secondsView.id, if (forward) END else START, PARENT_ID, if (forward) END else START ) - secondsView.start() + secondsView.startAnimation() applyTo(rootConstraintLayout) } } diff --git a/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt b/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt index 69dd09a07..d209d24da 100644 --- a/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt +++ b/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt @@ -8,6 +8,7 @@ import android.view.LayoutInflater import android.widget.LinearLayout import org.schabi.newpipe.R import org.schabi.newpipe.databinding.PlayerFastSeekSecondsViewBinding +import org.schabi.newpipe.util.DeviceUtils class SecondsView(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) { @@ -33,6 +34,9 @@ class SecondsView(context: Context, attrs: AttributeSet?) : LinearLayout(context field = value } + // Done as a field so that we don't have to compute on each tab if animations are enabled + private val animationsEnabled = DeviceUtils.hasAnimationsAnimatorDurationEnabled(context) + val binding = PlayerFastSeekSecondsViewBinding.inflate(LayoutInflater.from(context), this) init { @@ -44,12 +48,18 @@ class SecondsView(context: Context, attrs: AttributeSet?) : LinearLayout(context binding.triangleContainer.rotation = if (isForward) 0f else 180f } - fun start() { - stop() - firstAnimator.start() + fun startAnimation() { + stopAnimation() + + if (animationsEnabled) { + firstAnimator.start() + } else { + // If no animations are enable show the arrow(s) without animation + showWithoutAnimation() + } } - fun stop() { + fun stopAnimation() { firstAnimator.cancel() secondAnimator.cancel() thirdAnimator.cancel() @@ -65,6 +75,12 @@ class SecondsView(context: Context, attrs: AttributeSet?) : LinearLayout(context binding.icon3.alpha = 0f } + private fun showWithoutAnimation() { + binding.icon1.alpha = 1f + binding.icon2.alpha = 1f + binding.icon3.alpha = 1f + } + private val firstAnimator: ValueAnimator = CustomValueAnimator( { binding.icon1.alpha = 0f From 7bf1f3dba6c84e11e994a3603e419eafa85764df Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Thu, 16 Dec 2021 20:09:15 +0100 Subject: [PATCH 015/119] Removed unused field --- app/src/main/java/org/schabi/newpipe/player/Player.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 8eadbc821..a869de4b0 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -314,7 +314,6 @@ public final class Player implements private PlayerBinding binding; - private ValueAnimator controlViewAnimator; private final Handler controlsVisibilityHandler = new Handler(); // fullscreen player From d2aaf152a09dbaf9ee56bcd2ca53eadb25c5bad6 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Thu, 16 Dec 2021 20:14:41 +0100 Subject: [PATCH 016/119] Removed related import --- app/src/main/java/org/schabi/newpipe/player/Player.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index a869de4b0..6352847d3 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -51,7 +51,6 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; -import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.content.BroadcastReceiver; import android.content.Context; From 345ba74d588325167fb9efcccd0a996b063cc981 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 31 Dec 2021 20:58:23 +0100 Subject: [PATCH 017/119] Fixed naming --- .../main/java/org/schabi/newpipe/player/Player.java | 4 ++-- .../newpipe/views/player/PlayerFastSeekOverlay.kt | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 6352847d3..b37dddc7b 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -590,12 +590,12 @@ public final class Player implements .performListener(new PlayerFastSeekOverlay.PerformListener() { @Override - public void onDoubleTab() { + public void onDoubleTap() { animate(binding.fastSeekOverlay, true, SEEK_OVERLAY_DURATION); } @Override - public void onDoubleTabEnd() { + public void onDoubleTapEnd() { animate(binding.fastSeekOverlay, false, SEEK_OVERLAY_DURATION); } diff --git a/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt b/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt index a1ea3d901..23f56fa67 100644 --- a/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt +++ b/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt @@ -74,7 +74,7 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : ) /* - * Check if a initial tab occurred or if direction was switched + * Check if a initial tap occurred or if direction was switched */ if (!initTap || wasForwarding != shouldForward) { // Reset seconds and update position @@ -90,7 +90,7 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : } } - performListener?.onDoubleTab() + performListener?.onDoubleTap() secondsView.seconds += seekSeconds performListener?.seek(forward = shouldForward) @@ -100,7 +100,7 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : if (DEBUG) Log.d(TAG, "onDoubleTapFinished called with initTap = [$initTap]") - if (initTap) performListener?.onDoubleTabEnd() + if (initTap) performListener?.onDoubleTapEnd() initTap = false secondsView.stopAnimation() @@ -121,8 +121,8 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : } interface PerformListener { - fun onDoubleTab() - fun onDoubleTabEnd() + fun onDoubleTap() + fun onDoubleTapEnd() fun shouldFastForward(portion: DisplayPortion): Boolean? fun seek(forward: Boolean) } From f8c52c4dacc89a4dd478a19004191102b2850768 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 31 Dec 2021 21:22:02 +0100 Subject: [PATCH 018/119] Fixed SonarLint problems * Removed alphaRelativeDuration as there is no use for it --- app/src/main/java/org/schabi/newpipe/ktx/View.kt | 8 +------- .../java/org/schabi/newpipe/player/Player.java | 15 +++++++++------ .../newpipe/views/player/PlayerFastSeekOverlay.kt | 6 ++++-- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/ktx/View.kt b/app/src/main/java/org/schabi/newpipe/ktx/View.kt index ae1b4388c..8dcc9d85c 100644 --- a/app/src/main/java/org/schabi/newpipe/ktx/View.kt +++ b/app/src/main/java/org/schabi/newpipe/ktx/View.kt @@ -76,14 +76,8 @@ fun View.animate( animate().setListener(null).cancel() isVisible = true - val alphaRelativeDuration = if (enterOrExit && alpha < 1.0f) { - (duration * (1 - alpha)).toLong() - } else { - (duration * alpha).toLong() - } - when (animationType) { - AnimationType.ALPHA -> animateAlpha(enterOrExit, alphaRelativeDuration, delay, execOnEnd) + AnimationType.ALPHA -> animateAlpha(enterOrExit, duration, delay, execOnEnd) AnimationType.SCALE_AND_ALPHA -> animateScaleAndAlpha(enterOrExit, duration, delay, execOnEnd) AnimationType.LIGHT_SCALE_AND_ALPHA -> animateLightScaleAndAlpha(enterOrExit, duration, delay, execOnEnd) AnimationType.SLIDE_AND_ALPHA -> animateSlideAndAlpha(enterOrExit, duration, delay, execOnEnd) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index b37dddc7b..f7ef13d7a 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -600,22 +600,24 @@ public final class Player implements } @Override - public Boolean shouldFastForward(@NonNull final DisplayPortion portion) { + public Optional shouldFastForward( + @NonNull final DisplayPortion portion + ) { // Null indicates an invalid area or condition e.g. the middle portion // or video start or end was reached during double tap seeking if (invalidSeekConditions()) { playerGestureListener.endMultiDoubleTap(); - return null; + return Optional.empty(); } if (portion == DisplayPortion.LEFT // Small puffer to eliminate infinite rewind seeking && simpleExoPlayer.getCurrentPosition() > 500L) { - return false; + return Optional.of(false); } else if (portion == DisplayPortion.RIGHT) { - return true; + return Optional.of(true); } /* portion == DisplayPortion.MIDDLE */ - return null; + return Optional.empty(); } @Override @@ -630,7 +632,8 @@ public final class Player implements private boolean invalidSeekConditions() { return exoPlayerIsNull() - || simpleExoPlayer.getPlaybackState() == SimpleExoPlayer.STATE_ENDED + || simpleExoPlayer.getPlaybackState() + == com.google.android.exoplayer2.Player.STATE_ENDED || simpleExoPlayer.getCurrentPosition() >= simpleExoPlayer.getDuration() || currentState == STATE_COMPLETED; } diff --git a/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt b/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt index 23f56fa67..5a3eb9a4e 100644 --- a/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt +++ b/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt @@ -13,6 +13,7 @@ import org.schabi.newpipe.MainActivity import org.schabi.newpipe.R import org.schabi.newpipe.player.event.DisplayPortion import org.schabi.newpipe.player.event.DoubleTapListener +import java.util.Optional class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : ConstraintLayout(context, attrs), DoubleTapListener { @@ -62,7 +63,8 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : } override fun onDoubleTapProgressDown(portion: DisplayPortion) { - val shouldForward: Boolean = performListener?.shouldFastForward(portion) ?: return + val shouldForward: Boolean = + performListener?.shouldFastForward(portion)?.orElse(null) ?: return if (DEBUG) Log.d( @@ -123,7 +125,7 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : interface PerformListener { fun onDoubleTap() fun onDoubleTapEnd() - fun shouldFastForward(portion: DisplayPortion): Boolean? + fun shouldFastForward(portion: DisplayPortion): Optional fun seek(forward: Boolean) } From 1c20eabb48f4c9de518a8856f1c8ead2bf3138bc Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Thu, 6 Jan 2022 14:39:12 +0100 Subject: [PATCH 019/119] Code cleanup --- .../java/org/schabi/newpipe/player/Player.java | 10 +++++----- .../views/player/PlayerFastSeekOverlay.kt | 18 ++++++++++++++---- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index f7ef13d7a..431b4bb98 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -600,24 +600,24 @@ public final class Player implements } @Override - public Optional shouldFastForward( + public FastSeekDirection getFastSeekDirection( @NonNull final DisplayPortion portion ) { // Null indicates an invalid area or condition e.g. the middle portion // or video start or end was reached during double tap seeking if (invalidSeekConditions()) { playerGestureListener.endMultiDoubleTap(); - return Optional.empty(); + return FastSeekDirection.NONE; } if (portion == DisplayPortion.LEFT // Small puffer to eliminate infinite rewind seeking && simpleExoPlayer.getCurrentPosition() > 500L) { - return Optional.of(false); + return FastSeekDirection.BACKWARD; } else if (portion == DisplayPortion.RIGHT) { - return Optional.of(true); + return FastSeekDirection.FORWARD; } /* portion == DisplayPortion.MIDDLE */ - return Optional.empty(); + return FastSeekDirection.NONE; } @Override diff --git a/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt b/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt index 5a3eb9a4e..522977317 100644 --- a/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt +++ b/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt @@ -4,6 +4,7 @@ import android.content.Context import android.util.AttributeSet import android.util.Log import android.view.LayoutInflater +import androidx.annotation.NonNull import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.END import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.PARENT_ID @@ -13,7 +14,6 @@ import org.schabi.newpipe.MainActivity import org.schabi.newpipe.R import org.schabi.newpipe.player.event.DisplayPortion import org.schabi.newpipe.player.event.DoubleTapListener -import java.util.Optional class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : ConstraintLayout(context, attrs), DoubleTapListener { @@ -64,7 +64,7 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : override fun onDoubleTapProgressDown(portion: DisplayPortion) { val shouldForward: Boolean = - performListener?.shouldFastForward(portion)?.orElse(null) ?: return + performListener?.getFastSeekDirection(portion)?.directionAsBoolean ?: return if (DEBUG) Log.d( @@ -125,12 +125,22 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : interface PerformListener { fun onDoubleTap() fun onDoubleTapEnd() - fun shouldFastForward(portion: DisplayPortion): Optional + /** + * Determines if the playback should forward/rewind or do nothing. + */ + @NonNull + fun getFastSeekDirection(portion: DisplayPortion): FastSeekDirection fun seek(forward: Boolean) + + enum class FastSeekDirection(val directionAsBoolean: Boolean?) { + NONE(null), + FORWARD(true), + BACKWARD(false); + } } companion object { - private const val TAG = "PlayerSeekOverlay" + private const val TAG = "PlayerFastSeekOverlay" private val DEBUG = MainActivity.DEBUG } } From 30ce906f724f6508dbe976d337690bc880e73b2f Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 21 Jan 2022 21:25:25 +0100 Subject: [PATCH 020/119] Apply seek conditions based on direction * When rewinding: Check if <0,5s * When fast-forwarding: Check if player has completed or the current playback has ended This allows rewinding on the endscreen --- .../org/schabi/newpipe/player/Player.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 431b4bb98..c7bc3db3a 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -603,17 +603,25 @@ public final class Player implements public FastSeekDirection getFastSeekDirection( @NonNull final DisplayPortion portion ) { - // Null indicates an invalid area or condition e.g. the middle portion - // or video start or end was reached during double tap seeking - if (invalidSeekConditions()) { + if (exoPlayerIsNull()) { + // Abort seeking playerGestureListener.endMultiDoubleTap(); return FastSeekDirection.NONE; } - if (portion == DisplayPortion.LEFT - // Small puffer to eliminate infinite rewind seeking - && simpleExoPlayer.getCurrentPosition() > 500L) { + if (portion == DisplayPortion.LEFT) { + // Check if we can rewind + // Small puffer to eliminate infinite rewind seeking + if (simpleExoPlayer.getCurrentPosition() < 500L) { + return FastSeekDirection.NONE; + } return FastSeekDirection.BACKWARD; } else if (portion == DisplayPortion.RIGHT) { + // Check if the can fast-forward + if (currentState == STATE_COMPLETED + || simpleExoPlayer.getCurrentPosition() + >= simpleExoPlayer.getDuration()) { + return FastSeekDirection.NONE; + } return FastSeekDirection.FORWARD; } /* portion == DisplayPortion.MIDDLE */ @@ -629,14 +637,6 @@ public final class Player implements fastRewind(); } } - - private boolean invalidSeekConditions() { - return exoPlayerIsNull() - || simpleExoPlayer.getPlaybackState() - == com.google.android.exoplayer2.Player.STATE_ENDED - || simpleExoPlayer.getCurrentPosition() >= simpleExoPlayer.getDuration() - || currentState == STATE_COMPLETED; - } }); playerGestureListener.doubleTapControls(binding.fastSeekOverlay); } From 54ef604569ea723dbabf588670b27489e2b8fc98 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 21 Jan 2022 21:28:24 +0100 Subject: [PATCH 021/119] Improved docs --- app/src/main/java/org/schabi/newpipe/player/Player.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index c7bc3db3a..029b33b7f 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -609,14 +609,14 @@ public final class Player implements return FastSeekDirection.NONE; } if (portion == DisplayPortion.LEFT) { - // Check if we can rewind + // Check if it's possible to rewind // Small puffer to eliminate infinite rewind seeking if (simpleExoPlayer.getCurrentPosition() < 500L) { return FastSeekDirection.NONE; } return FastSeekDirection.BACKWARD; } else if (portion == DisplayPortion.RIGHT) { - // Check if the can fast-forward + // Check if it's possible to fast-forward if (currentState == STATE_COMPLETED || simpleExoPlayer.getCurrentPosition() >= simpleExoPlayer.getDuration()) { From fa293e3415e47937018de663ac8ae4046fdff4ed Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Thu, 6 Jan 2022 05:42:36 +0100 Subject: [PATCH 022/119] Translated using Weblate (Telugu) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 58.4% (374 of 640 strings) Translated using Weblate (Swedish) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Indonesian) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Italian) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Japanese) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Hungarian) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Sardinian) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Norwegian Bokmål) Currently translated at 94.8% (607 of 640 strings) Translated using Weblate (Swedish) Currently translated at 99.6% (638 of 640 strings) Translated using Weblate (Hebrew) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Persian) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Polish) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Arabic) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Greek) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Basque) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Italian) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Japanese) Currently translated at 99.5% (637 of 640 strings) Translated using Weblate (Russian) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Dutch) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Spanish) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (German) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (German) Currently translated at 100.0% (640 of 640 strings) Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (62 of 62 strings) Translated using Weblate (Swedish) Currently translated at 25.8% (16 of 62 strings) Translated using Weblate (Portuguese) Currently translated at 67.7% (42 of 62 strings) Translated using Weblate (Ukrainian) Currently translated at 82.2% (51 of 62 strings) Translated using Weblate (Telugu) Currently translated at 51.4% (328 of 638 strings) Translated using Weblate (Swedish) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Turkish) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Czech) Currently translated at 97.1% (620 of 638 strings) Translated using Weblate (Japanese) Currently translated at 99.2% (633 of 638 strings) Translated using Weblate (Russian) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (French) Currently translated at 99.5% (635 of 638 strings) Translated using Weblate (French) Currently translated at 99.5% (635 of 638 strings) Translated using Weblate (Santali) Currently translated at 13.9% (89 of 638 strings) Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (62 of 62 strings) Translated using Weblate (Chinese (Traditional)) Currently translated at 59.6% (37 of 62 strings) Translated using Weblate (Portuguese (Portugal)) Currently translated at 66.1% (41 of 62 strings) Translated using Weblate (Persian) Currently translated at 62.9% (39 of 62 strings) Translated using Weblate (Spanish) Currently translated at 58.0% (36 of 62 strings) Translated using Weblate (Dutch) Currently translated at 12.9% (8 of 62 strings) Translated using Weblate (Hebrew) Currently translated at 51.6% (32 of 62 strings) Translated using Weblate (Portuguese) Currently translated at 66.1% (41 of 62 strings) Translated using Weblate (Ukrainian) Currently translated at 80.6% (50 of 62 strings) Translated using Weblate (Dutch) Currently translated at 98.4% (628 of 638 strings) Translated using Weblate (Hindi) Currently translated at 4.9% (3 of 61 strings) Translated using Weblate (Hungarian) Currently translated at 6.5% (4 of 61 strings) Translated using Weblate (Hebrew) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Russian) Currently translated at 99.8% (637 of 638 strings) Translated using Weblate (Hungarian) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (French) Currently translated at 99.3% (634 of 638 strings) Translated using Weblate (Hungarian) Currently translated at 6.5% (4 of 61 strings) Translated using Weblate (Hungarian) Currently translated at 6.5% (4 of 61 strings) Translated using Weblate (Hungarian) Currently translated at 4.9% (3 of 61 strings) Translated using Weblate (Telugu) Currently translated at 51.0% (326 of 638 strings) Translated using Weblate (Italian) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Swedish) Currently translated at 24.5% (15 of 61 strings) Translated using Weblate (Portuguese (Portugal)) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Sardinian) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Croatian) Currently translated at 98.7% (630 of 638 strings) Translated using Weblate (Vietnamese) Currently translated at 99.8% (637 of 638 strings) Translated using Weblate (Swedish) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Hebrew) Currently translated at 99.0% (632 of 638 strings) Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Turkish) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Arabic) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Greek) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Chinese (Traditional, Hong Kong)) Currently translated at 58.4% (373 of 638 strings) Translated using Weblate (Portuguese) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Spanish) Currently translated at 100.0% (638 of 638 strings) Added translation using Weblate (English (Middle)) Translated using Weblate (Dutch) Currently translated at 11.4% (7 of 61 strings) Translated using Weblate (Telugu) Currently translated at 50.6% (323 of 638 strings) Translated using Weblate (Hebrew) Currently translated at 97.9% (625 of 638 strings) Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Persian) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Polish) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Indonesian) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (Greek) Currently translated at 99.8% (637 of 638 strings) Translated using Weblate (Japanese) Currently translated at 98.5% (629 of 638 strings) Translated using Weblate (Russian) Currently translated at 98.1% (626 of 638 strings) Translated using Weblate (French) Currently translated at 98.5% (629 of 638 strings) Translated using Weblate (Spanish) Currently translated at 99.0% (632 of 638 strings) Translated using Weblate (German) Currently translated at 100.0% (638 of 638 strings) Translated using Weblate (English) Currently translated at 100.0% (631 of 631 strings) Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (631 of 631 strings) Translated using Weblate (French) Currently translated at 99.6% (629 of 631 strings) Translated using Weblate (Telugu) Currently translated at 43.2% (273 of 631 strings) Translated using Weblate (Japanese) Currently translated at 99.8% (630 of 631 strings) Translated using Weblate (French) Currently translated at 99.6% (629 of 631 strings) Co-authored-by: Abhishek Kumar Co-authored-by: Agnieszka C Co-authored-by: AioiLight Co-authored-by: Ajeje Brazorf Co-authored-by: Alex25820 Co-authored-by: Alfonso Scarpino Co-authored-by: Allan Nordhøy Co-authored-by: Andreas P Co-authored-by: Andrey F Co-authored-by: Balázs Meskó Co-authored-by: Boros Zsombor Co-authored-by: Calcitem Co-authored-by: Danial Behzadi Co-authored-by: Emin Tufan Çetin Co-authored-by: Florian Co-authored-by: GnuPGを使うべきだ Co-authored-by: Gontzal Manuel Pujana Onaindia Co-authored-by: Hosted Weblate Co-authored-by: Ihor Hordiichuk Co-authored-by: JY3 Co-authored-by: Jeff Huang Co-authored-by: Linerly Co-authored-by: Milo Ivir Co-authored-by: Name Protected Co-authored-by: Prasanta-Hembram Co-authored-by: Ray Co-authored-by: Retrial Co-authored-by: Rex_sa Co-authored-by: Ricardo Co-authored-by: S3aBreeze Co-authored-by: TiA4f8R Co-authored-by: Vasilis K Co-authored-by: VfBFan Co-authored-by: Yaron Shahrabani Co-authored-by: Yuki Monkey Co-authored-by: bomzhellino Co-authored-by: bruh Co-authored-by: chr56 Co-authored-by: evfjunior Co-authored-by: mm4c Co-authored-by: nautilusx Co-authored-by: ndrnry Co-authored-by: nzgha Co-authored-by: nzgha Co-authored-by: pjammo Co-authored-by: ssantos Co-authored-by: subba raidu Co-authored-by: translator Co-authored-by: wmd arg Co-authored-by: zmni Co-authored-by: 刘韬 Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/es/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/fa/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/he/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/hi/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/hu/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/nl/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pt/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pt_PT/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/sv/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/uk/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/zh_Hans/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/zh_Hant/ Translation: NewPipe/Metadata --- app/src/main/res/values-ar/strings.xml | 18 +- .../main/res/values-b+zh+HANS+CN/strings.xml | 38 +- app/src/main/res/values-cs/strings.xml | 6 + app/src/main/res/values-de/strings.xml | 22 +- app/src/main/res/values-el/strings.xml | 16 +- app/src/main/res/values-enm/strings.xml | 2 + app/src/main/res/values-es/strings.xml | 18 +- app/src/main/res/values-eu/strings.xml | 28 +- app/src/main/res/values-fa/strings.xml | 22 +- app/src/main/res/values-fr/strings.xml | 24 +- app/src/main/res/values-he/strings.xml | 22 +- app/src/main/res/values-hr/strings.xml | 15 +- app/src/main/res/values-hu/strings.xml | 629 +++++++++++------- app/src/main/res/values-in/strings.xml | 31 +- app/src/main/res/values-it/strings.xml | 22 +- app/src/main/res/values-ja/strings.xml | 18 +- app/src/main/res/values-nb-rNO/strings.xml | 11 + app/src/main/res/values-nl/strings.xml | 28 +- app/src/main/res/values-pl/strings.xml | 18 +- app/src/main/res/values-pt-rBR/strings.xml | 64 +- app/src/main/res/values-pt-rPT/strings.xml | 18 +- app/src/main/res/values-pt/strings.xml | 18 +- app/src/main/res/values-ru/strings.xml | 20 +- app/src/main/res/values-sat/strings.xml | 4 + app/src/main/res/values-sc/strings.xml | 28 +- app/src/main/res/values-sv/strings.xml | 22 +- app/src/main/res/values-te/strings.xml | 148 ++++- app/src/main/res/values-tr/strings.xml | 65 +- app/src/main/res/values-uk/strings.xml | 52 +- app/src/main/res/values-vi/strings.xml | 21 +- app/src/main/res/values-zh-rHK/strings.xml | 157 ++++- app/src/main/res/values-zh-rTW/strings.xml | 14 +- app/src/main/res/values/strings.xml | 10 +- .../metadata/android/es/changelogs/981.txt | 2 + .../metadata/android/fa/changelogs/981.txt | 2 + .../metadata/android/he/changelogs/981.txt | 2 + .../metadata/android/hi/changelogs/63.txt | 8 + .../metadata/android/hi/full_description.txt | 2 +- .../metadata/android/hu/changelogs/64.txt | 8 + .../metadata/android/hu/full_description.txt | 2 +- .../metadata/android/hu/short_description.txt | 1 + .../metadata/android/nl/changelogs/957.txt | 2 +- .../metadata/android/nl/full_description.txt | 2 +- .../metadata/android/pt-PT/changelogs/968.txt | 7 + .../metadata/android/pt-PT/changelogs/970.txt | 11 + .../metadata/android/pt-PT/changelogs/977.txt | 10 + .../metadata/android/pt-PT/changelogs/978.txt | 1 + .../metadata/android/pt-PT/changelogs/979.txt | 2 + .../metadata/android/pt-PT/changelogs/980.txt | 13 + .../metadata/android/pt-PT/changelogs/981.txt | 2 + .../metadata/android/pt/changelogs/965.txt | 6 + .../metadata/android/pt/changelogs/968.txt | 7 + .../metadata/android/pt/changelogs/970.txt | 11 + .../metadata/android/pt/changelogs/980.txt | 13 + .../metadata/android/pt/changelogs/981.txt | 2 + .../metadata/android/sv/changelogs/980.txt | 13 + .../metadata/android/sv/changelogs/981.txt | 2 + .../metadata/android/uk/changelogs/930.txt | 19 + .../metadata/android/uk/changelogs/951.txt | 4 +- .../metadata/android/uk/changelogs/958.txt | 2 +- .../metadata/android/uk/changelogs/981.txt | 2 + .../android/zh-Hans/changelogs/981.txt | 2 + .../android/zh-Hans/full_description.txt | 2 +- .../android/zh-Hant/changelogs/981.txt | 2 + 64 files changed, 1351 insertions(+), 442 deletions(-) create mode 100644 app/src/main/res/values-enm/strings.xml create mode 100644 fastlane/metadata/android/es/changelogs/981.txt create mode 100644 fastlane/metadata/android/fa/changelogs/981.txt create mode 100644 fastlane/metadata/android/he/changelogs/981.txt create mode 100644 fastlane/metadata/android/hi/changelogs/63.txt create mode 100644 fastlane/metadata/android/hu/changelogs/64.txt create mode 100644 fastlane/metadata/android/hu/short_description.txt create mode 100644 fastlane/metadata/android/pt-PT/changelogs/968.txt create mode 100644 fastlane/metadata/android/pt-PT/changelogs/970.txt create mode 100644 fastlane/metadata/android/pt-PT/changelogs/977.txt create mode 100644 fastlane/metadata/android/pt-PT/changelogs/978.txt create mode 100644 fastlane/metadata/android/pt-PT/changelogs/979.txt create mode 100644 fastlane/metadata/android/pt-PT/changelogs/980.txt create mode 100644 fastlane/metadata/android/pt-PT/changelogs/981.txt create mode 100644 fastlane/metadata/android/pt/changelogs/965.txt create mode 100644 fastlane/metadata/android/pt/changelogs/968.txt create mode 100644 fastlane/metadata/android/pt/changelogs/970.txt create mode 100644 fastlane/metadata/android/pt/changelogs/980.txt create mode 100644 fastlane/metadata/android/pt/changelogs/981.txt create mode 100644 fastlane/metadata/android/sv/changelogs/980.txt create mode 100644 fastlane/metadata/android/sv/changelogs/981.txt create mode 100644 fastlane/metadata/android/uk/changelogs/930.txt create mode 100644 fastlane/metadata/android/uk/changelogs/981.txt create mode 100644 fastlane/metadata/android/zh-Hans/changelogs/981.txt create mode 100644 fastlane/metadata/android/zh-Hant/changelogs/981.txt diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index d8604e804..d996feeb5 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -98,7 +98,7 @@ تراجع تشغيل الكل تنبيهات NewPipe - تنبيهات مشغل NewPipe للخلفية والنوافذ المنبثقة + تنبيهات مشغل NewPipe [غير معروف] تعذر إعداد قائمة التنزيل تعطل التطبيق / واجهة المستخدم @@ -353,7 +353,7 @@ استخدام الإيماءات للتحكم بسطوع المشغّل التحديثات تم حذف الملف - تتبيه تحديث التطبيق + تنبيه تحديث التطبيق إيماء التحكم بالصوت الأحداث إشعارات لإصدار NewPipe الجديد @@ -637,7 +637,7 @@ هذا المحتوى غير متوفر في بلدك. اغلق التطبيق قسريا هذا الفيديو مقيد بالفئة العمرية. -\nنظرا لسياسات YouTube الجديدة المتعلقة بمقاطع الفيديو المقيدة بالفئة العمرية، لا يمكن ل NewPipe الوصول إلى أي من مقاطع الفيديو الخاصة بها وبالتالي يتعذر تشغيلها. +\nنظرا لسياسات YouTube الجديدة المتعلقة بمقاطع الفيديو المقيدة بالفئة العمرية، لا يمكن ل NewPipe الوصول إلى أي من مقاطع الفيديو الخاصة بها وبالتالي لا يمكن تشغيلها. إذاعة المميزة حل @@ -726,4 +726,16 @@ إظهار \"تعطل المشغل\" تحطيم المشغل رفع تقرير لأخطاء المشغل بالتفصيل الكامل بدلا من إظهار رسالة اشعار قصيرة الأجل (مفيدة لتشخيص المشاكل) + إشعار الإبلاغ عن الأخطاء + التنبيهات المتعلقة بالإبلاغ عن الأخطاء + واجه NewPipe خطأ، اضغط للتقرير + حدث خطأ ، انظر للإشعار + قم بإنشاء تنبيه بالخطأ + لم يتم العثور على مدير ملفات مناسب لهذا الإجراء. +\nالرجاء تثبيت مدير ملفات أو محاولة تعطيل \"%s\" في إعدادات التنزيل. + إظهار خطأ snackbar + لم يتم العثور على مدير ملفات مناسب لهذا الإجراء. +\nالرجاء تثبيت مدير ملفات متوافق مع Storage Access Framework. + يتم تشغيله في الخلفية + تعليق مثبت \ 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 52bdc2b2e..34043af94 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 @@ -33,7 +33,7 @@ %s 个视频 - 停用 + 已停用 后台播放 显示搜索建议 订阅 @@ -58,7 +58,7 @@ 更新 文件已删除 无法得知订阅人数 - 发布新版本时,通知我升级应用 + 有新版本时,显示通知提示更新应用 网格 NewPipe 可更新! 服务器不接受多线程下载, 使用 @string/msg_threads = 1 重试 @@ -148,7 +148,7 @@ App/UI 崩溃 抱歉, 这本不该发生。 使用电子邮件反馈错误 - 抱歉, 发生了一些错误。 + 抱歉,发生了一些错误。 反馈 信息: 发生了什么: @@ -174,7 +174,7 @@ 部分分辨率下没有音频 选择搜索时显示的建议 最佳分辨率 - 开源且小巧的 Android 媒体播放器。 + 自由且小巧的 Android 媒体播放器。 在 GitHub 上查看 NewPipe 的许可证 你是否想过要翻译、设计、清理或重构代码——我们始终欢迎你来贡献! @@ -194,7 +194,7 @@ 历史记录 历史记录 NewPipe 通知 - NewPipe 在后台播放和悬浮窗播放时在通知栏中显示通知 + NewPipe 播放器的通知 默认视频格式 行为 空空如也 @@ -249,7 +249,7 @@ 导入成功 没有有效的 ZIP 文件 警告:无法导入所有文件。 - 此操作会覆盖当前设置 + 此操作会覆盖当前设置。 显示信息 收藏 最近观看 @@ -272,8 +272,8 @@ 缩放画面 调试 自动生成 - 『内存泄漏监视』可能导致应用在『核心转储』时无响应 - 报告『提前结束Android生命周期』错误 + 内存泄漏监测可能会导致应用在堆转储时无响应 + 报告超出生命周期的错误 强制报告处理后的未送达的 Activity 或 Fragment 生命周期之外的 Rx 异常 使用快速寻址(不精确) 快速寻址定位允许播放器以较低精确度为代价换取更快的寻址定位速度。此功能不适用于以 5、15 或 25 秒为隔的寻址定位 @@ -300,8 +300,8 @@ \n3. 单击“包含所有数据”,然后单击“取消全选”,然后仅选择“订阅”并单击“确定” \n4. 点击“下一步”,然后点击“创建导出作业” \n5. 出现“下载”按钮后点击它 -\n6. 单击下面的导入文件并选择下载的 zip 文件 -\n7.【如果 zip 导入失败】解压 .csv文件(通常在“YouTube和YouTube Music/subscriptions/subscriptions.csv”下),点击下方的导入文件,选择解压出来的 csv 文件 +\n6. 单击下面的导入文件并选择下载的 .zip 文件 +\n7.(如果 .zip 导入失败)解压 .csv文件(通常在“YouTube和YouTube Music/subscriptions/subscriptions.csv”下),点击下方的导入文件,选择解压出来的 csv 文件 通过输入网址或你的 ID 导入 SoundCloud 配置文件: \n \n1. 在浏览器中启用“电脑模式“(该网站未适配移动设备); @@ -332,7 +332,7 @@ 清空搜索历史关键词 是否删除全部搜索历史? 搜索历史已删除 - NewPipe 是版权自由软件:您可以随时使用、研究共享和改进它。您可以根据自由软件基金会发布的 GNU 通用公共许可证 GPLv3 或(由您选择的)任何更高版本的许可证重新分发或修改该许可证。 + NewPipe 是 Copyleft 的自由软件:您可以随时使用、研究共享和改进它。您可以根据自由软件基金会发布的 GNU 通用公共许可证 GPLv3 或(由您选择的)任何更高版本的许可证重新分发或修改该许可证。 是否要导入设置? NewPipe 隐私政策 NewPipe 项目非常重视您的隐私。因此,未经您的同意,应用程序不会收集任何数据。 @@ -358,7 +358,7 @@ 使用手势控制播放器的亮度 视频默认语言 应用更新通知 - 当 NewPipe 有新版本时发送通知 + NewPipe 新版本的通知 外置存储不可用 无法下载到外部 SD 卡,修改下载文件夹位置? 读取已保存标签时发生错误,因此使用默认标签 @@ -521,7 +521,7 @@ 移除看过的视频? 移除看过的视频 来自服务的原始文本将在串流项目中可见 - 显示原始时间 + 在项目上显示原始时间 启用 YouTube“受限模式” 仅显示未分组订阅 播放列表页 @@ -666,4 +666,16 @@ 在使用播放器时显示一个崩溃选项 使播放器崩溃 报告播放器错误 + 错误报告通知 + 提示报告错误的通知 + 发生错误,详见通知 + 显示错误警示SnackBar + 创建一条错误通知 + 找不到适合此操作的文件管理器。 +\n请安装一文件管理器或尝试在下载设置中禁用“%s”。 + 找不到适合此操作的文件管理器。 +\n请安装与存储访问框架(SAF)兼容的文件管理器。 + NewPipe 遇到了一个错误,点击此处报告此错误 + 已经在后台播放 + 置顶评论 \ No newline at end of file diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 781b60704..467d40599 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -681,4 +681,10 @@ Tažením položky odstraníte Spustit hlavní přehrávač na celé obrazovce Zpracovávám... může trvat moment + Ručně zkontrolovat zda je k dispozici nová verze + Kontrola aktualizací + NewPipe narazil na problém, klikněte pro nahlášení + Došlo k chybě, více v oznámení + Vytvořit oznámení o chybě + Kontrola aktualizací… \ 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 551df1263..3e2a881ad 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -139,7 +139,7 @@ Abonnement konnte nicht aktualisiert werden Nach Unterbrechungen (z.B. Telefonaten) Wiedergabe fortsetzen NewPipe-Benachrichtigung - Benachrichtigungen für NewPipe-Hintergrund- und Pop-up Wiedergabe + Benachrichtigungen für den NewPipe-Player Verhalten Verlauf und Cache Rückgängig machen @@ -344,8 +344,8 @@ Gesten verwenden, um die Helligkeit einzustellen Aktualisierungen Datei gelöscht - Aktualisierungsbenachrichtigung - Benachrichtigung bei neuer NewPipe-Version + Benachrichtigung über App-Update + Benachrichtigungen über neue NewPipe-Versionen Kein externer Speicher verfügbar Herunterladen auf externe SD-Karte ist nicht möglich. Downloadordner zurücksetzen\? Konnte gespeicherte Tabs nicht lesen, daher werden die Voreinstellungen genutzt @@ -582,8 +582,8 @@ Vorschaubild für Sperrbildschirmhintergrund und Benachrichtigungen verwenden Vorschaubild anzeigen Hash wird berechnet - Benachrichtigungen für den Video-hashing Fortschritt - Video Hash Benachrichtigung + Benachrichtigungen über den Hashing-Fortschritt von Videos + Video-Hash Benachrichtigung Letzte Metadaten anzeigen Deaktiviere diese Option, um Meta-Infofelder mit zusätzlichen Informationen zum Stream-Ersteller, zum Stream-Inhalt oder zu einer Suchanforderung auszublenden @@ -678,4 +678,16 @@ Meldet Playerfehler mit allen Details, anstatt eine kurzlebige Popupmeldung anzuzeigen (nützlich für die Diagnose von Problemen) Zeigt eine Absturzoption an, wenn der Player verwendet wird Playerfehler melden + Benachrichtigung über Fehlerberichte + Benachrichtigungen zur Meldung von Fehlern + Bei NewPipe ist ein Fehler aufgetreten. Zum Melden antippen + Ein Fehler ist aufgetreten, siehe die Benachrichtigung + Eine Fehlermeldung erstellen + Fehler-Kurzmeldung anzeigen + Es wurde kein geeigneter Dateimanager für diese Aktion gefunden. +\nBitte installiere einen Dateimanager oder versuche, \'%s\' in den Downloadeinstellungen zu deaktivieren. + Es wurde kein geeigneter Dateimanager für diese Aktion gefunden. +\nBitte installiere einen Storage Access Framework kompatiblen Dateimanager. + Wird bereits im Hintergrund abgespielt + Angehefteter Kommentar \ 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 12c3161e1..b8a3277c5 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -130,7 +130,7 @@ Μόνο μία φορά Αρχείο Ειδοποίηση NewPipe - Ειδοποιήσεις αναπαραγωγής παρασκηνίου και αναδυόμενου παραθύρου + Ειδοποιήσεις του αναπαραγωγέα του NewPipe [Άγνωστο] Αλλαγή σε Παρασκήνιο Αλλαγή σε Αναδυόμενο Παράθυρο @@ -343,7 +343,7 @@ Ενημερώσεις Συμβάντα Το αρχείο διαγράφηκε - Ειδοποίηση Ενημέρωσης Εφαρμογής + Ειδοποίηση ενημέρωσης εφαρμογής Ειδοποίηση για νεότερη έκδοση του NewPipe Εξωτερική μνήμη αποθήκευσης μη διαθέσιμη Η αποθήκευση στην SD κάρτα δεν είναι δυνατή. Επαναφορά στην αρχική τοποθεσία λήψης; @@ -678,4 +678,16 @@ Αναφορά σφαλμάτων αναπαραγωγέα Αναφορά σφαλμάτων αναπαραγωγέα με λεπτομέρειες αντί για ένα σύντομο μήνυμα (χρήσιμο για διάγνωση προβλημάτων) Κατάρρευση αναπαραγωγέα + Ειδοποίηση αναφοράς σφάλματος + Ειδοποιήσεις για την αναφορά σφαλμάτων + Συνέβη ένα σφάλμα. Δείτε την ειδοποίηση + Δημιουργία ειδοποίησης σφάλματος + Δε βρέθηκε κατάλληλος διαχειριστής αρχείων για αυτή την ενέργεια. +\nΕγκαταστήστε έναν ή δοκιμάστε να απενεργοποιήσετε το \'%s\' στις ρυθμίσεις λήψεων. + Δε βρέθηκε κατάλληλος διαχειριστής αρχείων για αυτή την ενέργεια. +\nΕγκαταστήστε έναν συμβατό με το Πλαίσιο Πρόσβασης Αποθήκευσης. + Το NewPipe παρουσίασε ένα σφάλμα. Πατήστε για αναφορά + Εμφάνιση μιας snackbar σφάλματος + Αναπαράγεται ήδη στο παρασκήνιο + Καρφιτσωμένο σχόλιο \ No newline at end of file diff --git a/app/src/main/res/values-enm/strings.xml b/app/src/main/res/values-enm/strings.xml new file mode 100644 index 000000000..a6b3daec9 --- /dev/null +++ b/app/src/main/res/values-enm/strings.xml @@ -0,0 +1,2 @@ + + \ 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 a7e8db4ba..11d4aa494 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -139,7 +139,7 @@ Historial Historial Notificación de NewPipe - Notificaciones para reproductores en segundo plano y emergentes de NewPipe + Notificaciones para el reproductor de NewPipe Reproductor Funcionamiento Historial y caché @@ -396,7 +396,7 @@ Actualizaciones Eventos Notificación de actualización de la aplicación - Notificaciones de versiones nuevas de NewPipe + Notificaciones de nuevas versiones de NewPipe Almacenamiento externo no disponible No es posible descargar a una tarjeta SD externa. \¿Restablecer la ubicación de la carpeta de descarga\? No se pudo leer las pestañas guardadas, se usarán las pestañas predefinidas @@ -589,7 +589,7 @@ Transmisiones relacionadas Comentarios Notificaciones sobre el progreso del hashing del vídeo - Notificación del hash de vídeo + Notificación de hash de vídeo Mostrar metainformación Mostrar descripción Abrir con @@ -681,4 +681,16 @@ Muestra una opción de cierre abrupto al usar el reproductor Informar de errores del reproductor con detalle en lugar de mostrar un mensaje emergente efímero (útil para diagnosticar problemas) Mostrar \"Cerrar abruptamente el reproductor\" + Notificaciones para informar errores + Notificación de informe de errores + NewPipe ha detectado un error, pulse aquí para informar + Se produjo un error, vea la notificación + Crear una notificación de error + Mostrar un snackbar de error + No se encontró ningún gestor de archivos adecuado para esta acción. +\nPor favor instale un gestor de archivos o intente deshabilitar \"%s\" en lo ajustes de descargas. + No se encontró ningún gestor de archivos adecuado para esta acción. +\nPor favor instale un gestor de archivos compatible con \"Sistema de Acceso al Almacenamiento\". + Comentario fijado + Ya se reproduce en segundo plano \ 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 759499025..5d2fe379a 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -141,7 +141,7 @@ Portaera Historia eta cache-a Desegin - Atzeko planoko eta laster-leihoko NewPipe erreproduzigailuen jakinarazpenak + NewPipe erreproduzigailuaren jakinarazpenak Emaitzarik ez Kilkerrak besterik ez daude hemen Harpidedunik ez @@ -217,7 +217,7 @@ Ezabatu cacheko metadatuak Kendu cachetik webguneen datu guztiak Metadatuen cachea ezabatuta - Gehitu ilarara hurrengo jarioa + Gehitu hurrengo jarioa ilarara Jarraitu bukaerako (errepikapenik gabe) ilara erlazionatutako jario bat gehituz Arazketa Fitxategia @@ -292,7 +292,7 @@ \n4. Egin klik \"Hurrengo pausua\"-n eta \"Sortu esportazioa\" \n5. Egin klik \"Deskargatu\" botoian agertzen denean \n6. Egin klik INPORTATU FITXATEGIA botoian eta hautatu deskargatutako zip fitxategia -\n6. [Zip inportazioak huts egiten badu] Erauzi .csv fitxategia deskargatutako takeout zip-etik (normalean \"Youtube eta Youtube Music/harpidetzak/harpidetzak.csv\"), egin klik INPORTATU FITXATEGIA botoian eta hautatu erauzitako csv fitxategia +\n7. [.zip inportazioak huts egiten badu] Erauzi .csv fitxategia deskargatutako takeout zip-etik (normalean \"Youtube eta Youtube Music/harpidetzak/harpidetzak.csv\"), egin klik INPORTATU FITXATEGIA botoian eta hautatu erauzitako csv fitxategia Inportatu SoundCloud profila URL-a edo zure ID-a idatziz: \n \n1. Gaitu \"mahaigain modua\" web nabigatzailean (gunea ez dabil mugikorretan) @@ -343,7 +343,7 @@ Eguneraketak Gertaerak Fitxategia ezabatu da - Aplikazioaren eguneraketaren jakinarazpena + Aplikazioaren eguneraketen jakinarazpena NewPipe aplikazioaren bertsio berrien jakinarazpena Kanpo biltegiratzea ez dago eskuragarri Ezin da SD txartel batera deskargatu. Deskargen karpeta berrezarri nahi duzu\? @@ -668,4 +668,24 @@ Hasi erreproduzitzaile nagusia pantaila osoan Isatsari bideo hau erantsita Gehitu bideo hau isatsari + Erakutsi \"itxi erreproduzigailua\" + Prozesatzen... Itxoin mesedez + Atzeko planoan erreproduzitzen dagoeneko + Erroreen txostenen jakinarazpena + Jakinarazpenak erroreen berri emateko + NewPipe-k errore bat aurkitu du, sakatu berri emateko + Errore bat gertatu da, ikusi jakinarazpena + Bilatu eguneraketak + Bilatu bertsio berriak eskuz + Elementu berriak jarioan + Ez da fitxategi kudeatzaile bat aurkitu ekintza honetarako. +\nMesedez, instalatu Storage Access Framework-ekin bateragarria den fitxategi kudeatzaile bat. + Ainguratutako iruzkina + Itxi erreproduzigailua + Eguneraketak bilatzen… + Ez da fitxategi kudeatzaile bat aurkitu ekintza honetarako. +\nMesedez, instalatu fitxategi kudeatzaile bat edo saiatu \'%s\' desgaitzen deskarga ezarpenetan. + Erreproduzigailua erabiltzean ustekabean ixteko aukera ematen du + Erakutsi errore barra bat + Sortu errore jakinarazpen bat \ No newline at end of file diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index 826f76a88..d6569e137 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -116,7 +116,7 @@ همیشه فقط یک‌بار پرونده - اعلان نیوپایپ + آگاهی نیوپایپ [ناشناخته] وارد کردن پایگاه‌داده صادرکردن @@ -246,8 +246,8 @@ می‌خواهید تنظیمات را نیز وارد کنید؟ گام پرونده پاک شد - اعلان به‌روزرسانی کاره - اعلان‌ها برای نسخه جدید نیوپایپ + آگاهی به‌روزرسانی کاره + آگاهی‌ها برای نگارش‌های جدید نیوپایپ بازنشانی پیش‌فرض‌ها می‌خواهید پیش‌فرض‌ها را بازنشانی کنید؟ به‌روزرسانی‌ها @@ -280,7 +280,7 @@ نمایش شاخص موقعیت پخش در فهرست‌ها پاک کردن داده‌ها پخش بعد از قطع ناگهانی (مثل برقراری تماس) ادامه یابد - نمایش نکته «برای افزودن، نگه‌دارید» + نمایش نکته «برای صف‌گذاری، نگه‌دارید» نمایش راهنما هنگام فشردن پس زمینه یا دکمهٔ تصویر در تصویر در «جزییات:» ویدیو برای در صف قرار دادن، نگه دارید کنترل اشاره ای صدا @@ -297,7 +297,7 @@ پروانه‌های شخص سوم © %1$s توسط %2$s تحت %3$s اگر ایده‌ای برای ترجمه، تغییر طراحی، پاک‌سازی کد و یا تغییرات واقعا سنگین کدنویسی دارید، از کمک‌تان همواره استقبال می‌کنیم. هر چه بیشتر کار کنیم، نتایج بهتری می‌گیریم! - آگاهی‌ها برای پخش‌کنندهٔ پس‌زمینه و تصویر در تصویر نیوپایپ + آگاهی‌ها برای پخش‌کنندهٔ نیوپایپ چیزی جز کریکت اینجا نیست فاقد مشترک خطای عدم احیای پخش‌کننده رخ داد @@ -678,4 +678,16 @@ نمایش یک گزینهٔ فروپاشی هنگام استفاده از پخش کننده گزارش خطاهای پخش کننده با جزییات کامل به جای نشان دادن پیامی با عمر کوتاه (مناسب برای تشخیص مشکلات) نمایش «فروپاشی پخش کننده» + مدیر پروندهٔ مناسبی برای این کنش یافت نشد. +\nلطفاً مدیر پرونده‌ای نصب کرده یا در تنظیمات بارگیری، «%s» را خاموش کنید. + آگاهی گزارش خطا + آگاهی برای گزارش‌خطاها + نمایش یک نوار خطا + ایجاد یک آگاهی خطا + مدیر پروندهٔ مناسبی برای این کنش یافت نشد. +\nلطفاً مدیر پرونده‌ای سازگار با چارچوب‌دسترسی ذخیره‌ساز نصب کنید. + نیوپایپ به خطایی برخورد. برای گزارش، بزنید + خطایی رخ داد. آگاهی را ببینید + نظر سنجاق شده + در حال پخش در پس‌زمینه \ 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 8b32afdca..f27d9b4e7 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -142,7 +142,7 @@ Lecteur Comportement Historique et cache - Notifications pour les lecteurs en arrière-plan et flottant de NewPipe + Notifications pour le lecteur de NewPipe Aucun résultat Aucun contenu Aucun abonné @@ -343,7 +343,7 @@ Mises à jour Fichier supprimé Notification de mise à jour de l’application - Notifications pour une nouvelle version de NewPipe + Notifications pour des nouvelles versions de NewPipe Stockage externe indisponible Restaurer les valeurs par défaut Voulez-vous restaurer les valeurs par défaut \? @@ -675,9 +675,19 @@ Vérification des mises à jour… Vérifier les mises à jours Nouveaux éléments du flux - Reporter les erreurs du lecteur en détail au lieu de montrer un bref message éphémère (utile pour diagnostiquer les problèmes) - Reporter des erreurs du lecteur - Couper le lecteur - Montrer \"Couper le lecteur\" - Montrer une option couper lors de l\'utilisation du lecteur + Signaler les erreurs du lecteur de manière détaillée au lieu de montrer un bref message éphémère (utile pour diagnostiquer les problèmes) + Signaler les erreurs du lecteur + Faire planter le lecteur + Afficher « Faire planter le lecteur » + Montrer une option de plantage lors de l\'utilisation du lecteur + Notification de rapport d\'erreur + Notifications pour signaler les erreurs + NewPipe a rencontré une erreur, appuyez pour la signaler + Une erreur s\'est produite, voir la notification + Créer une notification d\'erreur + Aucun gestionnaire de fichiers approprié n\'a été trouvé pour cette action. +\nVeuillez installer un gestionnaire de fichiers compatible avec l\'Infrastructure d\'accès au stockage. + Montrer une erreur en bas de l\'écran + Aucun gestionnaire de fichier approprié n\'a été trouvé pour cette action. +\nVeuillez installer un gestionnaire de fichier ou essayez de désactiver \'%s\' dans les paramètres de téléchargement. \ 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 b7c4bb0fe..8aa6a5136 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -98,7 +98,7 @@ ביטול לנגן הכול התראה מ־NewPipe - התראות עבור נגן הרקע והנגן הצף של NewPipe + התראות עבור הנגן של NewPipe [לא ידוע] נגינת התזרים לא הצליחה אירעה תקלה בנגן ממנה לא ניתן להשתקם @@ -265,8 +265,8 @@ \n3. ללחוץ על „All data included”, ואז על „Deselect all”, לאחר מכן לבחור רק את „subscriptions” וללחוץ על „OK” \n4. ללחוץ על „Next step” ואז על „Create export” \n5. ללחוץ על כפתור ה־„Download” כשהוא מופיע -\n6. ללחוץ על „ייבוא קובץ” להלן ולבחור בקובץ ה־zip שהורדת -\n7. (אם ייבוא ה־zip נכשל) יש לחלץ את קובץ ה־‎.csv (בדרך כלל תחת „YouTube and YouTube Music/subscriptions/subscriptions.csv”), ללחוץ על „ייבוא קובץ” להלן וללחוץ על קובץ ה־csv שחולץ +\n6. ללחוץ על „ייבוא קובץ” להלן ולבחור בקובץ ה־‎.zip שהורדת +\n7. (אם ייבוא ה־‎.zip נכשל) יש לחלץ את קובץ ה־‎.csv (בדרך כלל תחת „YouTube and YouTube Music/subscriptions/subscriptions.csv”), ללחוץ על „ייבוא קובץ” להלן וללחוץ על קובץ ה־csv שחולץ קצב שימוש בחיפוש מהיר ולא מדויק חיפוש גס מאפשר לנגן לחפש נקודת זמן מהר יותר, ברמת דיוק נמוכה יותר. חיפוש של 5, 15 או 25 שניות לא עובד עם ההגדרה הזאת @@ -336,7 +336,7 @@ עדכונים קובץ נמחק התראת עדכון יישומון - התראות על גרסה חדשה של NewPipe + התראות על גרסאות חדשות של NewPipe האחסון החיצוני אינו זמין אין אפשרות להוריד לכרטיס SD. לאפס את מיקום תיקיית ההורדה\? לא ניתן לקרוא לשוניות שמורות, לכן נעשה שימוש באלו של ברירת המחדל @@ -566,7 +566,7 @@ להתחיל לנגן אוטומטית — %s לנגן את התור לא ניתן לזהות את הכתובת. לפתוח אותה ביישומון אחר\? - תור אוטומטי + הוספה אוטומטית לתור התור מהנגן הפעיל יוחלף מעבר מנגן אחד למשנהו עלול להחליף את התור שלך לבקש אישור לפני מחיקת התור @@ -702,4 +702,16 @@ דיווח על שגיאות בנגן מדווח על שגיאות בנגן בפירוט מלא במקום להציג הודעה שקופצת למסך לזמן קצר (יעיל לניתוח תקלות) הצגת אפשרות קריסה בעת שימוש בנגן + התראות לדיווח על שגיאות + הצגת חלונית בזק עם שגיאה + יצירת התראת שגיאה + NewPipe נתקל בשגיאה, לחיצה תדווח על כך + אירעה שגיאה, נא לקרוא את ההתראה + לא נמצא מנהל קבצים מתאים לפעולה זו. +\nנא להתקין מנהל קבצים או לנסות להשבית את ‚%s’ בהגדרות ההורדה. + התראת דיווח שגיאה + לא נמצאו מנהלי קבצים שמתאימים לפעולה הזאת. +\nנא להתקין מנהל קבצים שתומך בתשתית גישה לאחסון. + כבר מתנגן ברקע + הערה ננעצה \ No newline at end of file diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 37e9e9d02..09c85052c 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -139,7 +139,7 @@ Povijest Povijest NewPipe obavijest - Obavijesti za NewPipe pozadinske i skočne reproduktore + Obavijesti za NewPipe reproduktore Reproduktor Ponašanje Povijest i predmemorija @@ -280,8 +280,8 @@ \n3. Pritisni „Uključeni svi podaci”, zatim „Poništi odabir svih”, a zatim odaberi samo „pretplate” i pritisni „U redu” \n4. Pritisni na „Nastavi”, a zatim „Stvori izvoz” \n5. Pritisni na „Preuzmi” -\n6. Dolje pritisni na UVEZI DATOEKU i odaberi zip datoteku za peuzimanje -\n7. [Ako uvoz zip datoteke ne uspije] Izdvoji .csv datoteku (pod \"YouTube and YouTube Music/subscriptions/subscriptions.json\"). Dolje pritisni UVEZI DATOTEKU i odaberi izdvojenu csv datoteku +\n6. Dolje pritisni na UVEZI DATOEKU i odaberi .zip datoteku za peuzimanje +\n7. [Ako uvoz .zip datoteke ne uspije] Izdvoji .csv datoteku (pod \"YouTube and YouTube Music/subscriptions/subscriptions.json\"). Dolje pritisni UVEZI DATOTEKU i odaberi izdvojenu csv datoteku vašID, soundcloud.com/vašID Uzmite u obzir da ova operacija može uzrokovat veliku potrošnju prometa. \n @@ -304,7 +304,7 @@ Ažuriranja Događaji Datoteka obrisana - Obavijest za novu verziju NewPipe-a + Obavijest za nove NewPipe verzije Briše povijest ključnih riječi pretraživanja Vanjska pohrana nije dostupna Ažuriranja @@ -684,4 +684,11 @@ Prijedlozi lokalne pretrage Traži nove verzije Nemoj pokretati videa u mini reproduktoru, već se izravno pokreni cjeloekranski prikaz, ako je automatsko okretanje zaključano. Mini reproduktoru i dalje možeš pristupiti izlaskom iz cjeloekranskog prikaza + Novi feedovi + Obavijest o prijavi greške + Obavijesti za prijavu grešaka + Stvori obavijest o grešci + NewPipe je naišao na grešku, dodirni za prijavu + Došlo je do greške, pogledaj obavijest + Prekini rad playera \ No newline at end of file diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 58939138d..cc398b4d9 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -1,7 +1,7 @@ Közzétéve: %1$s - Nem megfelelő médialejátszó. Szeretné telepíti a VLC médialejátszót\? + Nem található megfelelő médialejátszó. Telepíti a VLC-t\? Telepítés Mégse Megnyitás böngészőben @@ -9,75 +9,75 @@ Letöltés Keresés Beállítások - Erre gondoltál: %1$s\? + Erre gondolt: „%1$s”\? Megosztás ezzel Videofájlok letöltési mappája - A letöltött videók itt lesznek tárolva + A letöltött videófájlok itt lesznek tárolva Válasszon letöltési mappát a videófájloknak Alapértelmezett felbontás - Lejátszás Kodi-val - Telepíted a Kore lejátszót\? - \"Lejátszás Kodi-val\" opció mutatása - Opció mutatása a videók Kodi médiaközponttal való lejátszására + Lejátszás Kodival + Telepíti a hiányzó Kore alkalmazást\? + A „Lejátszás Kodival” lehetőség megjelenítése + A videók Kodi médiaközponttal történő lejátszásának megjelenítése Hang - Alapértelmezett hang formátum + Alapértelmezett hangformátum Letöltés - Nem támogatott webcím + Nem támogatott URL Külső videólejátszó használata Külső hanglejátszó használata - Válaszd ki a hangfájlok letöltési helyét + Válassza ki a hangfájlok letöltési helyét Hálózati hiba - Lejátszás háttérben + Lejátszás a háttérben Videó és hang Megjelenés - Tartalom preferált nyelve - \'Következő\' és \'Hasonló\' videók mutatása + Tartalom alapértelmezett nyelve + „Következő” és „Hasonló” videók megjelenítése Sötét Világos Téma Hangfájlok letöltési mappája - A letöltött hangfájlok itt találhatóak + A letöltött hangfájlok itt lesznek tárolva Tetszik Nem tetszik Videó lejátszása, hossz: - Fetöltő profilképe + Fetöltő profilképének bélyegképe Tartalom Korhatáros tartalom megjelenítése Hiba - A tartalom nem elérhető + A tartalom nem érhető el Élő Jelentés Információ: Ez történt: - Megjegyzésed (angolul): + Az Ön megjegyzése (angolul): Részletek: - Sajnos hiba történt. + Elnézet, valami balul sült el. Elnézést, ennek nem kellett volna megtörténnie. Hiba bejelentése e-mailben - Nem sikerült a letöltés menü beállítása - Nem sikerült a videó URL aláírás azonosítása + Nem sikerült a letöltési menü beállítása + Nem sikerült a videó URL aláírásának feloldása Újra Videó - Audio - A kezdéshez koppints a \"Keresés\"-re. - Nem sikerült az összes előnézeti kép betöltése - Nem sikerült a weblap betöltése + Hang + A kezdéshez koppintson a nagyítóra. + Nem sikerült az összes bélyegkép betöltése + Nem sikerült a weblap feldolgozása Letöltések Letöltések - Hibabejelentés - Indít - Szünet + Hibajelentés + Indítás + Szüneteltetés Törlés - Ellenőrző összeg + Ellenőrzőösszeg Rendben Fájlnév - Threadek + Szálak Hiba NewPipe letöltés folyamatban - Katt a részletekért - Kérlek várj… + Koppintson a részletekért + Kis türelmet… Vágólapra másolva - Kérlek, válassz egy létező könyvtárat a letöltésekhez + Adjon meg később egy letöltési mappát a beállításokban Csatornáról leiratkozva Nem sikerült megváltoztatni a feliratkozást Nem sikerült frissíteni a feliratkozást @@ -86,25 +86,25 @@ Újdonságok Háttér Felugró ablak - Nem található stream lejátszó alkalmazás (feltelepítheted a VLC-t a lejátszáshoz). + Nem található lejátszó a közvetítéshez (feltelepítheti a VLC-t a lejátszáshoz). Megnyitás felugró módban Néhány felbontásnál eltávolítja a hangot Feliratkozás Feliratkozva - Több infó - Alapértelmezett felugró ablak felbontása - Mutassa a magasabb felbontásokat - Csak néhány eszköz tud lejátszani 2K/4K videókat - Alapértelmezett videó formátum + További infó + Felugró ablak alapértelmezett felbontása + Magasabb felbontások megjelenítése + Csak bizonyos eszközök tudnak 2K/4K-s videókat lejátszani + Alapértelmezett videoformátum Fekete - Jegyezze meg a felugró ablak helyét és méretét - Jegyezze meg a felugró ablak előző helyét és méretét + Felugró ablak tulajdonságainak megjegyzése + A felugró ablak előző helyének és méretének megjegyzése Keresési javaslatok - Mutasson javaslatokat keresés közben + Válassza ki a keresési javaslatokat keresés közben Keresési előzmények - Előzmények - Megnézett videók nyomon követése - Lejátszás folytatása félbeszakítás után (pl.: telefonhívás) + Megtekintési előzmények + Megtekintett videók nyomon követése + Lejátszás folytatása félbeszakítások után (például telefonhívás) Lejátszó Működés Előzmények és gyorsítótár @@ -119,32 +119,32 @@ Összes lejátszása Mindig Csak egyszer - NewPipe Értesítés - Értesítések a NewPipe háttér- és felugró ablak lejátszójához + NewPipe értesítés + Értesítések a NewPipe lejátszójához [Ismeretlen] Adatbázis importálása Adatbázis exportálása - Felülírja a jelenlegi előzményeket, feliratkozásokat, lejátszási listákat és (választható) beállításokat + Felülírja a jelenlegi előzményeket, feliratkozásokat, lejátszási listákat és (választhatóan) a beállításokat Előzmények, feliratkozások, lejátszási listák és beállítások exportálása - Alkalmazás/Kezelő felület összeomlott - Videó lejátszása sikertelen - A külső lejátszó nem támogatja az ilyen típusú linkeket - Nem található videó formátum - Nem található hang csatorna + Az alkalmazás/kezelőfelület összeomlott + Nem sikerült a videó lejátszása + A külső lejátszó nem támogatja az ilyen típusú hivatkozásokat + Nem található videó adatfolyam + Nem található hang adatfolyam Mi:\\nKérés:\\nTartalom nyelve:\\nTartalom származási országa:\\nAlkalmazás nyelve:\\nSzolgáltatás:\\nGMT idő:\\nCsomag:\\nVerzió:\\nOperációs rendszer verzió: Nincs találat - Adatfolyam fájl letöltése + Közvetítési fájl letöltése Hozzáadás ehhez Gyorsabb, de pontatlan tekerés használata - A pontatlan tekerés lehetővé teszi, hogy gyorsabban ugorjon a pozíciókra, de kevesebb pontossággal. Az 5, 15, vagy 25 másodperces tekerés nem működik ebben a módban. + A pontatlan tekerés lehetővé teszi, hogy gyorsabban ugorjon a pozíciókra, de kisebb pontossággal. Az 5, 15, vagy 25 másodperces tekerés nem működik ebben a módban. Bélyegképek betöltése - Kapcsold ki, hogy a megelőzzed bélyegképek betöltését, így csökkentve az adat és memória használatot. Ennek az értéknek a megváltoztatása törli a memóriában és a meghajtón lévő bélyegkép gyorsítótárat. + Kapcsolja ki, hogy a megelőzze a bélyegképek betöltését, így csökkentve az adat- és memóriahasználatot. A megváltoztatása törli a memóriában és a meghajtón lévő képgyorsítótárat. A bélyegkép gyorsítótár törölve - Gyorsítótárazott metaadat törlése - Minden gyorsítótárazott weboldal adat törlése - A metaadat gyorsítótár törölve lett - Következő videó automatikus lejátszása - Keresési előzmények tárolása az eszközön + Gyorsítótárazott metaadatok törlése + Minden gyorsítótárazott weboldaladat törlése + A metaadatok gyorsítótára törölve lett + Következő videó automatikus sorba állítása + Keresési előzmények helyi tárolása Csatornák Lejátszási listák Zeneszámok @@ -153,26 +153,26 @@ Folytatás a háttérben Folytatás felugró ablakban Megtekintési előzmények törlése - Eltávolítja a megtekintési előzményeket és a lejátszási pozíciókat - Törlöd az összes megtekintési előzményt\? - Megtekintési előzmények törölve. + Törli a megtekintési előzményeket és a lejátszási pozíciókat + Törli az összes megtekintési előzményt\? + Megtekintési előzmények törölve Keresési előzmények törlése - Eltávolítja a kereséshez használt kifejezéseket az előzményekből - Törlöd az összes keresési előzményt\? - Keresési előzmények törölve. - Lejátszási hiba történt - Lejátszási hiba helyreállítása + Eltávolítja a keresési kulcsszavakat az előzményekből + Törli az összes keresési előzményt\? + Keresési előzmények törölve + Helyreállíthatatlan lejátszóhiba történt + Lejátszóhiba helyreállítása Nincs ilyen mappa - Nincs ilyen fájl vagy tartalom forrás - A fájl nem létezik vagy jogosultság az olvasáshoz és íráshoz hiányzik - A fájl neve nem lehet üres + Nincs ilyen fájl- vagy tartalomforrás + A fájl nem létezik, vagy hiányzik az olvasási vagy írási jogosultság + A fájlnév nem lehet üres Hiba történt: %1$s - Nincs letölthető adatforrás + Nincs letölthető adatfolyam Nincs itt semmi pár tücskön kívül Húzza az átrendezéshez e - M - Mrd + m + M Nincs feliratkozó %s feliratkozó @@ -186,7 +186,7 @@ Nincs videó %s videó - %s videók + %s videó Létrehozás Átnevezés @@ -194,107 +194,108 @@ \na felugró ablakban történő megnyitáshoz 1 elem törölve. reCAPTCHA rejtvény - reCAPTCHA rejtvény igényelve + reCAPTCHA rejtvény kérve Letöltés Fájlnevekben engedélyezett karakterek - Érvénytelen karakterek ezzel az értékkel kerülnek helyettesítésre + Az érvénytelen karakterek erre az értékre lesznek lecserélve Csere karakter Betűk és számok Legtöbb speciális karakter Nincs a fájl lejátszásához szükséges alkalmazás telepítve - A NewPipe alkalmazásról - Az alkalmazásról - Engedélyek - Ingyenes, egyszerű streamelés Androidon. + A NewPipe névjegye + Névjegy + Licencek + Szabad, egyszerű közvetítésnézés Androidon. Közreműködés - Legyen ötleted a fordítással, a megjelenéssel, a forrás kód tisztításával vagy komolyabb átszervezésével kapcsolatban, bármilyen segítséget szívesen fogadunk. Járulj hozzá az alkalmazás fejlesztéséhez! - Megtekintés GitHubon + Legyen ötleted a fordítással, a dizájnnal, a forráskód tisztításával vagy egy komolyabb átszervezésével kapcsolatban, bármilyen segítséget szívesen fogadunk. Minél több minden készül el, annál jobb lesz! + Megtekintés a GitHubon Adományozás - A NewPipe alkalmazást önkéntesek fejlesztik az ő szabadidejükben, hogy a lehető legjobb felhasználói élményt hozzák el neked. Járulj hozzá, hogy segítsd a fejlesztőket amíg ők egy csésze kávét szürcsölnek, hogy még jobbá tehessük a NewPipe-ot. + A NewPipe alkalmazást önkéntesek fejlesztik a szabadidejükben, hogy a lehető legjobb felhasználói élményt nyújtsák. Járuljon hozzá, hogy a fejlesztők még jobbá tegyék alkalmazást, miközben egy csésze kávét szürcsölnek. Hozzájárulás Honlap - Látogasd meg a NewPipe honlapját további információkért és hírekért! + Látogassa meg a NewPipe honlapját további információkért és hírekért. A NewPipe adatvédelmi irányelvei - A NewPipe projekt komolyan veszi az adataid védelmét. Az alkalmazás nem gyűjt semmilyen adatot a beleegyezésed nélkül. + A NewPipe projekt komolyan veszi az adatvédelmét. Az alkalmazás nem gyűjt semmilyen adatot a beleegyezése nélkül. \nA NewPipe adatvédelmi irányelve részletesen elmagyarázza, mely adatok kerülnek elküldésre és tárolásra az alkalmazás összeomlásának jelentésekor. - Az adatvédelmi irányelvek elolvasása + Adatvédelmi irányelvek elolvasása A NewPipe licence Licenc elolvasása Előzmények Előzmények - Törölni kívánja ezt az elemet a keresési előzmények közül\? + Törli ezt az elemet a keresési előzmények közül\? Utoljára lejátszott Legtöbbet lejátszott Főoldal tartalma Üres oldal Újságárus oldal - Csatorna oldal - Csatorna választása - Még nincs csatorna feliratkozás - Újságárus választása + Csatornaoldal + Válasszon egy csatornát + Még nincs csatornafeliratkozás + Válasszon egy újságárust Exportálva Importálva - Nem érvényes ZIP fájl + Nem érvényes ZIP-fájl Figyelmeztetés: nem sikerült az összes fájl importálása. Ez felül fogja írni a jelenlegi beállításokat. - A beállításokat is importálni kívánja\? + A beállításokat is importálja\? Felkapott Top 50 - Új és friss + Új és népszerű Eltávolítás Részletek - Hang beállítások + Hangbeállítások Alapértelmezett tevékenység „%s” típusú tartalom megnyitásakor Videólejátszó Lejátszás háttérben Felugró ablakos lejátszás - Mindig kérdezz rá + Mindig kérdezzen Információk gyűjtése… Kért tartalom betöltése Új lejátszási lista Átnevezés Név Lejátszási listához adás - Beállítás lejátszási lista indexképeként - Könyvjelző törlése - Törlődjön ez a lejátszási lista\? - Lejátszási listsa létrehozva - Hozzáadva lejátszási listához - Lejátszási lista előképe megváltozott. - Felirat kikapcsolva - Illeszkedés + Beállítás a lejátszási lista bélyegképeként + Könyvjelző eltávolítása + Törli ezt a lejátszási listát\? + Lejátszási lista létrehozva + Lejátszási listához adva + A lejátszási lista bélyegképe megváltozott. + Nincs felirat + Igazítás Kitöltés - Közelítés + Nagyítás Automatikusan létrehozott Feliratok - Feliratok méretének és hátterének stílusbeli módosítása. A módosítások életbelépésehez az alkalmazás újraindítása szükséges. - Import + Feliratok méretének és hátterének stílusbeli módosítása. A módosítások életbe lépésehez az alkalmazás újraindítása szükséges. + Importálás Importálás a következőből Exportálás a következőbe Importálás… Exportálás… Fájl importálása Előző exportálás - Sikertelen a feliratkozások importálása - Sikertelen a feliratkozások exportálása - YouTube feliratkozások importálása Google takeout-ból: + A feliratkozások importálása nem sikerült + A feliratkozások exportálása nem sikerült + YouTube feliratkozások importálása a Google Takeoutból: \n -\n1. Navigálj erre az oldalra: %1$s -\n2. Jelentkezz be -\n3. Kattints a \"All data included/Minden adat\"-ra, majd a \"Deselect all/MInden kijelölés megszüntetése\" gombra, majd válaszd ki a \"subscriptions/feliratkozások\" és kattints az \"OK\"-ra -\n4. Kattints a \"Next step/Következő lépés\", majd az \"Create export/Export létrehozása\" gombra -\n5. Kattints a \"Download/Letöltés\" gombra, mikor megjelenik, majd -\n6. A letöltött zip fájlból csomagold ki a .json fájlt (általában: \"YouTube and YouTube Music/subscriptions/subscriptions.json\"), majd importáld itt. - Importálja SoundCloud profilját az URL vagy az azonosítójának begépelésével: +\n1. Navigáljon erre az oldalra: %1$s +\n2. Jelentkezzen be, ha kérik +\n3. Kattintson „Az összes adatot tartalmazza” gombra, majd a „Kijelölések megszüntetése” gombra, majd válassza ki a „feliratkozások” lehetőséget és kattintson az „OK” gombra +\n4. Kattintson a „Következő lépés”, majd az \"Exportálás indítása” gombra +\n5. Kattintson a „Letöltés” gombra, amikor megjelenik, +\n6. Kattintson a lenti FÁJL IMPORTÁLÁSA gombra, és válassza ki a letöltött ZIP-fájlt +\n7. [Ha a ZIP-fájl importálása nem sikerül] Bontsa ki a .csv fájlt (általában: „YouTube és YouTube Music/feliratkozások/feliratkozások.csv\"), majd kattintson lent a FÁJL IMPORTÁLÁSA gombra, és válassza az exportált CSV-fájlt + SoundCloud-profil importálása az URL vagy az azonosítójának begépelésével: \n -\n1. Az oldal mobileszközökön nem elérhető, így „asztali böngésző mód” szükséges -\n2. Navigáljon erre az oldalra: %1$s -\n3. Jelentkezzen be +\n1. A webböngészőben engedélyezze az „asztali módot” (az oldal nem érhető el mobileszközökön) +\n2. Navigáljon erre az URL-re: %1$s +\n3. Jelentkezzen be, ha kéri \n4. Másolja ki a profil URL-t, ahova át lett irányítva. - azonosítód, soundcloud.com/azonosítód - Ez a művelet adatforgalom igényes lehet. + saját azonosítója, soundcloud.com/azonosító + Ez a művelet adatforgalom-igényes lehet. \n -\nFolytatni kívánja\? +\nBiztos, hogy folytatja\? Ütem Hangmagasság Előrepörgetés csend alatt @@ -303,142 +304,143 @@ Elfogadás Elutasítás Nincs korlát - Felbontás korlátozása mobilinternet használata esetén - Művelet alkalmazás váltásakor a fő videólejátszóról — %s + Felbontás korlátozása mobil adatkapcsolat használata esetén + A fő videólejátszóról más alkalmazásra történő váltáskor teendő művelet — %s Ne tegyen semmit Lejátszás folytatása a háttérben Lejátszás folytatása felugró ablakban Lejátszás folytatása - Mutassa a \"Tartsa lenyomva a hozzáadáshoz\" tippet + A „Tartsa lenyomva a sorba állításhoz\" tipp megjelenítése Leiratkozás - Válassz fület - Kommentek mutatása - Kapcsold ki a kommentek elrejtéséhez - Alapértelmezett ország tartalom + Válasszon lapot + Megjegyzések megjelenítése + Kapcsolja ki a megjegyzések elrejtéséhez + Tartalom alapértelmezett országa Folytatás főnézetben - Figyelmen kívül hagy - Lejátszási lista könyvjelzők közé - Hasonló videó beadása az utolsó videó után egy nem ismétlődő sorban + Eltüntetés + Lejátszási lista könyvjelzőzése + Egy hasonló videó hozzáadása a befejeződő (nem ismétlődő) lejátszási sorhoz Sor a fájl nem írható felül Az előre- és visszatekerés időtartama Utolsó lejátszási pozíció visszaállítása Lejátszás folytatása - Jelentés új NewPipe verzióról - Alkalmazás-frissítés jelzése - File törölve + Értesítések az új NewPipe verziókról + Alkalmazásfrissítés értesítése + Fájl törölve Frissítések - Tipp mutatása háttér vagy felbukkanó gomb megnyomásakor a videó részletei oldalon + Tipp megjelenítése, ha megnyomja a hátteret vagy a felugró gombot a videó részleteinél Automatikus lejátszás Adatok törlése - Lejátszási pozíciók mutatása a listákban + Lejátszási pozíciók megjelenítése a listákban Pozíciók a listákban - Gesztusvezérlés használata fényerő szabályzásra + Gesztusok használata a fényerő szabályozásához Fényerő gesztus - Gesztusvezérlés használata hangerő szabályzásra + Gesztusok használata a lejátszó hangerejének szabályzásához Hangerő gesztus - A rendszer megkérdezi, hogy hova mentse el az egyes letöltéseket + Meg fogja kérdezni, hogy hova mentse el az egyes letöltéseket. +\nEngedélyezze a rendszermappa-választót (SAF), ha külső SD-kártyára akar letölteni Kérdezze meg, hova töltse le Letöltések szüneteltetése Letöltések indítása - Egyszerre egy letöltés fog futni ugyanabban az időben - Korlátozza a letöltési sort - Bezár - Hasznos, amikor átvált a mobil adatokra, bár néhány letöltést nem lehet felfüggeszteni - Megszakítás a mért hálózatokon - A letöltés megszakítása előtti kísérletek maximális száma - Maximális próbálkozások - Állj + Egyszerre csak egy letöltés fog futni + Letöltési sor korlátozása + Bezárás + Hasznos, ha mobil adatkapcsolatra vált, bár néhány letöltést nem lehet felfüggeszteni + Félbehagyás a forgalomkorlátos hálózatokon + A letöltés megszakítása előtti kísérletek legnagyobb száma + Próbálkozások legnagyobb száma + Leállítás Letöltött fájlok törlése Törli a letöltési előzményeket, vagy törli az összes letöltött fájlt\? Letöltési előzmények törlése - A letöltést nem lehet visszaállítani - Kapcsolat időtúllépés - A folyamat elveszett, mert a fájlt törölték + A letöltést nem lehet helyrehozni + Kapcsolati időtúllépés + Az előrehaladás elveszett, mert a fájlt törölték Nincs hely az eszközön - NewPipe leállt a fájl feldolgozása közben + A NewPipe leállt a fájl feldolgozása közben Utófeldolgozás sikertelen Nincs talalat - A szerver nem fogad többszálú letöltést, próbálkozzon újra @ string / msg_threads = 1 - A szerver nem küld adatokat - Nem lehet csatlakozni a szerverhez - A szerver nem talalható + A kiszolgáló nem fogad többszálú letöltést, próbálkozzon újra ezzel: @string/msg_threads = 1 + A kiszolgáló nem küld adatokat + Nem lehet csatlakozni a kiszolgálóhoz + A kiszolgáló nem található Nem sikerült biztonságos kapcsolatot létesíteni A célmappa nem hozható létre A fájlt nem lehet létrehozni Hiba megjelenítése - Ezzel a névvel egy letötés már várakozás alatt áll + Ezzel a névvel egy letöltés már várakozik Ezzel a névvel egy letöltés már folyamatban van - Az ilyen névvel letöltött fájl már létezik - Az ilyen névű fájl már létezik - Átír - Generáljon egyedi nevet + Ilyen névű letöltött fájl már létezik + Ilyen névű fájl már létezik + Felülírás + Egyedi név előállítása Letöltés sikertelen - Helyrehozás - Utófeldolgozás - Sorban álló - Szünet + helyrehozás + utófeldolgozás + sorba állítva + szüneteltetve Függőben lévő Befejezett - Kattints a letöltéshez - NewPipe frissítés elérhető! - Auto + Kattintson a letöltéshez + NewPipe frissítés érhető el! + Automatikus Rács Lista Lista nézet - File áthelyezve vagy törölve - Külső SD-kártyára mentés nem lehetséges. Visszaállítsuk a letöltési mappa helyét\? - Külső tárhely nem elérhető - Lejátszási pozíciók törölve. - Összes lejátszási pozíció törlése\? + A fájl áthelyezve vagy törölve + A külső SD-kártyára történő mentés nem lehetséges. Visszaállítja a letöltési mappa helyét\? + A külső tárhely nem érhető el + Lejátszási pozíciók törölve + Törli az összes lejátszási pozíciót\? Összes lejátszási pozíció törlése Lejátszási pozíciók törlése Találatok a következőre: %s - Bélyegkép méretezése 1:1 arányra + Bélyegkép méretezése 1:1-es arányra Értesítés színezése Semmi Keverés Ismétlés Leírás megjelenítése - Bufferelés + Pufferelés Megnyitás ezzel - Az URL-t nem lehetett felismerni. Megnyitás másik alkalmazással\? + Az URL-t nem lehetett felismerni. Megnyitja másik alkalmazással\? Automatikus sorba állítás - "Kikapcsolása elrejti a videó leírását és a kapcsolódó információt" - Vissza akarod állítani az alapértelmezéseket\? + Kapcsolja ki, hogy elrejtse a videó leírását és a további információkat + Visszaállítja az alapértelmezéseket\? Ez a videó korhatáros. -\nÚj, korhatáros videókkal kapcsolatos YouTube irányelvek miatt a NewPipe nem férhet hozzá a videóhoz, így nem tudja lejátszani. +\nAz új, korhatáros videókkal kapcsolatos YouTube irányelvek miatt a NewPipe nem férhet hozzá a videóhoz, így nem tudja lejátszani. Leírás Megjegyzések - Formázott jelentése másolása - Adj engedélyt a más alkalmazások feletti megjelenéshez - Még nincsenek lejátszási lista könyvjelzők + Formázott jelentés másolása + Adjon engedélyt a más alkalmazások feletti megjelenéshez + Még nincs könyvjelző lejátszási listához Némítás megszüntetése Némítás Nincs betöltve: %d Üres csoportnév - Törölni szeretnéd ezt a csoportot\? + Törli ezt a csoportot\? Mindig frissítsen Készítette: %s - Lejátszási listák oldala + Lejátszási lista oldal Bélyegkép használata a zárképernyőn és az értesítéseken is Rádió - Válaszd ki kedvenc éjszakai témád — %s - Kiválaszthatod a kedvenc éjszakai témádat lentebb + Válassza ki a kedvenc éjszakai témáját — %s + Lent kiválaszthatja a kedvenc éjszakai témáját Nemrég hozzáadott Az ExoPlayer korlátai miatt az előre- és visszatekerés időtartama %d másodpercre lett állítva - Csatorna csoportok - Rendszer által alapértelmezett - Az Általános adatvédelmi rendeletnek (GDPR) való megfelelés érdekében felhívjuk figyelmed a NewPipe adatvédelmi nyilatkozatára. Kérjük olvasd el figyelmesen. -\nEl kell fogadnod, ha jelenteni szeretnél programhibákat. + Csatornacsoportok + Rendszer alapértelmezése + Az Általános adatvédelmi rendeletnek (GDPR) való megfelelés érdekében felhívjuk figyelmét a NewPipe adatvédelmi nyilatkozatára. Olvassa el figyelmesen. +\nEl kell fogadnia, ha hibajelentést szeretne küldeni. Alkalmazás összeomlasztása - Memóriaszivárgások mutatása - A memóriaszivárgás-monitorozás az alkalmazás megállását okozhatja amíg a dinamikus memória mentése folyik + Memóriaszivárgások megjelenítése + A memóriaszivárgás-monitorozás az alkalmazás megállását okozhatja, amíg a dinamikus memória mentése folyik Automatikusan létrehozott (feltöltő nem található) Lejátszási sor Konferenciák - Legtöbbet lájkolt - Mely oldalak kerülnek a főoldalon megjelenítésre + Legkedveltebb + Mely oldalak jelennek meg a főoldalon %s hallgató %s hallgató @@ -449,58 +451,57 @@ %s néző Senki sem nézi - Feliratkozók száma nem érhető el + A feliratkozók száma nem érhető el Helyi - A nyelv meg fog változni amint az alkalmazás újra lesz indítva. + A nyelv az alkalmazás újraindításakor fog megváltozni Megjegyzések betöltése sikertelen - Lejátszási lista kiválasztása + Válasszon egy lejátszási listát Lejátszás automatikus indítása — %s Lejátszás sebességének beállítása - Lejátszó váltása törölheti a lejátszási sort + Az egyik lejátszóról a másikra váltás törölheti a lejátszási sort Csak Wi-Fi-hálózaton - SAF használata - A \'Storage Access Framework\' lehetővé teszi a letöltések külső SD-kártyára történő mentését. -\nBizonyos eszközökön nem támogatott - A műveletet letiltotta a rendszer + Rendszermappa-választó (SAF) használata + A „Storage Access Framework” lehetővé teszi a letöltések külső SD-kártyára történő mentését + A rendszer megtagadta a műveletet Soha Feliratkozások kiválasztása © %1$s %2$s, %3$s licenc alatt Harmadik féltől származó licencek Kész - Nincsenek megjegyzések + Nincs megjegyzés ∞ videó 100+ videó - Jelentés GitHub-on - Alapértékek visszaállítása - Segítség - Sütik törlése, amelyeket a NewPipe akkor ment, amikor megoldasz egy reCAPTCHA-t + Jelentés a GitHubon + Alapértelmezések visszaállítása + Súgó + Sütik törlése, amelyeket a NewPipe akkor ment, amikor megold egy reCAPTCHA-t reCAPTCHA sütik törölve reCAPTCHA sütik törlése Előadók Albumok - Dalok + Számok Események Videók Ez a videó korhatáros. \n -\nEngedélyezd a(z) \"%1$s\" beállítást ha meg szeretnéd tekinteni. - Gyermekek számára potenciálisan nem megfelelő, korhatáros tartalom mutatása (pl. 18+) +\nEngedélyezze a(z) „%1$s” beállítást, ha meg szeretné tekinteni. + Gyermekek számára esetlegesen nem megfelelő, korhatáros tartalom megjelenítése (például 18+) Értesítés - Csak HTTPS URL-ek támogatottak - Metaadatok mutatása + Csak a HTTPS URL-ek támogatottak + Metainformációk megjelenítése A jelenleg aktív lejátszási sor le lesz cserélve - Kérjen megerősítést a lejátszási sor törlése előtt + Megerősítés kérése a lejátszási sor törlése előtt Éjszakai téma - Értesítés az alkalmazás frissítéséhez, amikor egy új verzió érhető el + Frissítési értesítés megjelenítése, amikor egy új verzió érhető el Frissítések - Az Android igazítsa az értesítés színét a bélyegkép meghatározó színéhez (nem minden eszközön elérhető) - Legfeljebb három választható művelet jeleníthető meg a kompakt értesítésben! - Szabd személyre, hogy az értesítésben megjelenő akciógombok mit csinálnak. Válassz ki legfeljebb hármat a jobb oldali jelölőnégyzetekkel, amelyek a kompakt értesítésben is megjelennek. - Ötödik akciógomb - Negyedik akciógomb - Harmadik akciógomb - Második akciógomb - Első akciógomb + Az Android igazítsa az értesítés színét a bélyegkép meghatározó színéhez (nem minden eszközön érhető el) + Legfeljebb három művelet jeleníthető meg a kompakt értesítésben. + Koppintással szerkesztheti az egyes értesítéseken megjelenő műveleteket. Válasszon ki legfeljebb hármat a jobb oldali jelölőnégyzetekkel, amelyek a kompakt értesítéseken is megjelennek. + Ötödik műveletgomb + Negyedik műveletgomb + Harmadik műveletgomb + Második műveletgomb + Első műveletgomb Alkalmazás nyelve %d másodperc @@ -524,47 +525,167 @@ %d kiválasztva Új - Ez a tartalmat még nem támogatja a NewPipe. + Ezt a tartalmat még nem támogatja a NewPipe. \n \nRemélhetőleg egy következő verzióban már támogatott lesz. - Nincs a készülékeden olyan alkalmazás, amely meg tudja nyitni ezt - Ez a videó csak YouTube Music Prémium előfizetők számára érhető el, így nem megtekinthető és nem letölthető NewPipe segítségével. + Nincs a készülékén olyan alkalmazás, amely meg tudja ezt nyitni + Ez a videó csak YouTube Music Prémium előfizetők számára érhető el, így nem tekinthető meg és nem tölthető le a NewPipe-pal. Automatikus (rendszertéma) - Ez a tartalom csak előfizetőknek érhető el, nem megtekinthető és nem letölthető a NewPipe segítségével. - Ez a tartalom nem érhető el az országodban. - Ez a tartalom privát, így nem megtekinthető és nem letölthető a NewPipe segítségével. + Ez a tartalom csak előfizetőknek érhető el, nem tekinthető meg és nem tölthető le a NewPipe-pal. + Ez a tartalom nem érhető el az országában. + Ez a tartalom privát, így nem tekinthető meg és nem tölthető le a NewPipe-pal. A letöltés elkezdődött - Értesítésben megjelenő bélyegkép átméretezése 16:9 helyett 1:1 arányra (torzítással járhat) + Értesítésben megjelenő bélyegkép átméretezése 16:9-es helyett 1:1-es arányra (torzítással járhat) Fejezetek - Bélyegkép mutatása - Lejátszás felugró ablakban - Lejátszás a háttérben - Sorhoz hozzáadva - Sorhoz adás - Mentett fülek olvasása sikertelen, alapértelmezettek használata - Értesítések a videó hashelési folyamathoz - Videó hash értesítés - YouTube biztosít egy \"Korlátozott Módot\" ami elrejti a lehetséges felnőtteknek szóló tartalmat - YouTube \"Korlátozott Mód\"-jának bekapcsolása + Bélyegkép megjelenítése + Lejátszás indítása felugró ablakban + Lejátszás indítása a háttérben + Sorba állítva + Sorba állítás + Nem sikerült a mentett lapok olvasása, alapértelmezettek használata + Értesítések a videók ujjlenyomatkészítési folyamatához + Videó ujjlenyomat-készítési értesítése + A YouTube biztosít egy „Korlátozott módot”, amely elrejti a lehetséges felnőtteknek szóló tartalmat + A YouTube „Korlátozott módjának” bekapcsolása A példány már létezik - Pédány érvényesítése nem sikerült - Példány URL megadása + A példány érvényesítése nem sikerült + Adja meg a példány URL-ét Példány hozzáadása - A neked tetsző példányokat megtalálhatod itt: %s - Válaszd ki a kedvenc PeerTube példányaidat + Találjon önnek tetsző példányokat itt: %s + Válassza ki a kedvenc PeerTube példányait PeerTube példányok Életciklusából kifutott hibák jelentése - Preferált \'nyitási\' cselekedet + Előnyben részesített „megnyitási” művelet Fiók bezárása Fiók megnyitása Csatorna részleteinek megjelenítése - Tartsd hogy sorba állítsd - Alap Kiosk - A NewPipe egy copyleft szabad szoftver: Felhasználhatod, tanulmányozhatod, megoszthatod és fejlesztheted akaratod szerint. Konkrétan továbbadhatod és/vagy módosíthatod a GNU General Public License feltételei alatt ami a Free Software Foundation álltal lett publikálva, vagy a 3. verzióját a licensznek, vagy (a saját opciód szerint), bármelyik későbbi verzióját. + Tartsa a sorba állításhoz + Alapértelmezett újságárus + A NewPipe egy copyleft szabad szoftver: tetszése szerint felhasználhatja, tanulmányozhatja, megoszthatja és fejlesztheti. Egész pontosan a Free Software Foundation által kiadott GNU General Public License 3-as, vagy (választható módon) újabb verziójának feltételei szerint módosíthatja vagy adhatja tovább. Megoldás - Nyomj a \"Kész\"-re amikor meg van oldva - Hash számítása - Összefüggő elemek - Kérlek ellenőrizd, hogy egy hiba, ami az összeomlásodat írja le, létezik-e már. Ha duplikált jegyet adsz be, időt veszel el tőlünk amit arra tudnánk fordítani, hogy kijavítsuk magát a bugot. - Lekicsinyítés alkalmazás váltáskor + Nyomja meg a „Kész” gombot, ha megoldotta + Ujjlenyomat számítása + Kapcsolódó elemek + Ellenőrizze, hogy létezik-e már olyan jegy, amely az összeomlásával foglalkozik. Ha duplikált jegyet ad fel, akkor olyan időt vesz el tőlünk, amelyet a hiba javítására tudnánk fordítani. + Minimalizálás alkalmazásváltáskor + A(z) %s ezt az okot adta meg: + Helyi keresési javaslatok + Távoli keresési javaslatok + A fő lejátszó teljes képernyős indítása + A videókat ne a kis lejátszóban indítsa el, hanem kapcsolja be a teljes képernyős módot, ha az automatikus forgatás zárolva van. Továbbra is elérheti a kis lejátszót, ha kilép a teljes képernyőből. + Szolgáltatás be/ki, jelenleg kiválasztott: + A megjegyzések ki vannak kapcsolva + Húzza oldalra az elemeket az eltávolításukhoz + A következő sorba állítása + A következő sorba állítva + Feldolgozás… Ez eltarthat egy ideig. + Az eltávolítás utáni, fragment vagy activity életcikluson kívüli, nem kézbesíthető Rx kivételek jelentésének kényszerítése + Eredeti „ennyi ideje” megjelenítése az elemeken + Tiltsa le a médiacsatornázást, ha fekete képernyőt vagy akadozást tapasztal videólejátszáskor + Picasso színes szalagok megjelenítése a képek fölött, megjelölve a forrásukat: piros a hálózathoz, kék a lemezhez, zöld a memóriához + Minden letöltésnél meg fogja kérdezni, hogy hova mentse el + A „Storage Access Framework” nem támogatott Android KitKaten vagy régebbin + Válasszon egy példányt + Lista legutóbbi frissítése: %s + Lista betöltése… + Csak a nem csoportosított feliratkozások megjelenítése + Lista + Lista frissítési küszöb + A legutóbbi frissítés óta eltelt idő, ami után a feliratkozás elavultnak számít – %s + A szerző fiókját eltávolították. +\nA NewPipe nem fogja tudni betölteni ezt a listát a jövőben. +\nLeiratkozik erről a csatornáról\? + A gyors listamód nem ad ennél több információt. + Lekérés egy dedikált listából, ha lehetséges + Gyors mód engedélyezése + Úgy gondolja, hogy a lista betöltése lassú\? Ha így van, akkor próbálja engedélyezni a gyors betöltést (ezt a beállításokban változtathatja meg, vagy a lenti gomb megnyomásával). +\n +\nA NewPipe két listabetöltési stratégiát kínál: +\n• A teljes feliratkozott csatorna lekérése, amely lassú, de teljes. +\n• Egy dedikált szolgáltatási végpont, amely gyors, de általában nem teljes. +\n +\nA különbség a kettő között az, hogy a gyorsból általában hiányoznak egyes információk, mint az elem hossza vagy a típusa (nem lehet megkülönböztetni az élő videókat a normálaktól), valamint kevesebb elemet adhat vissza. +\n +\nA YouTube például egy olyan szolgáltatás, amely ezt a gyors módot RSS hírcsatornával kínálja. +\n +\nÍgy a választása azon múlik, hogy melyiket tartja fontosabbnak: a sebességet vagy a pontos információkat. + Csatorna profilképének bélyegképe + Legutóbbi + Kiemelt + Most már kijelölheti a leírásban lévő szöveg. Vegye figyelembe, hogy kijelölési módban az oldal villoghat, és a hivatkozások nem biztos, hogy kattinthatók lesznek. + Szöveg kijelölésének letiltása a leírásban + Licenc + Korhatár + Kiszolgáló + Bélyegkép URL + Nyilvános + Nem listázott + Ki + Csatornarészletek betöltése… + Nem található megfelelő fájlkezelő ehhez a művelethez. +\nTelepítsen egy fájlkezelőt, vagy próbálja meg letiltani a következőt a letöltési beállításokban: „%s”. + + Letöltés befejezve + %s letöltés befejezve + + Lista feldolgozása… + Egyes szolgáltatásoknál érhető el, általában sokkal gyorsabb, és korlátozott számú elemet adhat vissza, gyakran hiányos információkkal (például nincs hossz, elemtípus, vagy élő videó állapot) + Fiók eltávolítva + Megjelölés megtekintettként + Még nincs letöltési mappa beállítva, válassza ki az alapértelmezett letöltési mappát most + Tekerősáv bélyegkép-előnézete + Magas minőségű (nagyobb) + Hiba a lista betöltésekor + Megnézett elemek megjelenítése + Nyelv + Támogatás + Weboldal megnyitása + Táblagép mód + Az Android 10-től kezdve, csak a „Storage Access Framework” támogatott + Új listaelemek + Privát + Belső + Készítő által szívecskézve + Be + A(z) „%s” listája nem tölthető be. + Ez egy SoundCloud Go+ szám, legalábbis az Ön országában, így nem játszható le vagy tölthető le a NewPipe-pal. + Kapcsolja ki, hogy elrejtse a metainformációs dobozokat, melyek további információkat tartalmaznak a közvetítés létrehozójáról, annak tartalmáról vagy egy keresési kérésről + Hibajelentési értesítés + Értesítések a hibák jelentéséhez + A NewPipe hibát észlelt, koppintson a jelentéséhez + Hiba történt, lásd az értesítést + Médiacsatornázás letiltása + Hiba üzenetsávjának megjelenítése + Hibaértesítés létrehozása + Új verziók kézi keresése + Alacsony minőségű (kisebb) + Frissítések keresése… + Készítette: %s + Nem található megfelelő fájlkezelő ehhez a művelethez. +\nTelepítsen egy olyan fájlkezelőt, amely kompatibilis a Storage Access Frameworkkel. + Szöveg kijelölésének engedélyezése a leírásban + Kategória + Címkék + Adatvédelem + Hiba a csatornarészletek megjelenítésekor + Gyors mód letiltása + Igen, és távolítsa el a részben megnézett videókat is + A videók, melyeket már megnézett miután a lejátszási listához adta őket, el lesznek távolítva. +\nBiztos benne\? Ez nem vonható vissza. + A szolgáltatásokból származó eredeti szövegek láthatók lesznek a közvetítési elemeken + Lejátszó összeomlasztása + Képjelölők megjelenítése + A „lejátszó összeomlasztása” lehetőség megjelenítése + Megjeleníti az összeomlasztási lehetőséget a lejátszó használatakor + Hangmagasság megtartása (torzítást okozhat) + Frissítések keresése + Ne jelenítse meg + Megnézettek eltávolítása + Eltávolítja a megnézett videókat\? + + %1$s letöltés törölve + %1$s letöltés törölve + + Rögzített megjegyzés + Már megy a lejátszás a háttérben \ No newline at end of file diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index fd67cbfb1..5eb00875a 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -153,7 +153,7 @@ Selalu Hanya Sekali Berkas - Notifikasi untuk pemutar latar belakang dan popup NewPipe + Notifikasi untuk pemutar NewPipe [Tidak diketahui] Alihkan ke Latar Belakang Alihkan ke Popup @@ -285,11 +285,12 @@ Impor langganan YouTube dari Google takeout: \n \n1. Kunjungi URL ini: %1$s -\n2. Masuk ketika ditanya +\n2. Masuk ketika ditanyakan \n3. Klik \"Semua data disertakan\", lalu \"Batalkan semua pilihan\", lalu hanya pilih \"langganan\" dan klik \"OKE\" \n4. Klik \"Langkah berikutnya\" dan kemudian \"Buat ekspor\" -\n5. Klik tombol \"Unduh\" dan -\n6. Dari unduhan zip takeout ekstrak berkas .json (biasanya di bawah \"YouTube and YouTube Music/subscriptions/subscriptions.json\") dan impor di sini +\n5. Klik tombol \"Unduh\" +\n6. Klik IMPOR FILE di bawah dan pilih file .zip yang terunduh +\n7. [Jika impor .zip gagal] Ekstrak file .csv (biasanya di \"YouTube dan YouTube Music/langganan/langganan.csv\"), klik IMPOR FILE di bawah dan pilih file csv yang diekstrak Impor profil SoundCloud dengan mengetik URL atau ID Anda: \n \n1. Aktifkan \"mode desktop\" di peramban web (situs tidak tersedia untuk perangkat seluler) @@ -336,8 +337,8 @@ Pembaruan Acara Berkas dihapus - Notifikasi Pembaruan Apl - Notifikasi untuk versi NewPipe baru + Notifikasi pembaruan apl + Notifikasi untuk versi-versi NewPipe baru Penyimpanan eksternal tidak tersedia Tidak bisa mengunduh ke kartu SD eksternal. Atur ulang lokasi folder unduhan\? Tidak bisa membaca tab yang disimpan, beralih menggunakan tab bawaan @@ -570,7 +571,7 @@ Nonaktifkan untuk menyembunyikan kotak info dengan informasi tambahan tentang kreator, konten stream atau pencarian Tampilkan info meta Notifikasi untuk laju pemrosesan hash video - Notifikasi Hash Video + Notifikasi hash video Tidak ada apl di perangkat Anda yang bisa membuka ini Chapter Deskripsi @@ -580,8 +581,8 @@ Tampilkan deskripsi Buka dengan Konten ini hanya tersedia untuk pengguna yang telah membayar, sehingga tidak bisa diputar atau diunduh oleh NewPipe. - Video ini hanya tersedia untuk anggota Premium YouTube Music, sehingga tidak bisa diputar atau diunduh oleh NewPipe. - Konten ini bersifat pribadi, jadi tidak bisa diputar ataupun diunduh oleh NewPipe. + Video ini hanya tersedia untuk anggota YouTube Music Premium, sehingga tidak bisa diputar atau diunduh oleh NewPipe. + Konten ini privat, sehingga tidak bisa diputar atau diunduh oleh NewPipe. Ini adalah sebuah trek SoundCloud Go +, setidaknya di negara Anda, sehingga tidak bisa diputar atau diunduh oleh NewPipe. Konten ini tidak tersedia di negara Anda. Hentikan aplikasi @@ -665,4 +666,16 @@ Melaporkan kesalahan pemain video dalam detail yang penuh daripada menampilkan pesan toast yang muncul sebentar (berguna untuk memeriksa masalah) Laporkan kesalahan pemain video Hentikan pemain video + Notifikasi untuk melaporkan kegalatan + Notifikasi laporan kegalatan + Sebuah kegalatan terjadi, lihat notifikasinya + Menampilkan sebuah snackbar kegalatan + Buat sebuah notifikasi kegalatan + Tidak ada manajer file yang ditemukan untuk tindakan ini. +\nMohon instal sebuah manajer file atau coba menonaktifkan \'%s\' di pengaturan unduhan. + NewPipe mengalami sebuah kegalatan, ketuk untuk melaporkan + Tidak ada manajer file yang ditemukan untuk tindakan ini. +\nMohon instal sebuah manajer file yang kompatibel dengan Storage Access Framework. + Komentar dipin + Sudah diputar di latar belakang \ 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 46306f4c6..f9e620e3d 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -142,8 +142,8 @@ Comportamento Cronologia e cache Annulla - Notifiche NewPipe - Notifiche per lettore in sottofondo e popup + Notifica NewPipe + Notifiche per il lettore multimediale di NewPipe Nessun risultato Nessun iscritto @@ -342,8 +342,8 @@ Utilizza i gesti per controllare la luminosità del lettore multimediale Aggiornamenti File eliminato - Notifiche di aggiornamenti dell\'applicazione - Notifiche per una nuova versione di NewPipe + Notifiche per aggiornamenti dell\'app + Notifiche per le nuove versioni di NewPipe Archiviazione esterna non disponibile Impossibile scaricare sulla scheda SD esterna. Ripristinare la posizione della cartella dei download\? Impossibile leggere le schede salvate, verranno usate quelle predefinite @@ -577,7 +577,7 @@ Utilizza le copertine come sfondo della schermata di blocco e per le notifiche Mostra copertina Calcolo dell\'hash - Notifica Hash Video + Notifica hash video Notifiche per lo stato di avanzamento dell\'hashing video Recente Disattiva per nascondere i riquadri con informazioni aggiuntive sul contenuto, sul suo autore o su una richiesta di ricerca @@ -678,4 +678,16 @@ Invece di mostrare un messaggio popup di breve durata, gli errori del lettore multimediale saranno visualizzati in modo dettagliato (utile per diagnosticare i problemi) Mostra \"Fai crashare il lettore\" Fai crashare il lettore + NewPipe ha riscontrato un errore, tocca per segnalarlo + Mostra un messaggio di errore + Non è stato trovato alcun gestore di file appropriato per questa azione. +\nInstallane uno prova a disattivare \"%s\" nelle impostazioni di download. + Notifica per segnalazione errori + Notifiche per segnalare errori + Si è verificato un errore, vedi la notifica + Crea una notifica di errore + Non è stato trovato alcun gestore di file appropriato per questa azione. +\nInstallane uno compatibile con Storage Access Framework. + Commento in primo piano + Già in riproduzione in sottofondo \ No newline at end of file diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 147876ac7..6f00ff0e1 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -277,9 +277,9 @@ 最も再生された動画 拡大 プレイリスト - 「長押しして追加」のヒントを表示 + 「長押ししてキュー」のヒントを表示 トラック - NewPipe のバックグラウンドおよびポップアッププレイヤーの通知 + NewPipe のプレイヤーの通知 新着と人気 長押ししてキューに追加 ポップアップで連続再生を開始 @@ -664,4 +664,18 @@ プレイヤーのエラーを報告 \"プレイヤーがクラッシュ\"を表示 プレイヤーがクラッシュ + 新しいフィードアイテム + エラー報告通知 + エラーが発生しました。通知をご覧ください + NewPipe はエラーに遭遇しました。タップして報告 + スナックバーにエラーを表示 + 既にバックグラウンドで再生されています + 固定されたコメント + この動作に適切なファイルマネージャが見つかりませんでした。 +\nStorage Access Frameworkと互換性のあるファイルマネージャをインストールしてください。 + この動作に適切なファイルマネージャが見つかりませんでした。 +\nファイルマネージャをインストールするか、ダウンロード設定で\'%s\'を無効にすることをお試しください。 + プレイヤー使用時にクラッシュオプションを表示 + エラー通知を作成 + エラーを報告する通知 \ 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 737017128..ff82fce20 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -675,4 +675,15 @@ Se etter nye versjoner manuelt Nye informasjonskanalelementer Ser etter oppdateringer … + Viser et krasjalternativ ved bruk av avspilleren + Det oppstod en feil. Sjekk merknaden. + Festet kommentar + Spilles allerede i bakgrunnen + Feilrapport-merknad + Merknader for innrapportering av feil + NewPipe-feil. Trykk for å rapportere. + Opprett en feilmerknad + Vis et feil-alternativsfelt + Installer en filbehandler først, eller skru av «%s» i nedlastingsinnstillingene. + Installer en filbehandler som støtter lagringstilgangsrammeverk først. \ No newline at end of file diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 5940a803e..b85d48476 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -66,7 +66,7 @@ Downloads Foutrapport App/UI gecrasht - Wat:\\nVerzoek:\\nTaal van inhoud:\\nTaal van land:\\nTaal van Applicatie:\\nDienst:\\nTijd in GMT:\\nPakket:\\nVersie:\\nVersie van besturingssysteem: + Wat:\\nVerzoek:\\nTaal van inhoud:\\nTaal van land:\\nTaal van Applicatie:\\nDienst:\\nGMT-tijd:\\nPakket:\\nVersie:\\nVersie van besturingssysteem: Begin Pauzeren Verwijderen @@ -137,7 +137,7 @@ Hervat afspelen Ga verder met afspelen na onderbrekingen (b.v. telefoongesprekken) NewPipe Melding - Meldingen voor NewPipe-achtergrond- en pop-upspelers + Meldingen voor NewPipe speler Geschiedenis Geschiedenis Speler @@ -342,8 +342,8 @@ Gebruik gebaren om de helderheid van de speler aan te passen Updates Bestand verwijderd - App Update Melding - Meldingen voor nieuwe versies van NewPipe + App update melding + Meldingen voor nieuwe New Pipe versies Externe opslag niet beschikbaar Downloaden naar externe SD-kaart is niet mogelijk. Download map opnieuw instellen\? Fout bij het lezen van de opgeslagen tabbladen, waardoor standaardtabbladen worden gebruikt @@ -484,7 +484,7 @@ Geen abonnement geselecteerd %d geselecteerd - %d geselecteerd + %d geselecteerde Lege groepsnaam Wilt u deze groep verwijderen\? @@ -552,7 +552,7 @@ Vraag bevestiging alvorens de wachtrij te wissen Niets Aan het bufferen - Shuffle + Willekeurig afspelen Herhaal Je kan maximaal drie acties selecteren om te tonen in de compacte notificatie! Pas elke notificatieactie hieronder aan door er op te tikken. Selecteer tot drie acties die getoond worden in de compacte notificatie door gebruik te maken van de selectievakjes aan de rechterkant @@ -579,7 +579,7 @@ Recente Hash berekenen Meldingen over de voortgang van video hashing - Video Hash Melding + Video hash melding Schakel dit uit om meta-informatie vakken te verbergen met aanvullende informatie over de maker van de stream, streaminhoud of een zoekopdracht Laat meta informatie zien Beschrijving @@ -627,7 +627,7 @@ Media tunneling uitschakelen Uit Aan - Tablet mode + Tablet modus Open website %s geeft de volgende reden: Account getermineerd @@ -678,4 +678,16 @@ Controleer op updates Bezig met controleren op updates… Nieuwe feed items + Foutmelding + Beschrijving van foutmeldingen + NewPipe meldt fout, tik voor bericht + Foutmelding + Maak een foutmelding + Speelt al op de achtergrond + Korte foutmelding weergeven + Er is geen geschikte bestandsbeheerder gevonden voor deze actie. +\nInstalleer een bestandsbeheerder of probeer \'%s\' uit te schakelen in de download instellingen. + Er is geen geschikte bestandsbeheerder gevonden voor deze actie. +\nInstalleer een bestandsbeheerder die compatibel is met het Storage Access Framework. + Vastgemaakt commentaar \ 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 3fce4c91b..8393bf1ad 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -135,8 +135,8 @@ Śledź obejrzane wideo Wznawiaj odtwarzanie Kontynuuj odtwarzanie po przerwaniu (np. po rozmowie telefonicznej) - Powiadomienia NewPipe - Powiadomienia dla NewPipe przy odtwarzaniu w tle i w trybie okienkowym + Powiadomienie NewPipe + Powiadomienia dla odtwarzacza NewPipe Historia Historia Odtwarzacz @@ -349,7 +349,7 @@ Aktualizacje Plik usunięty Powiadomienie o aktualizacji aplikacji - Powiadomienia o nowej wersji NewPipe + Powiadomienia o nowych wersjach NewPipe Pamięć zewnętrzna niedostępna Pobieranie na kartę SD nie jest możliwe. Zresetować lokalizację folderu zapisywania\? Nie udało się odczytać zapisanych kart, więc będą używane domyślne @@ -697,4 +697,16 @@ Zepsuj odtwarzacz Pokazuj „zepsuj odtwarzacz” Zgłasza szczegółowo błędy odtwarzacza zamiast pokazywać krótkotrwałą wiadomość toast (przydatne do diagnozowania problemów) + Powiadomienie raportu o błędach + Powiadomienia do zgłaszania błędów + NewPipe napotkał błąd. Naciśnij, aby zgłosić + Wystąpił błąd. Zobacz powiadomienie. + Pokaż snackbar z błędem + Utwórz powiadomienie o błędzie + Nie znaleziono odpowiedniego menedżera plików dla tej akcji. +\nZainstaluj menedżer plików lub spróbuj wyłączyć „%s” w ustawieniach pobierania. + Nie znaleziono odpowiedniego menedżera plików dla tej akcji. +\nZainstaluj menedżer plików zgodny z Storage Access Framework. + Już jest odtwarzane w tle + Przypięty komentarz \ 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 23682f301..b90c45ca9 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -3,7 +3,7 @@ Áudio Não foi possível decodificar assinatura da URL do vídeo Seu comentário (em inglês): - O que ocorreu: + O que aconteceu: Informação: Vídeo Preto (AMOLED) @@ -16,7 +16,7 @@ Formato de áudio padrão Resolução padrão Excluir - Não curtidas + Não gostei Curtidas Baixar Baixar @@ -82,7 +82,7 @@ Usar player de áudio externo Usar player de vídeo externo Mostrar opção \"Reproduzir com Kodi\" - Ocorrido:\\nPedido:\\nIdioma do conteúdo:\\nPaís do conteúdo:\\nIdioma do app:\\nServiço:\\nHora GMT:\\nPacote:\\nVersão:\\nVersão do Sistema Operacional: + O que aconteceu:\\nPedido:\\nIdioma do conteúdo:\\nPaís do conteúdo:\\nIdioma do app:\\nServiço:\\nHora GMT:\\nPacote:\\nVersão:\\nVersão do Sistema Operacional: Abrir no modo popup Resolução padrão do popup Mostrar resoluções mais altas @@ -130,7 +130,7 @@ Não foi possível atualizar inscrição Inscrições Novidades - Retomar vídeo + Continuar reprodução Continua vídeo após interrupções (ex: ligações) Histórico de pesquisa Armazena histórico de pesquisa localmente @@ -138,8 +138,8 @@ Armazena histórico de vídeos assistidos Histórico Histórico - Notificações do NewPipe - Notificações para players popup e em segundo plano do NewPipe + Notificação do NewPipe + Notificações para o player do NewPipe Comportamento Histórico e cache Desfazer @@ -267,17 +267,17 @@ \n \n1. Acesse este link: %1$s \n2. Faça login quando solicitado -\n3. Clique em \"Todos os dados incluídos\", em seguida, em \"Desmarque todos\", em seguida, selecione apenas \"assinaturas\" e clique em \"OK\" +\n3. Clique em \"Todos os dados incluídos\", depois em \"Desmarcar todos\", em seguida, selecione apenas \"assinaturas\" e clique em \"OK\" \n4. Clique em \"Próximo passo\" e em seguida, em \"Criar exportação\" \n5. Clique no botão \"Baixar\" quando ele aparecer -\n6. Clique em Importar Arquivo abaixo e selecione o arquivo zip baixado -\n7. Caso a importação do arquivo zip falhe: Extraia o arquivo .csv (normalmente em \"YouTube e YouTube Music/subscriptions/subscriptions.csv\", clique em Importar Arquivo abaixo e selecione o arquivo cvs extraído +\n6. Clique em IMPORTAR ARQUIVO abaixo e selecione o arquivo .zip baixado +\n7. Caso a importação do arquivo .zip falhe: Extraia o arquivo .csv (geralmente em \"YouTube e YouTube Music/subscriptions/subscriptions.csv\", clique em IMPORTAR ARQUIVO abaixo e selecione o arquivo csv extraído Importe um perfil do SoundCloud digitando o URL ou seu ID: \n -\n1. Ative o \"modo desktop\" no navegador (o site não está disponível em aparelhos celulares) +\n1. Ative o \"modo desktop\" em um navegador (o site não está disponível em aparelhos celulares) \n2. Acesse este URL: %1$s \n3. Faça login quando solicitado -\n4. Copie o URL do perfil que voçê foi redirecionado. +\n4. Copie o URL do perfil que você foi redirecionado. seuID, soundcloud.com/seuid Tenha em mente que esta operação poderá consumir muitos dados. \n @@ -288,9 +288,9 @@ Remove todos os dados de páginas em cache Cache de metadados limpo Controles de velocidade de reprodução - Ritmo + Velocidade Desative para não carregar miniaturas e economizar no uso de dados e memória. A alteração limpa todo o cache de imagens em memória e em disco - Altura + Afinação Desvincular (pode causar distorção) Ação de \'abrir\' preferida Ação padrão ao abrir conteúdo — %s @@ -326,7 +326,7 @@ Nenhum Minimizar para segundo plano Minimizar para player popup - Avanço rápido durante silêncio + Avançar durante o silêncio Passo Redefinir Canais @@ -343,8 +343,8 @@ Atualizações Eventos Arquivo excluído - Notificação de atualização - Notificação de novas versões do NewPipe + Notificação de atualização do aplicativo + Notificações para novas versões do NewPipe Armazenamento externo indisponível Não é possível baixar para o cartão SD externo. Redefinir o local da pasta de download\? Não foi possível carregar as abas salvas, carregando as abas padrão @@ -410,7 +410,7 @@ Tempo limite de conexão Excluir todo o histórico de downloads ou excluir todos os arquivos baixados\? Limitar fila de downloads - Um download será feito ao mesmo tempo + Um download será feito por vez Iniciar downloads Pausar downloads Perguntar onde salvar o arquivo @@ -437,7 +437,7 @@ Duração do salto para avançar/retroceder Instâncias do PeerTube Escolha suas instâncias do PeerTube favoritas - Procure instâncias que gosta em %s + Encontre as instâncias que gosta em %s Adicionar instância Insira o link da instância Erro ao validar a instância @@ -506,7 +506,7 @@ \n• Buscar todo o conteúdo do canal inscrito, que é lento mas completo. \n• Usar um endpoint de serviço dedicado, que é rápido mas geralmente incompleto. \n -\nA diferença entre os dois é que o rápido geralmente falta alguma informação, como a duração ou tipo do item (não consegue distinguir entre as lives e os vídeos normais) e pode retornar menos itens. +\nA diferença entre os dois é que no rápido geralmente falta alguma informação, como a duração ou tipo do item (não consegue distinguir entre as lives e os vídeos normais) e pode retornar menos itens. \n \nO YouTube é um exemplo de serviço que oferece o modo rápido com seu feed RSS. \n @@ -578,7 +578,7 @@ Mostrar miniatura Calculando hash Notificações para o progresso do hash do vídeo - Notificação de Hash do Vídeo + Notificação de hash do vídeo Desative para ocultar as caixas de informações de metadados com informações adicionais sobre o criador, conteúdo do stream ou uma solicitação de pesquisa Mostrar informação de metadados Recentes @@ -592,12 +592,12 @@ Nenhum aplicativo em seu dispositivo pode abrir isso O aplicativo parou Este conteúdo está disponível apenas para usuários que pagaram, portanto não pode ser transmitido ou baixado pelo NewPipe. - Este vídeo está disponível apenas para assinantes do YouTube Music Premium, portanto não pode ser transmitido ou baixado por NewPipe. + Este vídeo está disponível apenas para assinantes do YouTube Music Premium, portanto não pode ser transmitido ou baixado pelo NewPipe. Este conteúdo é privado, portanto não pode ser transmitido ou baixado pelo NewPipe. Esta é uma faixa do SoundCloud Go+, pelo menos no seu país, portanto não pode ser transmitida ou baixada pelo NewPipe. Este conteúdo não está disponível em seu país. Este vídeo tem restrição de idade. -\nDevido às novas políticas do YouTube sobre vídeos com restrição de idade, o NewPipe não pode acessar nenhuma de suas streams de vídeo e assim ele não pode ser exibido. +\nDevido às novas políticas do YouTube sobre vídeos com restrição de idade, o NewPipe não pode acessar nenhum de seus streams de vídeo e assim ele não pode ser exibido. Rádio Destaque Resolvido @@ -614,7 +614,7 @@ Não Listado Público Limite de Idade - URL da Capa + URL da Miniatura Hospedado em Suporte Idioma @@ -646,10 +646,10 @@ Baixa qualidade (menor) Alta qualidade (maior) Pré visualização da miniatura da barra de busca - Comentários estão desabilitados + Os comentários estão desabilitados Marcar como visto Curtido pelo criador - Exibir fitas coloridas de Picasso no topo das imagens indicando sua fonte: vermelho para rede, azul para disco e verde para memória + Exibir fitas coloridas no topo das imagens indicando sua fonte: vermelho para rede, azul para disco e verde para memória Carregando detalhes do canal… Erro ao exibir detalhes do canal @@ -664,7 +664,7 @@ Adicionado na próxima posição da fila Adicionar a próxima posição da fila Deslize items para remove-los - Não inicia os vídeos no player reduzido, mas muda direto para o modo de tela cheia, se a rotação automatica estiver travada. Você ainda consegue acessar o player reduzido saindo da tela cheia + Não inicia os vídeos no player reduzido, mas muda direto para o modo de tela cheia, se a rotação automática estiver travada. Você ainda consegue acessar o player reduzido saindo da tela cheia Iniciar o player principal em tela cheia Sugestões de busca remotas Sugestões de busca locais @@ -678,4 +678,16 @@ Reportar erros do player Mostra uma opção de travamento ao usar o player Novos itens do feed + Notificação de relatório de erro + Notificações para reportar erros + O NewPipe encontrou um erro, toque para reportar + Crie uma notificação de erro + Nenhum gerenciador de arquivos apropriado foi encontrado para esta ação. +\nInstale um gerenciador de arquivos compatível com o Storage Access Framework. + Ocorreu um erro, consulte a notificação + Mostrar um snackbar de erro + Nenhum gerenciador de arquivos apropriado foi encontrado para esta ação. +\nInstale um gerenciador de arquivos ou tente desativar \'%s\' nas configurações de download. + Já está tocando em segundo plano + Comentário fixado \ No newline at end of file diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index c4a695c3b..b66cc6a08 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -25,7 +25,7 @@ Canal não subscrito Nome do ficheiro Mostrar indicadores de posição de reprodução nas listas - Notificações para NewPipe e para os reprodutores popup + Notificações para o reprodutor do NewPipe Desvincular (pode causar distorção) Escolha as sugestões a mostrar ao pesquisar Ficheiro ZIP inválido @@ -176,8 +176,8 @@ \n3. Clique em \"Todos os dados incluídos\", depois em \"Desmarcar todos\", depois selecione apenas \"subscrições\" e clique em \"OK\". \n4. Clique em \"Próximo passo\" e depois em \"Criar exportação\". \n5. Clique no botão \"Descarregar\" após aparecer -\n6. Clique em IMPORT FILE abaixo e selecione o ficheiro zip descarregado -\n7. [Se a importação do zip falhar] Extraia o ficheiro .csv (geralmente em \"YouTube e YouTube Music/subscriptions/subscriptions.csv\"), clique em IMPORT FILE abaixo e selecione o ficheiro csv extraído +\n6. Clique em IMPORT FILE abaixo e selecione o ficheiro .zip descarregado +\n7. [Se a importação do .zip falhar] Extraia o ficheiro .csv (geralmente em \"YouTube e YouTube Music/subscriptions/subscriptions.csv\"), clique em IMPORT FILE abaixo e selecione o ficheiro csv extraído Ativar reprodutor em segundo plano Desafio reCAPTCHA solicitado Reprodução automática @@ -281,7 +281,7 @@ pós-processamento não é possível sobrescrever o ficheiro Fonte de conteúdo/ficheiro inexistente - Notificações para uma nova versão do NewPipe + Notificações para novas versões do NewPipe Histórico Lista Remover vídeos visualizados\? @@ -678,4 +678,14 @@ Relatar erros do reprodutor Mostrar \"travar o reprodutor\" Mostra uma opção de travamento ao usar o reprodutor + Notificação de relatório de erros + Notificações para reportar erros + NewPipe encontrou um erro, toque para relatar + Ocorreu um erro, veja a notificação + Mostrar um snackbar de erro + Criar uma notificação de erro + Nenhum gestor de ficheiros apropriado foi encontrado para esta ação. +\nPor favor, instale um gestor de ficheiros ou tente desativar \'%s\' nas configurações de descarregar. + Nenhum gestor de ficheiros apropriado foi encontrado para esta ação. +\nPor favor, instale um gestor de ficheiros compatível com o Storage Access Framework. \ 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 907fc080b..d827a4d12 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -135,7 +135,7 @@ Histórico e cache Anular Notificação NewPipe - Notificações para NewPipe e para os reprodutores popup + Notificações para o reprodutor do NewPipe Sem resultados Aqui não há nada para ver Sem subscritores @@ -268,8 +268,8 @@ \n3. Clique em \"Todos os dados incluídos\", depois em \"Desmarcar todos\", depois selecione apenas \"subscrições\" e clique em \"OK\". \n4. Clique em \"Próximo passo\" e depois em \"Criar exportação\". \n5. Clique no botão \"Descarregar\" após aparecer -\n6. Clique em IMPORT FILE abaixo e selecione o ficheiro zip descarregado -\n7. [Se a importação do zip falhar] Extraia o ficheiro .csv (geralmente em \"YouTube e YouTube Music/subscriptions/subscriptions.csv\"), clique em IMPORT FILE abaixo e selecione o ficheiro csv extraído +\n6. Clique em IMPORT FILE abaixo e selecione o ficheiro .zip descarregado +\n7. [Se a importação do .zip falhar] Extraia o ficheiro .csv (geralmente em \"YouTube e YouTube Music/subscriptions/subscriptions.csv\"), clique em IMPORT FILE abaixo e selecione o ficheiro csv extraído Importe o seu perfil SoundCloud digitando o URL ou a ID.: \n \n1. Ative o modo desktop do seu navegador web (o site não está disponível para dispositivos móveis) @@ -343,7 +343,7 @@ Atualizações Ficheiro eliminado Notificação de nova versão - Notificações para uma nova versão do NewPipe + Notificações para novas versões do NewPipe Armazenamento externo indisponível Não é possível guardar no cartão SD. Repor pasta de descargas\? Não foi possível ler as guias gravadas, portanto usando as guias predefinidas @@ -678,4 +678,14 @@ Relatar erros do reprodutor Mostrar \"travar o reprodutor\" Mostra uma opção de travamento ao usar o reprodutor + Notificação de relatório de erros + Notificações para reportar erros + NewPipe encontrou um erro, toque para relatar + Ocorreu um erro, veja a notificação + Mostrar um snackbar de erro + Criar uma notificação de erro + Nenhum gestor de ficheiros apropriado foi encontrado para esta ação. +\nPor favor, instale um gestor de ficheiros ou tente desativar \'%s\' nas configurações de descarregar. + Nenhum gestor de ficheiros apropriado foi encontrado para esta ação. +\nPor favor, instale um gestor de ficheiros compatível com o Storage Access Framework. \ 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 9db2179ac..a2da5e1d6 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -134,7 +134,7 @@ Возобновить при фокусе Возобновлять воспроизведение после перерывов (например, телефонных звонков) Уведомление NewPipe - Уведомление для NewPipe в фоне и во всплывающем окне + Уведомления для плеера NewPipe Загрузки Допустимые символы имён файлов Заменяет недопустимые символы> @@ -362,8 +362,8 @@ Жест громкости Обновления Файл удалён - Уведомление об обновлении - Уведомления о новой версии NewPipe + Уведомление об обновлении приложения + Уведомления о новых версиях NewPipe Обновления Показать уведомление при наличии новой версии Доступно обновление NewPipe! @@ -589,7 +589,7 @@ Использовать миниатюру для фона уведомлений и экрана блокировки Показать миниатюру Показать уведомление при хэшировании видео - Уведомление о хэшировании + Уведомление о хэшировании видео Вычисляется хэш Недавнее Отключите, чтобы скрыть поля метаданных (автор потока, содержимое потока или поисковый запрос) @@ -694,4 +694,16 @@ Показать \"Вызвать сбой плеера\" Показать функцию вызова сбоя при работе плеера Вызвать сбой плеера + Уведомление отчёта об ошибке + Уведомления для отчётов об ошибках + NewPipe столкнулся с ошибкой, нажмите для отчёта + Произошла ошибка, подробнее в уведомлении + Показать ошибку снекбара + Создать уведомление об ошибке + Для этого действия не найдено подходящего файлового менеджера. +\nПожалуйста, установите файловый менеджер, или попробуйте отключить \'%s\' в настройках загрузок. + Для этого действия не найдено подходящего файлового менеджера. +\nПожалуйста, установите файловый менеджер, совместимый со Storage Access Framework (SAF). + Уже проигрывается в фоне + Закреплённый комментарий \ No newline at end of file diff --git a/app/src/main/res/values-sat/strings.xml b/app/src/main/res/values-sat/strings.xml index 817aacd9a..a5c59c700 100644 --- a/app/src/main/res/values-sat/strings.xml +++ b/app/src/main/res/values-sat/strings.xml @@ -60,4 +60,8 @@ ᱫᱚᱥᱟᱨ ᱠᱟᱹᱢᱤ ᱵᱩᱛᱟᱹᱢ ᱢᱟᱲᱟᱝ ᱠᱟᱹᱢᱤ ᱵᱩᱛᱟᱹᱢ ᱛᱷᱟᱹᱢᱵᱽᱱᱮᱞ ᱫᱚ ᱑:᱑ ᱮᱥᱯᱮᱠᱼᱴ ᱨᱮᱥᱤᱭᱚ ᱨᱮ ᱢᱟᱯ ᱢᱮ + ᱴᱷᱤᱠ + ᱥᱟᱰᱮ + ᱧᱮᱞ ᱠᱟᱱ ᱞᱮᱠᱷᱟ ᱪᱤᱱᱦᱟᱹ ᱠᱟᱜ ᱢᱮ + ᱯᱞᱮᱭᱚᱨ ᱠᱨᱟᱥ ᱠᱟᱜ ᱢᱮ \ No newline at end of file diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml index 550ab343a..3cea8cc97 100644 --- a/app/src/main/res/values-sc/strings.xml +++ b/app/src/main/res/values-sc/strings.xml @@ -7,7 +7,7 @@ \n3. Incarca in \"Totu sos datos incluidos\", a pustis in \"Boga sa seletzione a totus\" e a pustis galu ischerta petzi \"iscritziones\" e incarca \"AB\" \n4. Incarca in \"Passu imbeniente\" e a pustis in \"Crea un\'esportatzione\" \n5. Cando aparit, incarca in su butone \"Iscarrigamentu\" -\n6. Incarca in IMPORTA SU DOCUMENTU in suta e ischerta su documentu zip iscarrigadu +\n6. Incarca in IMPORTA SU DOCUMENTU in suta e ischerta su documentu .zip iscarrigadu \n6. [Si s\'importatzione fallit] Estrae su documentu .csv (de sòlitu tenet su nùmene\"\"YouTube and YouTube Music/subscriptions/subscriptions.csv\"), incarca in IMPORTA SU DOCUMENTU in suta e ischerta su documentu csv estratu Esportatzione de s\'iscritzione fallida Importatzione de s\'iscritzione fallida @@ -402,9 +402,9 @@ Cola a sa ventanedda Cola a s\'isfundu [Disconnotu] - Notìficas pro una versione noa de NewPipe + Notìficas pro sas versiones noas de NewPipe Notìfica de agiornamentu de s\'aplicatzione - Notìficas pro sos riproduidores in s\'isfundu e a ventanedda de NewPipe + Notìficas pro su riproduidore de NewPipe Notìficas de NewPipe Documentu Una borta ebbia @@ -454,7 +454,7 @@ Istadu predefinidu pro sos cuntenutos URL non suportadu Ammustra un\'impòsitu cando incarcas in su butone de isfundu o de sa ventanedda in sa pàgina de sos detàllios de unu vìdeu - Ammustra s\'impòsitu \"Mantene incarcadu pro pònnere in elencu\" + Ammustra s\'impòsitu \"Mantene incarcadu pro pònnere in lista\" Ammustra sos vìdeos imbenientes e simigiantes Riprodutzione automàtica Iscàrriga @@ -476,7 +476,7 @@ Imprea sos gestos pro controllare su volume de su riproduidore Gestos de controllu de su volume Sighi a riproduire (chene ripetitziones) annanghende unu vìdeu correladu a sa lista - Annanghe automaticamente unu cuntenutu a sa lista + Annanghe in automàticu su flussu imbeniente a sa lista Memòria temporànea de sos metadatos iscarrigada Boga totu sos datos de sa pàgina web in sa memòria temporànea Iscantzella sos metadatos in sa memòria temporànea @@ -545,7 +545,7 @@ Incumintza cun sa riprodutzione automaticamente — %s Lista de riprodutzione Reconnoschimentu de s\'URL fallidu. Lu cheres abèrrere cun un\'àtera aplicatzione\? - Annanghe a sa lista automaticamente + Annanghidura automàtica a sa lista Sa lista dae su riproduidore ativu at a èssere remplasada Colende dae unu riproduidore a s\'àteru dias pòdere remplasare sa lista tua Pedi una cunfirma in antis de iscantzellare una lista @@ -672,4 +672,20 @@ Chirca agiornamentos Verìfica in manera manuale pro versiones noas Controllende sos agiornamentos… + NewPipe at rilevadu un\'errore, toca pro lu sinnalare + B\'at àpidu un\'errore, pòmpia sa notìfica + Ammustra una barra de errore + Notìficas pro sinnalare errores + Notìfica de sinnalatzione de errores + Ammustra un\'optzione pro fàghere serrare de repente su riproduidore cando l\'impreas + Crea una notìfica de errore + Elementos noos de su flussu + No est istadu agatadu perunu gestore de documentos pro custa atzione. +\nPro praghere installa·nde unu o proa a inabilitare \'%s\' in sas impostatziones de iscarrigamentu. + Ammustra \"faghe serrare su riproduidore\" + No est istadu agatadu perunu gestore de documentos pro custa atzione. +\nPro praghere installa unu gestore de documentos cumpatìbile cun su \"Sistema de Atzessu a s\'Archiviatzione\". + Faghe serrare su riproduidore + Cummentu apicadu + Giai in riprodutzione in s\'isfundu \ No newline at end of file diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index e16ef6e5e..4dd02cf4a 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -79,7 +79,7 @@ Gillar Ogillar Prenumerera - Prenumererad + Prenumererar Prenumeration avslutad Kunde inte ändra prenumeration Kunde inte uppdatera prenumeration @@ -98,8 +98,8 @@ Historik och cacheminne Ångra Spela alla - NewPipe-avisering - Aviseringar för NewPipes bakgrunds- och popup-spelare + NewPipe avisering + Aviseringar för NewPipes spelare [Okänd] Kunde inte dekryptera video URL signatur Misslyckades med att spela denna ström @@ -343,7 +343,7 @@ Uppdateringar Fil raderad Avisering för appuppdatering - Aviseringar för nya NewPipe-versioner + Aviseringar för nya NewPipe versioner Extern lagring otillgänglig Fel vid läsning av sparade flikar, använder standardflikar Återställ standardvärden @@ -493,7 +493,7 @@ \nÄr du säker\? Detta kan inte ångras! Ta bort tittade videor\? Ta bort tittade - Systems standard + Systemstandard Appspråk Välj en instans \"Storage Access Framework\" möjliggör hämtningar till ett externt SD-kort @@ -678,4 +678,16 @@ Krascha spelaren Visar ett kraschalternativ vid användning av spelaren Rapporterar spelarfel i detalj i stället för att visa ett kortvarigt popup-meddelande (användbart för att diagnostisera problem) + Felrapport-avisering + Avisering för att rapportera fel + NewPipe stötte på ett fel, tryck för att rapportera + Ett fel uppstod, se aviseringen + Visa en fel snackbar + Skapa en fel avisering + Ingen lämplig filhanterare hittades för denna åtgärd. +\nInstallera en filhanterare eller testa att inaktivera \'%s\' i nedladdningsinställningarna. + Ingen lämplig filhanterare hittades för denna åtgärd. +\nInstallera en filhanterare som är kompatibel med Storage Access Framework. + Spelas redan i bakgrunden + Fäst kommentar \ No newline at end of file diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml index b009423a0..47f85a961 100644 --- a/app/src/main/res/values-te/strings.xml +++ b/app/src/main/res/values-te/strings.xml @@ -78,9 +78,9 @@ వీడియో ఆడియో మళ్ళీ ప్రయత్నించు - కె + కి ఎం - బి + బిలియన్ సభ్యులు లేరు %s సభ్యుడు @@ -233,4 +233,148 @@ ఉదాహరణను ధృవీకరించడం సాధ్యపడలేదు ఉదాహరణ ఇప్పటికే ఉంది నోటిఫికేషన్ + వినియోగదారులు + ఈవెంట్స్ + కొత్త NewPipe వెర్షన్ కోసం నోటిఫికేషన్‌లు + కంటెంట్‌కి వయస్సు పరిమితి (18+ వంటివి) ఉన్నందున పిల్లలకు అనుచితమైన కంటెంట్‌ను చూపండి + ఈ వీడియో వయో పరిమితి విధించబడింది. +\nవయో-నియంత్రిత వీడియోలతో కూడిన కొత్త YouTube విధానాల కారణంగా, NewPipe దాని వీడియో స్ట్రీమ్‌లలో దేనినీ యాక్సెస్ చేయదు మరియు దానిని ప్లే చేయడం సాధ్యం కాదు. + ఈ వీడియోకు వయో పరిమితి ఉంది. +\n +\nమీరు దీన్ని చూడాలనుకుంటే సెట్టింగ్‌లలో \"%1$s\"ని ఆన్ చేయండి. + ట్రాక్స్ + పాటలు + వెనుకగా మార్చు + ఫైల్ తొలగించబడింది + ఎల్లప్పుడూ + ఒక్కసారి మాత్రమే + ఫైల్ + థంబ్‌నెయిల్‌లోని ప్రధాన రంగు ప్రకారం నోటిఫికేషన్ రంగును Android అనుకూలీకరించండి (ఇది అన్ని పరికరాల్లో అందుబాటులో లేదని గమనించండి) + వీడియో హాష్ నోటిఫికేషన్ + వీడియో హ్యాషింగ్ పురోగతి కోసం నోటిఫికేషన్‌లు + ప్లేజాబితాలు + NewPipe ప్లేయర్‌ నోటిఫికేషన్‌లు + ప్రత్యక్ష (ప్రసారం) + వయో పరిమితి ఉన్న కంటెంట్‌ని చూపండి + YouTube యొక్క \"పరిమితం చేయబడిన మోడ్\"ని ఆన్ చేయండి + YouTube \"పరిమితం చేయబడిన మోడ్\"ని అందిస్తుంది, ఇది పరిణతి చెందిన కంటెంట్‌ను దాచిపెడుతుంది + ఛానెల్లు + వీడియోలు + ఆల్బమ్‌లు + కళాకారులు + నిలిపివేయబడినది + శుభ్రపరచు + ఉత్తమ స్పష్టత + యాప్‌ నవీకరణ నోటిఫికేషన్ + [తెలియదు] + ఫైల్ పేరు ఖాళీగా ఉండకూడదు + సేవ్ చేసిన ట్యాబ్‌లను చదవడం సాధ్యం కాలేదు, కాబట్టి డిఫాల్ట్ వాటిని ఉపయోగిస్తోంది + మీరు డిఫాల్ట్‌లను పునరుద్ధరించాలనుకుంటున్నారా\? + ప్లేబ్యాక్ స్థానాలు తొలగించబడ్డాయి + బాహ్య ప్లేయర్‌లు ఈ రకమైన లింక్‌లకు మద్దతు ఇవ్వవు + చెక్సమ్ + వీడియో URL సంతకాన్ని డీఓబ్‌ఫస్కేట్ చేయడం సాధ్యపడలేదు + GitHubపై నివేదించు + ఇక్కడ క్రికెట్‌లు తప్ప మరేమీ లేదు + ఎవరూ వినడం లేదు + ఎవరూ చూడటం లేదు + వ్యాఖ్యలు లేవు + బాహ్య SD కార్డ్‌కి డౌన్‌లోడ్ చేయడం సాధ్యం కాదు. డౌన్‌లోడ్ ఫోల్డర్ స్థానాన్ని రీసెట్ చేయాలా\? + సృష్టించు + సహాయం + డౌన్‌లోడ్ చేయడానికి స్ట్రీమ్‌లు ఏవీ అందుబాటులో లేవు + డిఫాల్ట్‌ విలువలకు మార్చు + క్రమాన్ని మార్చడానికి లాగండి + వీక్షణ చరిత్రను శుభ్రపరచుము + మొత్తం వీక్షణ చరిత్రను తొలగించాలా\? + ప్లేబ్యాక్ స్థానాలను తొలగించండి + బాహ్య నిల్వ అందుబాటులో లేదు + యాప్/UI క్రాష్ అయింది + ఆడియో స్ట్రీమ్‌లు ఏవీ కనుగొనబడలేదు + అటువంటి ఫోల్డర్ లేదు + ఇతర యాప్‌లలో ప్రదర్శించడానికి అనుమతి ఇవ్వండి + ఫార్మాట్ చేసిన నివేదికను కాపీ చేయండి + వివరణ + టోగుల్ సేవ, ప్రస్తుతం ఎంపిక చేయబడింది: + + %s శ్రోత + %s శ్రోతలు + + 100+ వీడియోలు + ∞ వీడియోలు + వ్యాఖ్యలు నిలిపివేయబడ్డాయి + మీరు reCAPTCHAని పరిష్కరించినప్పుడు NewPipe స్టోర్ చేసే కుక్కీలను క్లియర్ చేయండి + అన్ని ప్లేబ్యాక్ స్థానాలను తొలగించాలా\? + వీక్షణ చరిత్ర తొలగించబడింది + శోధన చరిత్ర తొలగించబడింది + శోధన చరిత్రను శుభ్రపరచు + శోధన కీలకపదాల చరిత్రను తొలగిస్తుంది + మొత్తం శోధన చరిత్రను తొలగించాలా\? + అన్ని ప్లేబ్యాక్ స్థానాలను తొలగిస్తుంది + ప్లే చేసిన స్ట్రీమ్‌ల చరిత్ర మరియు ప్లేబ్యాక్ స్థానాలను తొలగిస్తుంది + అటువంటి ఫైల్/కంటెంట్ సోర్స్ లేదు + దయచేసి మీ క్రాష్‌ను చర్చిస్తున్న సమస్య ఇప్పటికే ఉందో లేదో తనిఖీ చేయండి. డూప్లికేట్ టిక్కెట్‌లను క్రియేట్ చేస్తున్నప్పుడు, అసలు బగ్‌ని పరిష్కరించడానికి మేము వెచ్చించే సమయాన్ని మీరు మా నుండి తీసుకుంటారు. + వ్యాఖ్యలు + సంబంధిత అంశాలు + సభ్యుల సంఖ్య అందుబాటులో లేదు + ప్లేయర్లో కోలుకోలేని లోపం సంభవించింది + వీడియో స్ట్రీమ్‌లు ఏవీ కనుగొనబడలేదు + ఫైల్ తరలించబడింది లేదా తొలగించబడింది + ఫైల్ ఉనికిలో లేదు లేదా దానిని చదవడానికి లేదా వ్రాయడానికి అనుమతి లేదు + లోపం సంభవించింది: %1$s + + %s చూస్తున్నాడు + %s చూస్తున్నారు + + లోపాలు నివేదించడానికి నోటిఫికేషన్‌లు + లోపనివేదన నోటిఫికేషన్ + చెరుపు + వాటిని తీసివేయడానికి వాటిని స్వైప్ చేయండి + ఈ ఫైల్‌ని ప్లే చేయడానికి యాప్ ఏదీ ఇన్‌స్టాల్ చేయబడలేదు + మరింత సమాచారం మరియు వార్తల కోసం NewPipe వెబ్‌సైట్‌ని సందర్శించండి. + NewPipe ప్రాజెక్ట్ మీ గోప్యతను చాలా తీవ్రంగా పరిగణిస్తుంది. కాబట్టి, మీ సమ్మతి లేకుండా యాప్ ఎలాంటి డేటాను సేకరించదు. +\nNewPipe యొక్క గోప్యతా విధానం మీరు క్రాష్ నివేదికను పంపినప్పుడు ఏ డేటా పంపబడుతుందో మరియు నిల్వ చేయబడుతుందో వివరంగా వివరిస్తుంది. + NewPipe అనేది కాపీ లెఫ్ట్ లిబ్రే సాఫ్ట్‌వేర్: మీరు దీన్ని ఇష్టానుసారంగా ఉపయోగించవచ్చు, అధ్యయనం చేయవచ్చు మరియు మెరుగుపరచవచ్చు. ప్రత్యేకంగా మీరు ఫ్రీ సాఫ్ట్‌వేర్ ఫౌండేషన్ ద్వారా ప్రచురించబడిన GNU జనరల్ పబ్లిక్ లైసెన్స్ నిబంధనల ప్రకారం, లైసెన్స్ యొక్క వెర్షన్ 3 లేదా (మీ ఐచ్ఛికం ప్రకారం) ఏదైనా తర్వాతి సంస్కరణలో దాన్ని పునఃపంపిణీ చేయవచ్చు మరియు/లేదా సవరించవచ్చు. + ప్లేజాబితా బుక్‌మార్క్‌లు ఇంకా లేవు + గోప్యతా విధానాన్ని చదవండి + అప్‌లోడర్ అవతార్ థంబ్‌నెయిల్ + విరాళం ఇవ్వండి + కియోస్క్‌ని ఎంచుకోండి + reCAPTCHA కుక్కీలను క్లియర్ చేయండి + దీనికి ఈ అనుమతి అవసరం +\nతేలియాడే పద్ధతిలో తెరవండి + © %3$s కింద %2$s ద్వారా %1$s + చివరిగా ఆడింది + చరిత్ర, సభ్యత్వాలు, ప్లేజాబితాలు మరియు అమరికలను ఎగుమతిచేయుము + మీ ప్రస్తుత చరిత్ర, సభ్యత్వాలు, ప్లేజాబితాలు మరియు (ఐచ్ఛికంగా) సెట్టింగ్‌లను భర్తీ చేస్తుంది + డాటాబేసుని దిగుమతిచేయుము + reCAPTCHA కుక్కీలను క్లియర్ చేయండి + NewPipe లోపాన్ని ఎదుర్కొంది, నివేదించడానికి నొక్కండి + లోపం సంభవించింది, నోటిఫికేషన్ చూడండి + రద్దుచేయుము + పేరు మార్చండి + హాష్‌ని లెక్కిస్తోంది + ఇంకా డౌన్‌లోడ్ ఫోల్డర్ సెట్ చేయబడలేదు, ఇప్పుడే డిఫాల్ట్ డౌన్‌లోడ్ ఫోల్డర్‌ను ఎంచుకోండి + 1 అంశం తొలగించబడింది. + పరిష్కరించబడినప్పుడు \"పూర్తయింది\" నొక్కండి + పరిష్కరించండి + పూర్తి + చాలా ప్రత్యేక పాత్రలు + ఆండ్రాయిడ్‌లో లిబ్రే తేలికపాటి స్ట్రీమింగ్. + వాలంటీర్లు తమ ఖాళీ సమయాన్ని వెచ్చిస్తూ మీకు ఉత్తమ వినియోగదారు అనుభవాన్ని అందించడం ద్వారా NewPipe అభివృద్ధి చేయబడింది. డెవలపర్‌లు ఒక కప్పు కాఫీని ఆస్వాదిస్తున్నప్పుడు న్యూపైప్‌ని మరింత మెరుగ్గా చేయడంలో సహాయపడటానికి తిరిగి ఇవ్వండి. + తిరిగి ఇవ్వండి + వెబ్సైట్ + NewPipe యొక్క గోప్యతా విధానం + ఎక్కువగా ఆడినవి + ప్రధాన పేజీలో ఏ ట్యాబ్‌లు చూపబడతాయి + కియోస్క్ పేజీ + డిఫాల్ట్ కియోస్క్ + ఎగుమతి చేయబడింది + దిగుమతి చేయబడింది + చెల్లుబాటు అయ్యే జిప్ ఫైల్ లేదు + reCAPTCHA సవాలు + reCAPTCHA సవాలు అభ్యర్థించబడింది + ప్లేజాబితాను ఎంచుకోండి + ఇప్పటికే వెనుకగా ప్లే అవుతోంది + డాటాబేసుని ఎగుమతిచేయుము \ 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 fdc96c589..8433df39f 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -20,19 +20,19 @@ Ses indirme klasörü İndirilen ses dosyaları burada depolanır Ses dosyaları için indirme klasörünü seç - Varsayılan çözünürlük + Öntanımlı çözünürlük Kodi ile oynat Eksik Kore uygulaması yüklensin mi\? \"Kodi ile oynat\" seçeneğini göster Kodi ortam merkezi üzerinden video oynatmak için bir seçenek göster - Varsayılan ses biçimi + Öntanımlı ses biçimi Tema Koyu Açık İndir \'Sonraki\' ve \'Benzer\' videoları göster Desteklenmeyen URL - Varsayılan içerik dili + Öntanımlı içerik dili Ses Video ve ses Görünüm @@ -79,10 +79,10 @@ Lütfen daha sonra ayarlardan uygun indirme klasörü belirleyin İndirme menüsü ayarlanamadı Açılır pencere kipinde aç - Varsayılan açılır pencere çözünürlüğü + Öntanımlı açılır pencere çözünürlüğü Yüksek çözünürlükleri göster Yalnızca bazı aygıtlar 2K/4K videoları oynatabilir - Varsayılan video biçimi + Öntanımlı video biçimi Siyah Açılır pencere kipinde oynatılıyor Tümü @@ -104,7 +104,7 @@ Açılan pencerenin son boyutunu ve konumunu hatırla Bazı çözünürlüklerde sesi kaldırır Arama önerileri - Ararken gösterilecek önerileri seçin + Ararken gösterilecek önerileri seç En iyi çözünürlük NewPipe Hakkında Üçüncü Taraf Lisansları @@ -140,8 +140,8 @@ Davranış Geçmiş ve önbellek Geri al - NewPipe Bildirimi - NewPipe arka plan ve açılır pencere oynatıcıları için bildirimler + NewPipe bildirimi + NewPipe oynatıcısı için bildirimler Sonuç yok Burada cırcır böceklerinden başka bir şey yok Abone yok @@ -151,14 +151,14 @@ Görüntüleme yok - %s görüntüleme - %s görüntüleme + %s görüntülenme + %s görüntülenme Video yok Geçmiş Geçmiş Bu ögeyi arama geçmişinden silmek istiyor musunuz\? - \"Eklemek için basılı tutun\" ipucunu göster + \"Basılı tutarak kuyruğa ekle\" ipucunu göster Video \"Ayrıntılar:\" sayfasında arka plan veya açılır pencere düğmesine basıldığında ipucu göster Tümünü Oynat [Bilinmeyen] @@ -178,7 +178,7 @@ Kaldır Ayrıntılar Ses Ayarları - Kuyruğa eklemek için basılı tutun + Basılı tutarak kuyruğa ekle Arka planda oynatmayı başlat Açılır pencerede oynatmayı başlat Bağışta bulunun @@ -186,7 +186,7 @@ Bağışta bulunun Web sitesi Daha çok bilgi ve haber için NewPipe web sitesini ziyaret edin. - Varsayılan içerik ülkesi + Öntanımlı içerik ülkesi Arka Plana Geç Açılır Pencereye Geç Ana Görünüme Geç @@ -245,7 +245,7 @@ Parçanın dışında veya atımdan sonraki etkinlik yaşam döngüsündeki teslim edilemeyen Rx beklentilerinin bildirimini zorla Hızlı isabetsiz konumlama kullan İsabetsiz konumlama, oynatıcının daha düşük hassasiyetle daha hızlı konumlamasını sağlar. 5, 15 veya 25 saniyeye konumlama bununla birlikte çalışmamaktadır - Sonraki akışı kuyruğa kendiliğinden ekle + Sonraki akışı kendiliğinden kuyruğa ekle İlgili bir akış ekleyerek sonlanacak (yinelemeyen) oynatma sırasını sürdür Dosya Böylesi klasör yok @@ -269,8 +269,8 @@ \n3. \"Tüm veriler dahil\"e ve sonrasında \"Hiçbirini seçme\"ye tıklayın, ardından yalnızca \"abonelikler\"i seçin ve \"Tamam\"a tıklayın \n4. \"Sonraki adım\"a ve ardından \"Dışa aktar\"a tıklayın \n5. Göründüğünde \"İndir\" düğmesini tıklayın -\n6. Aşağıdaki DOSYAYI İÇE AKTAR düğmesini tıklayın ve indirilen zip dosyasını seçin -\n7. [Zip içe aktarma işlemi başarısız olursa] .csv dosyasını çıkarın (genellikle \"YouTube and YouTube Music/subscriptions/subscriptions.csv\"), aşağıdaki DOSYAYI İÇE AKTAR düğmesini tıklayın ve çıkarılan csv dosyasını seçin +\n6. Aşağıdaki DOSYAYI İÇE AKTAR düğmesini tıklayın ve indirilen .zip dosyasını seçin +\n7. [.zip içe aktarma işlemi başarısız olursa] .csv dosyasını çıkarın (genellikle \"YouTube and YouTube Music/subscriptions/subscriptions.csv\"), aşağıdaki DOSYAYI İÇE AKTAR düğmesini tıklayın ve çıkarılan csv dosyasını seçin URL\'yi veya ID\'nizi yazarak SoundCloud profilini içe aktarın: \n \n1. Web tarayıcısında \"masaüstü kipi\" etkinleştirin (site, mobil aygıtlar için uygun değildir) @@ -293,7 +293,7 @@ Ayır (bozulmaya neden olabilir) İndirilebilecek akış yok Yeğlenen \'aç\' eylemi - İçerik açılırken varsayılan eylem — %s + İçerik açılırken öntanımlı eylem — %s Alt yazılar Oynatıcı alt yazı metin ölçeğini ve arka plan biçimini değiştirin. Etkili olması için uygulamayı yeniden başlatma gerektirir Bu dosyayı oynatmak için herhangi bir uygulama yüklü değil @@ -338,13 +338,13 @@ Oynatıcının parlaklığını denetlemek için hareketleri kullan Güncellemeler Dosya silindi - Uygulama Güncelleme Bildirimi - Yeni NewPipe sürümü için bildirimler + Uygulama güncelleme bildirimi + Yeni NewPipe sürümleri için bildirimler Dış depolama kullanılamıyor Dış SD karta indirilemiyor. İndirme klasörü konumu sıfırlansın mı\? - Kayıtlı sekmeler okunamadı, bu nedenle varsayılanlar kullanılıyor - Varsayılanları geri yükle - Varsayılanları geri yüklemek istiyor musunuz\? + Kayıtlı sekmeler okunamadı, bu nedenle öntanımlılar kullanılıyor + Öntanımlıları geri yükle + Öntanımlıları geri yüklemek istiyor musunuz\? Abone sayısı mevcut değil Ana sayfada hangi sekmeler gösterilir Güncellemeler @@ -422,7 +422,7 @@ %s video %s video - Varsayılan Kiosk + Öntanımlı Kiosk Kimse izlemiyor %s izliyor @@ -454,7 +454,7 @@ İndirilen dosyaları sil Diğer uygulamaların üzerinde görüntüleme izni ver Uygulama dili - Sistem varsayılanı + Sistem öntanımlısı Çözüldüğünde \"Bitti\" düğmesine basın Bitti Videolar @@ -546,7 +546,7 @@ Oynatmayı kendiliğinden başlat — %s Oynatma kuyruğu URL tanınamadı. Başka bir uygulamayla açılsın mı\? - Kendiliğinden kuyruğa ekle + Kendiliğinden kuyrukla Etkin oynatıcının kuyruğu değiştirilecek Bir oynatıcıdan diğerine geçmek kuyruğunuzu değiştirebilir Bir kuyruğu temizlemeden önce onay iste @@ -578,7 +578,7 @@ Bildirimi renklendir Hash hesaplanıyor Video dosya özetleme süreci için bildirimler - Video Dosya Özeti Bildirimi + Video dosya özeti bildirimi En Son Akış oluşturucu, akış içeriği veya bir arama isteği hakkında ek bilgiler içeren meta bilgi kutularını gizlemek için kapatın Üst bilgiyi göster @@ -673,4 +673,17 @@ Yeni sürümleri el ile denetleyin Güncellemeler denetleniyor… Yeni akış ögeleri + Hata raporlama bildirimi + NewPipe hatayla karşılaştı, bildirmek için dokun + Hata oluştu, bildirime bakın + \"Oynatıcıyı çöktür\"ü göster + Hata bildirimi oluştur + Hata balonu göster + Bu eyleme uygun dosya yönetici yok. +\nLütfen dosya yönetici kurun veya indirme ayarlarında \'%s\' devre dışı bırakın. + Bu eyleme uygun dosya yönetici bulunamadı. +\nLütfen Depolama Erişimi Çerçevesi uyumlu dosya yönetici kurun. + Hata raporları için bildirimler + Oynatıcı kullanırken çöktürme seçeneği gösterir + Oynatıcıyı çöktür \ 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 6c5da09b3..c00cbd017 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -11,8 +11,8 @@ Налаштування Ви мали на увазі: «%1$s»\? Поширити через - Викор. зовнішній відеопрогравач - Викор. зовнішній аудіопрогравач + Зовнішній відеопрогравач + Зовнішній аудіопрогравач Тека для завантаження відео Виберіть теку для завантаження відеофайлів Виберіть теку для завантаження аудіофайлів @@ -35,7 +35,7 @@ Переважна мова вмісту Відео та звук Зовнішній вигляд - Відтворення на тлі + Відтворення у фоновому режимі Вміст Вміст із віковими обмеженнями Наживо @@ -85,7 +85,7 @@ Вкажіть теку для завантажень пізніше в налаштуваннях Програвач потокового відео не знайдений (ви можете встановити VLC для програвання). Відкрити у віконному режимі - Прибирає звук при певних роздільних здатностях + Прибирає звук за певної роздільності Підписатися Ви підписалися Ви відписалися від каналу @@ -93,7 +93,7 @@ Не вдалося оновити підписку Підписки Новинки - На тлі + У фоновому режимі У вікні Типова роздільність вікна Не всі пристрої можуть відтворювати 2K/4K-відео @@ -127,14 +127,14 @@ Завжди Лише раз Сповіщення NewPipe - Сповіщення для програвачів NewPipe на тлі й у вікні + Сповіщення для програвачів NewPipe [Невідомо] Перейти у фоновий режим Перемкнути у вікно Перемкнути на головну Імпортувати базу даних Експортувати базу даних - Поточні підписки, списки відтворення, історія і (за бажанням) налаштування буде замінено + Поточні підписки, добірки, історія і (за бажанням) налаштування буде замінено Експорт підписок, списків відтворення, історії та налаштувань Не вдалося відтворити цей потік Відновлення після помилки програвача @@ -255,8 +255,8 @@ Моніторинг втрат пам\'яті може призвести до нереагування застосунку під час запису дампу Звітувати про помилки життєвого циклу застосунку Примусове звітування про неможливість доставлення Rx-винятків, які відбуваються за межами фрагменту або діяльності життєвого циклу після усунення - Викор. швидкий неточний пошук - Неточний пошук дозволяє програвачеві рухатися позиціями швидше, проте з меншою точністю + Швидкий неточний пошук + Швидше, але не точне перемотування. Перехід на 5, 15 або 25 секунд не працюватиме Автододавання в чергу наступної трансляції Продовжити при завершені (не повторюваної) черги, додавши повʼязаний запис Файл @@ -333,13 +333,13 @@ Пропускати тихі проміжки Крок Скинути - Зменшити при перемиканні програм - Дія при перемиканні до інших програм від головного відеопрогравача — %s + Зменшити при перемиканні застосунку + Дія при перемиканні до інших застосунків з основного відеопрогравача — %s Нічого - Зменшити до програвача на тлі + Зменшити до програвача у фоновому режимі Зменшити до програвача у вікні Канали - Списки відтворення + Добірки Доріжки Користувачі Режим перегляду списком @@ -355,7 +355,7 @@ Події Файл видалено Сповіщення про оновлення застосунку - Сповіщення про нову версію NewPipe + Сповіщення про нові версії NewPipe Зовнішнє сховище недоступне Відновити типові налаштування Відновити типові значення\? @@ -379,8 +379,8 @@ Завантажений файл з такою назвою вже існує Файл з такою назвою вже завантажується Показати помилку - Цільову теку не можливо створити - Файл не можливо створити + Неможливо створити цільову теку + Неможливо створити файл Захищене з\'єднання не встановлено Сервер не знайдено Не вдалося з\'єднатися із сервером @@ -396,10 +396,10 @@ Помилка зчитування збережених вкладок. Використовуються типові вкладки Вкладки, показані на головній сторінці Показувати сповіщення з пропозицією оновити застосунок за наявності нової версії - Корисно під час перемикання на мобільні дані, хоча деякі завантаження не можливо призупинити + Корисно під час перемикання на мобільні дані, хоча деякі завантаження неможливо призупинити Показувати коментарі Вимкніть, щоб сховати коментарі - Самовідтворення + Автовідтворення Коментарі відсутні Не вдалося завантажити коментарі Закрити @@ -604,7 +604,7 @@ Реп\'яшки (cookies) reCAPTCHA видалено Очистити реп\'яшки (cookies) reCAPTCHA Сповіщення про перебіг відеогешування - Сповіщення про відеогешування + Сповіщення про відеохешування Це відео має вікові обмеження. \nЗгідно з новою політикою YouTube щодо відео з віковими обмеженнями NewPipe не може мати доступ до жодного потоку цього відео і, таким чином, не має можливості відтворити його. Показувати вміст, який, можливо, не підходить для дітей, бо має вікове обмеження (наприклад, 18+) @@ -642,7 +642,7 @@ Дозволити виділяти текст в описі Тепер можна виділяти текст в описі. Зауважте, що сторінка може мигати і посилання можуть не працювати в режимі виділення. %s подає таку причину: - Не можливо завантажити стрічку для «%s». + Неможливо завантажити стрічку для «%s». Помилка завантаження стрічки Обліковий запис автора припинено. \nNewPipe не зможе завантажити цей канал у майбутньому. @@ -693,4 +693,16 @@ Повідомити про помилки програвача Збій програвача Повне повідомлення про помилки програвача замість, короткого звіту (корисно для діагностики проблем) + Сповіщення про звіт про помилку + Сповіщення для звітів про помилки + Сталася помилка NewPipe, торкніться, щоб звітувати + Сталася помилка. Перегляньте сповіщення + Для цієї дії не знайдено відповідного файлового менеджера. +\nУстановіть файловий менеджер або спробуйте вимкнути «%s» у налаштуваннях завантажень. + Для цієї дії не знайдено відповідного файлового менеджера. +\nУстановіть файловий менеджер, сумісний зі Storage Access Framework. + Показати панель помилок + Створити сповіщення про помилку + Уже відтворюється у фоновому режимі + Закріплений коментар \ No newline at end of file diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 520040820..fc923dc3d 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -147,7 +147,7 @@ Theo dõi các video đã xem Tiếp tục phát Tiếp tục phát sau khi bị gián đoạn (ví dụ: cuộc gọi điện thoại) - Hiển thị mẹo \"Giữ để nối thêm\" + Hiển thị mẹo \"Giữ để thêm vào hàng đợi\" Hiển thị mẹo khi nhấn nút phát trong nền hoặc phát trên popup trong trang \"Chi tiết\" Quốc gia nội dung mặc định Phát @@ -163,7 +163,7 @@ Chỉ một lần Tập tin Thông báo NewPipe - Thông báo cho trình phát popup và trình phát nền + Thông báo cho trình phát của NewPipe [Không xác định] Chuyển sang nền Chuyển sang Popup @@ -656,4 +656,21 @@ Đã cho mục tiếp vào hàng đợi Cho mục tiếp vào hàng đợi Đang thực hiện...Có thể mất một lúc + Thông báo báo cáo lỗi + Thông báo để báo cáo lỗi + NewPipe đã gặp lỗi, nhấn để báo cáo + Có lỗi xảy ra, hãy xem thông báo + Hiện \"làm trình phát dừng\" + Hiện tùy chọn dừng đột ngột khi sử dụng trình phát + Hiện thanh báo lỗi + Tạo thông báo lỗi + Kiểm tra cập nhật + Kiểm tra phiên bản mới theo cách thủ công + Đang kiểm tra cập nhật… + Mục feed mới + Làm trình phát dừng + Không tìm thấy ứng dụng quản lý tệp phù hợp nào để thực hiện hành động. +\nVui lòng cài đặt ứng dụng quản lý tệp tương thích với Storage Access Framework. + Không tìm thấy ứng dụng quản lý tệp phù hợp nào để thực hiện hành động. +\nVui lòng cài đặt ứng dụng quản lý tệp hoặc tắt \'%s\' trong cài đặt tải xuống. \ No newline at end of file diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 05c867993..306cd17e2 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -112,7 +112,7 @@ 特許 在 Android 上運作自由輕便的 Youtube 前端。 檢視我們的 GitHub - NewPipe 的特許 + NewPipe 嘅授權協議 無論您僅想分享您對 NewPipe 的一些構思,還是願意設計和翻譯程式介面,甚至想幫我們整理或重新編寫原始碼,我們都無任歡迎。貢獻更多,應用程式便會變得更好! 檢閱特許 貢獻 @@ -243,4 +243,159 @@ 您係咪要還原返做預設嗰個樣? 複製執咗格式嘅報告 乜都搵唔到 + 名稱 + 接受 + 關閉 + 下載失敗 + + 完成咗 %s 個下載 + + 產生獨一無二嘅名稱 + 匯入檔案 + 匯出緊… + 先前嘅匯出 + 惟請注意:呢項操作可能相當消耗網絡數據。 +\n +\n您係咪要繼續? + 幾時都唔使 + 自動 + 低畫質 (較細) + 唔顯示 + 撳一下去下載 + 無觀看次數 + + %s 個人聽緊 + + 明白 + 排緊隊 + 後期處理緊 + 暫停咗 + 無限制 + 自動產生 (搵唔到上載者) + 代替字元 + 個 ZIP 檔無效 + 最多讚 + 匯出咗 + + %s 次觀看 + + 無人睇緊 + + %s 部影片 + + 無留言 + 計算緊雜湊 + 檔名准用啲咩字元 + 無效嘅字元會用呢一楷嚟代替 + 去 NewPipe 網站睇更多資訊同最新消息。 + 閱讀私隱政策 + 匯入咗 + 攞緊資訊… + 填滿 + 縮放 + 匯入唔到訂閱 + 節奏 + 播放速度控掣 + 系統預設噉樣 + 檢查有冇更新 + 個 App 用咩文 + 睇咗嗰啲剷咗佢 + 係咪要剷走睇咗嘅影片? + 網站 + NewPipe 嘅私隱政策 + 改過個名 + 音高 + 完成咗 + 無影片 + 影片播放器 + 僅限用 Wi-Fi 嘅時候 + 高畫質 (較大) + 無訂閱者 + + %s 位訂閱者 + + 訂閱者人數不詳 + + %s 個人睇緊 + + 無人聽緊 + 100+ 部影片 + ∞ 部影片 + 未開放留言 + 建立 + 未設定下載資料夾,請立即揀選預設嘅下載資料 + 刪除咗 1 個項目。 + 執執佢 + 未裝 app 嚟播放呢個檔案 + 搞掂 + NewPipe 專案非常認真看待您嘅私隱。因此,呢個 app 未徵得您嘅同意係唔會收集任何資料。 +\nNewPipe 嘅私隱政策,詳加解釋當您傳送彈 app 報告嘅時候有咩資料會傳送同保存。 + 最近播放 + 最常播放 + 頭版內容 + 頭版要擺放邊啲分頁 + 滑走啲項目去剷走佢 + 空白頁 + 重新開過個 app 之後就會轉新語言 + 時興 + 頭位 50 + 最新同大熱 + 警告:未能匯入晒全部檔案。 + 噉樣做會冚咗您而家嘅設定個囉噃。 + 您想唔想匯入埋啲設定? + 載入唔到留言 + 最近新加 + 剷咗佢 + 詳細資料 + 唔使靜音 + 背景播放器 + 浮面播放器 + 幾時都問 + 載入緊請求嘅內容 + 字幕 + 無字幕 + 自動產生 + 貼合 + 匯入 + 由邊處匯入: + 匯出去邊處: + 匯入緊… + 無聲嘅時候快轉 + 重設 + 為符合歐盟嘅《通用數據保障條例》(GDPR) 規範,我哋謹請您注意 NewPipe 嘅私隱政策。請仔細閱讀。 +\n您必須接受先可以傳送錯誤報告畀我哋。 + 拒絕 + 用流動數據嘅時候限制解像度 + 更新 + 出咗新版本嘅時候,顯示通知提示升級個 app + 手動檢查下有冇新版本 + NewPipe 出咗更新! + 仲等緊 + 恢復緊 + 動作被系統拒絕咗 + 檢查緊有冇更新… + 覆寫 + + %d 個鐘 + + + %d 日 + + 有咩新嘢 + + %d 秒 + + + %d 分鐘 + + 改過個名 + 字母同數目字 + 大部份特殊字元 + 下載 + 課金 + 匯出唔到訂閱 + 修改播放器字幕啲字嘅大細同背景款式。要重新開過個 app 先會生效 + 執好就撳一下「搞掂」 + 靜音 + 處理緊… 可能要等等 \ No newline at end of file diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index b6bd8a096..d43ceb155 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -124,7 +124,7 @@ 歷史記錄與快取 復原 NewPipe 通知 - NewPipe 背景播放與懸浮模式播放器的通知 + NewPipe 播放器的通知 沒有結果 這裡空空如也 無訂閱者 @@ -666,4 +666,16 @@ 完整回報播放器錯誤,而非顯示短暫的 toast 訊息(用於診斷問題) 顯示「播放器當機」 使用播放器時顯示當機選項 + 錯誤回報通知 + 回報錯誤的通知 + 顯示錯誤 SnackBar + 建立錯誤通知 + 找不到適合此動作的檔案管理程式。 +\n請安裝相容於儲存空間存取框架的檔案管理員。 + 找不到適合此動作的檔案管理程式。 +\n請安裝檔案管理程式或在下載設定嘗試停用「%s」。 + NewPipe 遇到錯誤,點擊以回報 + 發生錯誤,請檢視通知 + 釘選留言 + 已經在背景播放 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ffddf94b0..5336861b3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -466,7 +466,15 @@ Previous export Could not import subscriptions Could not export subscriptions - Import YouTube subscriptions from Google takeout:\n\n1. Go to this URL: %1$s\n2. Log in when asked\n3. Click on \"All data included\", then on \"Deselect all\", then select only \"subscriptions\" and click \"OK\"\n4. Click on \"Next step\" and then on \"Create export\"\n5. Click on the \"Download\" button after it appears\n6. Click on IMPORT FILE below and select the downloaded zip file\n7. [If the zip import fails] Extract the .csv file (usually under \"YouTube and YouTube Music/subscriptions/subscriptions.csv\"), click on IMPORT FILE below and select the extracted csv file + Import YouTube subscriptions from Google takeout: +\n +\n1. Go to this URL: %1$s +\n2. Log in when asked +\n3. Click on \"All data included\", then on \"Deselect all\", then select only \"subscriptions\" and click \"OK\" +\n4. Click on \"Next step\" and then on \"Create export\" +\n5. Click on the \"Download\" button after it appears +\n6. Click on IMPORT FILE below and select the downloaded .zip file +\n7. [If the .zip import fails] Extract the .csv file (usually under \"YouTube and YouTube Music/subscriptions/subscriptions.csv\"), click on IMPORT FILE below and select the extracted csv file Import a SoundCloud profile by typing either the URL or your ID:\n\n1. Enable \"desktop mode\" in a web-browser (the site is not available for mobile devices)\n2. Go to this URL: %1$s\n3. Log in when asked\n4. Copy the profile URL you were redirected to. yourID, soundcloud.com/yourid Keep in mind this operation can be network expensive.\n\nDo you want to continue? diff --git a/fastlane/metadata/android/es/changelogs/981.txt b/fastlane/metadata/android/es/changelogs/981.txt new file mode 100644 index 000000000..d78d60488 --- /dev/null +++ b/fastlane/metadata/android/es/changelogs/981.txt @@ -0,0 +1,2 @@ +Eliminada la compatibilidad con MediaParser para poder solucionar problemas de reanudación de la reproducción tras el almacenamiento en búfer en Android 11+. +Deshabilitado el túnel de medios en Philips QM16XE para poder solucionar problemas de reproducción. diff --git a/fastlane/metadata/android/fa/changelogs/981.txt b/fastlane/metadata/android/fa/changelogs/981.txt new file mode 100644 index 000000000..fce4da4ad --- /dev/null +++ b/fastlane/metadata/android/fa/changelogs/981.txt @@ -0,0 +1,2 @@ +برداشتن پشتیبانی MediaParser برای تعمیر شکست از سر گیری پخش پس از میانگیری روی اندروید ۱۱+. +تونل‌زنی رسانهٔ از کارافتاده روی QM16XE فیلیپس برای تعمیر مشکلات پخش. diff --git a/fastlane/metadata/android/he/changelogs/981.txt b/fastlane/metadata/android/he/changelogs/981.txt new file mode 100644 index 000000000..8a5f0d04a --- /dev/null +++ b/fastlane/metadata/android/he/changelogs/981.txt @@ -0,0 +1,2 @@ +הוסרה תמיכה ב־MediaParser כדי לתקן המשך נגינה שנכשל לאחר אגירה ב־Android 11+‎. +הושבת תיעול מדיה ב־Philips QM16XE כדי לתקן בעיות נגינה. diff --git a/fastlane/metadata/android/hi/changelogs/63.txt b/fastlane/metadata/android/hi/changelogs/63.txt new file mode 100644 index 000000000..557b8c29b --- /dev/null +++ b/fastlane/metadata/android/hi/changelogs/63.txt @@ -0,0 +1,8 @@ +### सुधार +- आयात/निर्यात सेटिंग्स #1333 +- ओवरड्रॉ को कम करें (प्रदर्शन सुधार) #1371 +- कोड में कुछ छोटे सुधार #1375 +- जीडीपीआर के बारे में सब कुछ जोड़ें #1420 + +### ठीक किए गए +- डाउनलोडर: .गीगा फाइलों से अधूरे डाउनलोड लोड करने पर क्रैश को ठीक करें #1407 diff --git a/fastlane/metadata/android/hi/full_description.txt b/fastlane/metadata/android/hi/full_description.txt index 9ab5b312b..47c8826d7 100644 --- a/fastlane/metadata/android/hi/full_description.txt +++ b/fastlane/metadata/android/hi/full_description.txt @@ -1 +1 @@ -न्यूपाइप किसी भी गुगल फ्रेमवर्क लाइब्रेरी, या यूट्यूब एपीआई का उपयोग नहीं करता है। यह केवल वेबसाइट को पार्स करता है ताकि इसकी आवश्यकता वाली जानकारी हासिल की जा सके। इसलिए इस ऐप का उपयोग गुगल सेवाओं के स्थापित किए बिना उपकरणों पर किया जा सकता है। इसके अलावा, आपको न्यूपाइप का उपयोग करने के लिए युट्युब खाते की आवश्यकता नहीं है, और यह मुक्त और खुला है। +न्यूपाइप किसी भी गुगल फ्रेमवर्क लाइब्रेरी, या यूट्यूब एपीआई का उपयोग नहीं करता है। यह केवल वेबसाइट को पार्स करता है ताकि इसकी आवश्यकता वाली जानकारी हासिल की जा सके। इसलिए इस ऐप का उपयोग गुगल सेवाओं के स्थापित किए बिना उपकरणों पर किया जा सकता है। इसके अलावा, आपको न्यूपाइप का उपयोग करने के लिए युट्युब खाते की आवश्यकता नहीं है, और यह मुक्त और खुला है। diff --git a/fastlane/metadata/android/hu/changelogs/64.txt b/fastlane/metadata/android/hu/changelogs/64.txt new file mode 100644 index 000000000..4ba4191a9 --- /dev/null +++ b/fastlane/metadata/android/hu/changelogs/64.txt @@ -0,0 +1,8 @@ +### Fejlesztések +- Lehetőség a videó minőségének korlátozására mobiladat-kapcsolaton #1339 +- Az alkalmazás bezárásáig megjegyzi a fényerő-beállítást #1442 +- Jobb letöltési teljesítmény gyengébb CPU-kon #1431 +- médiamunkamenet (működő) támogatásának hozzáadása #1433 + +### Javítások +- A letöltések megnyitásánál történő összeomlás javítása (a javítás mostantól érhető el a kiadási verziókban is) #1441 diff --git a/fastlane/metadata/android/hu/full_description.txt b/fastlane/metadata/android/hu/full_description.txt index df1f8cb77..772992ee4 100644 --- a/fastlane/metadata/android/hu/full_description.txt +++ b/fastlane/metadata/android/hu/full_description.txt @@ -1 +1 @@ -A NewPipe nem használ semmilyen Google keretrendszer könyvtárat, sem a YouTube API-t. Csupán a weboldalt dolgozza fel, hogy kinyerje a szükséges információkat. Így ez az alkalmazás a Google Szolgáltatások nélkül futó eszközökön is használható. Továbbá a NewPipe használatához nincs szükség YouTube-fiókra sem. A NewPipe szabad és nyílt forráskódú szoftver. +A NewPipe nem használ semmilyen Google keretrendszer programkönyvtárat, sem a YouTube API-t. Csupán a weboldalt dolgozza fel, hogy kinyerje a szükséges információkat. Így ez az alkalmazás a Google Szolgáltatások nélkül futó eszközökön is használható. Továbbá a NewPipe használatához nincs szükség YouTube-fiókra sem. A NewPipe szabad és nyílt forráskódú szoftver. diff --git a/fastlane/metadata/android/hu/short_description.txt b/fastlane/metadata/android/hu/short_description.txt new file mode 100644 index 000000000..0a96f5e90 --- /dev/null +++ b/fastlane/metadata/android/hu/short_description.txt @@ -0,0 +1 @@ +Egy ingyenes és könnyű YouTube előtétprogram Androidra. diff --git a/fastlane/metadata/android/nl/changelogs/957.txt b/fastlane/metadata/android/nl/changelogs/957.txt index f8e495930..ce334f310 100644 --- a/fastlane/metadata/android/nl/changelogs/957.txt +++ b/fastlane/metadata/android/nl/changelogs/957.txt @@ -1,4 +1,4 @@ -• Voeg specifieke enqeue-acties samen +• Voeg specifieke wachtrij-acties samen • 2-vinger-beweging om de speler te sluiten • Wis reCAPTHA-cookies • Optie om meldingen niet te kleuren diff --git a/fastlane/metadata/android/nl/full_description.txt b/fastlane/metadata/android/nl/full_description.txt index 290373183..2fa0ff5d0 100644 --- a/fastlane/metadata/android/nl/full_description.txt +++ b/fastlane/metadata/android/nl/full_description.txt @@ -1 +1 @@ -NewPipe gebruikt geen enkele Google framework library, of de YouTube API. Het parseert alleen de website om informatie die het nodig heeft te krijgen. Daardoor kan deze app gebruikt worden zonder Google Services geïnstalleerd te hebben. Daarnaast heb je geen YouTube-account nodig om NewPipe te gebruiken, en is het FLOSS. +NewPipe gebruikt geen enkele Google framework library, noch de YouTube API. Het analyseert de website alleen op zoek naar informatie die het nodig heeft. Daardoor kan deze app gebruikt worden zonder Google Services installatie. Daarnaast heb je geen YouTube-account nodig om NewPipe te gebruiken en is het FLOSS. diff --git a/fastlane/metadata/android/pt-PT/changelogs/968.txt b/fastlane/metadata/android/pt-PT/changelogs/968.txt new file mode 100644 index 000000000..96f3d0fba --- /dev/null +++ b/fastlane/metadata/android/pt-PT/changelogs/968.txt @@ -0,0 +1,7 @@ +Adicionada a opção de detalhes do canal ao menu de pressão prolongada. +Adicionada funcionalidade para renomear o nome da lista de reprodução da interface da lista de reprodução. +Permitir que o utilizador faça uma pausa enquanto um vídeo está a ser gravado no buffer. +Polido o tema branco. +Corrigida a sobreposição de fontes quando se utiliza uma fonte de tamanho maior. +Corrigido nenhum vídeo em dispositivos Formuler e Zephier. +Corrigidas várias falhas. diff --git a/fastlane/metadata/android/pt-PT/changelogs/970.txt b/fastlane/metadata/android/pt-PT/changelogs/970.txt new file mode 100644 index 000000000..8d43bb9db --- /dev/null +++ b/fastlane/metadata/android/pt-PT/changelogs/970.txt @@ -0,0 +1,11 @@ +Novo +- Mostrar metadados de conteúdo (marcações, categorias, licença, ...) abaixo da descrição +- Adicionado "Mostrar detalhes do canal" opção em listas de reprodução remotas (não locais) +- Adicionado "Abrir no browser" opção para o menu de pressão longa + +Fixo +- Fixação da falha de rotação na página de detalhes do vídeo +- Fixo botão "Reproduzir com Kodi" no reprodutor sempre pede instalar Kore +- Caminhos de importação e exportação fixos e melhorados +- [YouTube] Fixo comentário e contagem +... diff --git a/fastlane/metadata/android/pt-PT/changelogs/977.txt b/fastlane/metadata/android/pt-PT/changelogs/977.txt new file mode 100644 index 000000000..340ab4d4f --- /dev/null +++ b/fastlane/metadata/android/pt-PT/changelogs/977.txt @@ -0,0 +1,10 @@ +• Adicionado botão "reproduzir seguinte" ao menu de toque longo +• Adicionado prefixo do caminho curto do YouTube ao filtro +• Importação de configurações corrigida +• Trocada a posição da barra de pesquisa com os botões do reprodutor no ecrã da fila +• Várias correções de MediasessionManager +• Barra de pesquisa corrigida após o final do vídeo +• Tunelamento de mídia desativado no RealtekATV +• Expandida a área clicável dos botões minimizados + +Ver também o registo de alterações e o blogue abaixo. diff --git a/fastlane/metadata/android/pt-PT/changelogs/978.txt b/fastlane/metadata/android/pt-PT/changelogs/978.txt new file mode 100644 index 000000000..be505a16c --- /dev/null +++ b/fastlane/metadata/android/pt-PT/changelogs/978.txt @@ -0,0 +1 @@ +Corrigida a verificação se existe uma nova versão do NewPipe. Esta verificação era muitas vezes executada demasiado cedo, o que levava a uma falha da aplicação. Agora isto deve estar corrigido. diff --git a/fastlane/metadata/android/pt-PT/changelogs/979.txt b/fastlane/metadata/android/pt-PT/changelogs/979.txt new file mode 100644 index 000000000..52b1baaff --- /dev/null +++ b/fastlane/metadata/android/pt-PT/changelogs/979.txt @@ -0,0 +1,2 @@ +- Problema ao retomar a reprodução corrigido +- Melhorias para garantir que o serviço que determina se o NewPipe deve verificar se existe uma nova versão não seja iniciado em segundo plano diff --git a/fastlane/metadata/android/pt-PT/changelogs/980.txt b/fastlane/metadata/android/pt-PT/changelogs/980.txt new file mode 100644 index 000000000..2def4bc5a --- /dev/null +++ b/fastlane/metadata/android/pt-PT/changelogs/980.txt @@ -0,0 +1,13 @@ +Novo +- Adicionado "Adicionar à lista de reprodução" opção para o menu compartilhar +- Adicionado suporte para ligações curtos y2u.be e PeerTube + +Melhorado +- Controles de Velocidade de Reprodução mais compactos +- Feed destaca novos itens agora +- A opção "Mostrar itens observados" no feed está agora gravada + +Fixo +- Fixo a extração de likes e dislikes da YouTube +- Repetição automática fixa após retornar do fundo +... diff --git a/fastlane/metadata/android/pt-PT/changelogs/981.txt b/fastlane/metadata/android/pt-PT/changelogs/981.txt new file mode 100644 index 000000000..1e7c23f50 --- /dev/null +++ b/fastlane/metadata/android/pt-PT/changelogs/981.txt @@ -0,0 +1,2 @@ +Removido o suporte ao MediaParser para corrigir falha de reprodução após buffer no Android 11+. +Tunelamento de mídia desativado no Philips QM16XE para corrigir problemas de reprodução. diff --git a/fastlane/metadata/android/pt/changelogs/965.txt b/fastlane/metadata/android/pt/changelogs/965.txt new file mode 100644 index 000000000..de54cf139 --- /dev/null +++ b/fastlane/metadata/android/pt/changelogs/965.txt @@ -0,0 +1,6 @@ +Corrigido o crash que ocorria ao reordenar grupos de canais. +Corrigida a obtenção de mais vídeos do YouTube a partir de canais e listas de reprodução. +Corrigida a obtenção de comentários do YouTube. +Adicionado suporte a /watch/, /v/ e /w/ subpaths nas URLs do YouTube. +Corrigida a extração de id de cliente SoundCloud e conteúdo geo-restrito. +Adicionada a localização Curda do Norte. diff --git a/fastlane/metadata/android/pt/changelogs/968.txt b/fastlane/metadata/android/pt/changelogs/968.txt new file mode 100644 index 000000000..96f3d0fba --- /dev/null +++ b/fastlane/metadata/android/pt/changelogs/968.txt @@ -0,0 +1,7 @@ +Adicionada a opção de detalhes do canal ao menu de pressão prolongada. +Adicionada funcionalidade para renomear o nome da lista de reprodução da interface da lista de reprodução. +Permitir que o utilizador faça uma pausa enquanto um vídeo está a ser gravado no buffer. +Polido o tema branco. +Corrigida a sobreposição de fontes quando se utiliza uma fonte de tamanho maior. +Corrigido nenhum vídeo em dispositivos Formuler e Zephier. +Corrigidas várias falhas. diff --git a/fastlane/metadata/android/pt/changelogs/970.txt b/fastlane/metadata/android/pt/changelogs/970.txt new file mode 100644 index 000000000..8d43bb9db --- /dev/null +++ b/fastlane/metadata/android/pt/changelogs/970.txt @@ -0,0 +1,11 @@ +Novo +- Mostrar metadados de conteúdo (marcações, categorias, licença, ...) abaixo da descrição +- Adicionado "Mostrar detalhes do canal" opção em listas de reprodução remotas (não locais) +- Adicionado "Abrir no browser" opção para o menu de pressão longa + +Fixo +- Fixação da falha de rotação na página de detalhes do vídeo +- Fixo botão "Reproduzir com Kodi" no reprodutor sempre pede instalar Kore +- Caminhos de importação e exportação fixos e melhorados +- [YouTube] Fixo comentário e contagem +... diff --git a/fastlane/metadata/android/pt/changelogs/980.txt b/fastlane/metadata/android/pt/changelogs/980.txt new file mode 100644 index 000000000..2def4bc5a --- /dev/null +++ b/fastlane/metadata/android/pt/changelogs/980.txt @@ -0,0 +1,13 @@ +Novo +- Adicionado "Adicionar à lista de reprodução" opção para o menu compartilhar +- Adicionado suporte para ligações curtos y2u.be e PeerTube + +Melhorado +- Controles de Velocidade de Reprodução mais compactos +- Feed destaca novos itens agora +- A opção "Mostrar itens observados" no feed está agora gravada + +Fixo +- Fixo a extração de likes e dislikes da YouTube +- Repetição automática fixa após retornar do fundo +... diff --git a/fastlane/metadata/android/pt/changelogs/981.txt b/fastlane/metadata/android/pt/changelogs/981.txt new file mode 100644 index 000000000..1e7c23f50 --- /dev/null +++ b/fastlane/metadata/android/pt/changelogs/981.txt @@ -0,0 +1,2 @@ +Removido o suporte ao MediaParser para corrigir falha de reprodução após buffer no Android 11+. +Tunelamento de mídia desativado no Philips QM16XE para corrigir problemas de reprodução. diff --git a/fastlane/metadata/android/sv/changelogs/980.txt b/fastlane/metadata/android/sv/changelogs/980.txt new file mode 100644 index 000000000..dd81569d7 --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/980.txt @@ -0,0 +1,13 @@ +Nytt +• La till "Lägg till i spellista" alternativ i delningsmenyn +• La till stöd för y2u.be och PeerTube kort länkar + +Förbättrat +• Gjorde uppspelningshastighetskontrollerna mer kompakta +• Flödet markerar nya objekt nu +• "Visa bevakade objekt" alternativet i flödet sparas nu + +Fixat +• Fixade YouTube tumme upp och tumme ner extraktion +• Fixade automatisk uppspelning efter återkomst från bakgrunden +Och mycket mer diff --git a/fastlane/metadata/android/sv/changelogs/981.txt b/fastlane/metadata/android/sv/changelogs/981.txt new file mode 100644 index 000000000..edb8c1779 --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/981.txt @@ -0,0 +1,2 @@ +Tog bort stödet för MediaParser för att åtgärda fel i återupptagningen av uppspelning efter buffring på Android 11+. +Inaktiverade media tunneling på Philips QM16XE för att åtgärda uppspelningsproblem. diff --git a/fastlane/metadata/android/uk/changelogs/930.txt b/fastlane/metadata/android/uk/changelogs/930.txt new file mode 100644 index 000000000..0adf7b847 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/930.txt @@ -0,0 +1,19 @@ +Нове +• Пошук на YouTube Music +• Підтримка Android TV + +Поліпш. +• Можна вилуч. всі переглянуті відео з локальної добірки +• Сповіщення про непідтрим. вміст +• Покращено жести зміни розміру програвача щипанням +• Вилучення трансляцій з черги натиском на тло +• Краща обробка розміру заголовка панелі + +Випр. +• Роботу налаштув. вікового обмеж. вмісту +• Деякі види reCAPTCHA +• Збої під час відкр. закладок, якщо добірка `null` +• Виявлення винятків, пов'язаних з мережею +• Кнопку сорт. груп у підписках + +та інше diff --git a/fastlane/metadata/android/uk/changelogs/951.txt b/fastlane/metadata/android/uk/changelogs/951.txt index fa7c0f526..1cd68b0b8 100644 --- a/fastlane/metadata/android/uk/changelogs/951.txt +++ b/fastlane/metadata/android/uk/changelogs/951.txt @@ -2,8 +2,8 @@ •Дод.пошук для збир.підписок у вікні груп. стрічок •Дод.фільтр до вікна груп.стрічок для показу лише незгруп.підписок •Дод.вкладку добірок на осн.стор. -•Швид.перемот.вперед/назад на тлі/вікні програв.черги -•Відобр.поради пошуку: мали на увазі і показ результ. для +•Швид.перемот.вперед/назад у фоні/вікні програв.черги +•Показ порад пошуку: мали на увазі й показ результ. для Покр. •Вил.запис метадан.програми в зміш.файли •Не вилуч.невдалі потоки з черги diff --git a/fastlane/metadata/android/uk/changelogs/958.txt b/fastlane/metadata/android/uk/changelogs/958.txt index 18b22eedf..8f88562e5 100644 --- a/fastlane/metadata/android/uk/changelogs/958.txt +++ b/fastlane/metadata/android/uk/changelogs/958.txt @@ -7,7 +7,7 @@ • Збої запуску NewPipe після його видалення з оперативної пам’яті • Збої запуску, коли немає з'єднання з інтернетом • Дотримання параметрів яскравості та жестів -• [YouTube] Виправлені довгі списки відтворення +• [YouTube] Виправлені довгі добірки Інше: • Очищення коду та кілька внутрішніх удосконалень diff --git a/fastlane/metadata/android/uk/changelogs/981.txt b/fastlane/metadata/android/uk/changelogs/981.txt new file mode 100644 index 000000000..fb358f995 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/981.txt @@ -0,0 +1,2 @@ +Вилучено підтримку MediaParser, щоб виправити помилку відновлення відтворення після буферизації на Android 11+. +Вимкнено медіатунелювання на Philips QM16XE, щоб розв'язати проблеми відтворення. diff --git a/fastlane/metadata/android/zh-Hans/changelogs/981.txt b/fastlane/metadata/android/zh-Hans/changelogs/981.txt new file mode 100644 index 000000000..be941ae71 --- /dev/null +++ b/fastlane/metadata/android/zh-Hans/changelogs/981.txt @@ -0,0 +1,2 @@ +移除了对MediaParser的支持,以解决在Android 11+上缓冲后恢复播放失败的问题。 +在Philips QM16XE上禁用了媒体隧道,以解决播放问题。 diff --git a/fastlane/metadata/android/zh-Hans/full_description.txt b/fastlane/metadata/android/zh-Hans/full_description.txt index 5382a813b..c168ee934 100644 --- a/fastlane/metadata/android/zh-Hans/full_description.txt +++ b/fastlane/metadata/android/zh-Hans/full_description.txt @@ -1 +1 @@ -Newpipe不使用任何Google框架库组件,或YouTube API。Newpipe仅仅通过解析YouTube网页版来获取所需信息。因此该应用可工作在无GMS服务的设备上。此外,你也不需要任何YouTube账号,Newpipe是自由开源软件(FLOSS)。 +NewPipe 不使用任何 Google 框架库组件,或 YouTube API。NewPipe 仅仅通过解析 YouTube 网页版来获取所需信息。因此该应用可工作在无 Google 服务的设备上。此外,你也不需要 YouTube 账号,NewPipe是自由开源软件(FLOSS)。 diff --git a/fastlane/metadata/android/zh-Hant/changelogs/981.txt b/fastlane/metadata/android/zh-Hant/changelogs/981.txt new file mode 100644 index 000000000..cf0bd8588 --- /dev/null +++ b/fastlane/metadata/android/zh-Hant/changelogs/981.txt @@ -0,0 +1,2 @@ +移除了對MediaParser的支持,以解決在Android 11+上緩衝後恢復播放失敗的問題。 +在Philips QM16XE上禁用了媒體隧道,以解決播放問題。 From 0cf24c5d36be12e104cab06e51bdf4ce24f1ac80 Mon Sep 17 00:00:00 2001 From: zeritti Date: Thu, 6 Jan 2022 15:14:23 +0000 Subject: [PATCH 023/119] Translated using Weblate (Czech) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-cs/strings.xml | 27 +++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 467d40599..f65a350fe 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -123,7 +123,7 @@ Nejlepší rozlišení Vrátit Oznámení NewPipe - Oznámení pro NewPipe přehrávače v pozadí a v okně + Oznámení pro NewPipe přehrávač Žádné výsledky Je tu sranda jak v márnici mld. @@ -164,7 +164,7 @@ Podílet se Historie Historie - Zobrazovat tip \"Podržet pro přidání\" + Zobrazit tip \"Podržet pro vložení do fronty\" Ukázat tip po stisku na pozadí nebo na popup tlačítko v \"Podrobnostech\" o videu Přehrát vše Tento stream nelze přehrát @@ -258,7 +258,7 @@ Vymazat metadata v mezipaměti Odebrat všechna data uložená v mezipaměti Mezipaměť metadat vymazána - Automatická fronta dalšího streamu + Další stream automaticky vložit do fronty Pokračovat konečnou (neopakující se) frontu playbacku připojením souvisejícího streamu Soubor Neexistující složka @@ -275,15 +275,15 @@ Předchozí export Odběry nelze importovat Odběry nelze exportovat - Importovat YouTube odběry stáhnutím exportního souboru: + Importovat YouTube odběry z Google: \n \n1. Přejděte na tuto URL adresu: %1$s \n2. Na vyžádání se přihlašte -\n3. Klikněte na \"Jsou zahrnuta všechna data z YouTube\" pak na \"Zrušit výběr všech\" a pak vyberte jen \"odběry\" a klikněte na OK +\n3. Klikněte na \"Jsou zahrnuta všechna data\", \"Zrušit výběr všech\" a pak vyberte jen \"odběry\" a klikněte na OK \n4. Klikněte na \"Další krok\" a pak na \"Vytvořit export\" \n5. Vyčkejte než se objeví tlačítko \"Stáhnout\" a klikněte na něj \n6. Klikněte IMPORTOVAT SOUBOR a vyberte stažený .zip soubor z předchozího kroku -\n7. [Pokud se import .zip souboru nezdaří] Rozbalte soubor subscriptions.csv (měl by se nacházet v adresáři \"YouTube and YouTube Music/subscriptions/subscriptions.csv\"), stiskněte IMPORTOVAT SOUBOR níže a vyberte rozbalený soubor subscriptions.csv +\n7. [Pokud se import .zip souboru nezdaří] Rozbalte soubor .csv (měl by to být soubor \"YouTube and YouTube Music/subscriptions/subscriptions.csv\"), stiskněte IMPORTOVAT SOUBOR níže a vyberte rozbalený csv soubor Importovat SoundCloud profil zadáním URL adresy nebo vašeho ID: \n \n1. Ve svém prohlížeči povolte \"režim pro PC\" (pro mobilní zařízení není stránka dostupná) @@ -346,7 +346,7 @@ Aktualizace Soubor smazán Oznámení o aktualizaci aplikace - Oznámení o nové verzi NewPipe + Oznámení o nových verzích NewPipe Externí úložiště není k dispozici Nelze načíst uložené karty, takže se použijí výchozí karty Obnovit do výchozího nastavení @@ -687,4 +687,17 @@ Došlo k chybě, více v oznámení Vytvořit oznámení o chybě Kontrola aktualizací… + Ukázat \"Zřícení přehávače\" + Hraje již v pozadí + Nové položky feedů + Pro tuto akci nebyl nalezen žádný vhodný správce souborů. +\nProsím, nainstalujte správce souborů kompatibilní se Storage Access Framework. + Oznámení o hlášení chyb + Oznámení za účelem hlášení chyb + Pro tuto akci nebyl nalezen žádný vhodný správce souborů. +\nProsím, nainstalujte správce souborů nebo zkuste vypnout %s v nastaveních stahování. + Ukáže volbu pro zřícení během používání přehrávače + Ukázat krátké oznámení o chybě + Připnutý komentář + Zřícení přehrávače \ No newline at end of file From d18a34b766ccdeaa3bf3bd979d5bb50d1894c17a Mon Sep 17 00:00:00 2001 From: ToldYouThat Date: Thu, 6 Jan 2022 16:25:52 +0000 Subject: [PATCH 024/119] Translated using Weblate (Turkish) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-tr/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 8433df39f..c96034a9c 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -686,4 +686,6 @@ Hata raporları için bildirimler Oynatıcı kullanırken çöktürme seçeneği gösterir Oynatıcıyı çöktür + Zaten arka planda oynuyor + Sabitlenmiş yorum \ No newline at end of file From 4b0ed9de5d6222b17c036f56ca8e55f5e860a7c7 Mon Sep 17 00:00:00 2001 From: subba raidu Date: Thu, 6 Jan 2022 05:00:49 +0000 Subject: [PATCH 025/119] Translated using Weblate (Telugu) Currently translated at 63.5% (407 of 640 strings) --- app/src/main/res/values-te/strings.xml | 33 ++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml index 47f85a961..5bdecf730 100644 --- a/app/src/main/res/values-te/strings.xml +++ b/app/src/main/res/values-te/strings.xml @@ -377,4 +377,37 @@ ప్లేజాబితాను ఎంచుకోండి ఇప్పటికే వెనుకగా ప్లే అవుతోంది డాటాబేసుని ఎగుమతిచేయుము + యాప్ పునఃప్రారంభించబడిన తర్వాత భాష మారుతుంది + ఛానెల్ వివరాలను చూపు + కంటెంట్‌ని తెరిచేటప్పుడు డిఫాల్ట్ చర్య — %s + ప్రాధాన్య \'తెరవండి\' చర్య + తదుపరి ఎన్క్యూ + తదుపరి క్యూలో ఉంచారు + సమాచారాన్ని పొందుతోంది… + తేలియాడే విధంగా ప్లే చేయడం ప్రారంభించండి + స్థానిక + అభ్యర్థించిన కంటెంట్ లోడ్ అవుతోంది + కొత్త ప్లేజాబితా + పేరు మార్చండి + పేరు + తేలియాడే ప్లేయర్ + ప్రతిసారీ అడుగు + ప్లేజాబితాకు చేర్చు + మూగ + హెచ్చరిక: అన్ని ఫైల్‌లను దిగుమతి చేయడం సాధ్యపడలేదు. + ఇది మీ ప్రస్తుత సెటప్‌ను భర్తీ చేస్తుంది. + మీరు అమరికలను కూడా దిగుమతి చేయాలనుకుంటున్నారా\? + వ్యాఖ్యలను లోడ్ చేయడం సాధ్యపడలేదు + ఇటీవల జోడించినవి + చాలా నచ్చింది + సమావేశాలు + ప్లే క్యూ + ఎన్క్యూ + క్యూలో ఉంచారు + వెనుకగా ప్లే చేయడం ప్రారంభించండి + డ్రాయర్ తెరవండి + డ్రాయర్‌ని మూసివేయండి + చలనచిత్ర ప్లేయర్ + తేలియాడే ప్లేయర్ + ప్రాసెస్ చేస్తోంది... కొంత సమయం పట్టవచ్చు \ No newline at end of file From 864c19e7dc8e1f443ce270ef64d800853e1ede2b Mon Sep 17 00:00:00 2001 From: retiolus Date: Thu, 6 Jan 2022 13:34:34 +0000 Subject: [PATCH 026/119] Translated using Weblate (Catalan) Currently translated at 94.8% (607 of 640 strings) --- app/src/main/res/values-ca/strings.xml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 297cf8043..28c55cd59 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -126,7 +126,7 @@ S\'ha eliminat la memòria cau d\'imatges Elimina les metadades de la memòria cau S\'ha esborrat la memòria cau de metadades - Afegeix vídeos relacionats a la cua + Posa a la cua el següent flux Suggeriments de cerca Mostra suggeriments durant la cerca Historial de cerca @@ -137,7 +137,7 @@ S\'està reproduint en rerefons S\'està reproduint en mode emergent Notificació del NewPipe - Notificacions dels reproductors en rerefons o emergents del NewPipe + Notificacions per al reproductor de NewPipe No s\'han pogut carregar totes les miniatures No s\'ha pogut desxifrar la signatura de l\'URL del vídeo No s\'ha pogut processar el lloc web @@ -270,7 +270,7 @@ Desvincula (pot causar deformació) Elimina totes les dades de llocs web de la memòria cau Acaba de reproduir la cua (sense repetició) quan s\'hi afegeixi un vídeo relacionat - Mostra els missatges d\'ajuda + Mostra l\'indicador «Mantenir per posar a la cua» Mostra un missatge d\'ajuda quan el botó de mode en segon pla o emergent estigui premut a la pàgina de detalls d\'un vídeo Què ha passat:\\nPetició:\\nIdioma del contingut:\\nPaís del contingut:\\nLlengua de l\'aplicació:\\nServei:\\nHora GMT:\\nPaquet:\\nVersió:\\nVersió del SO: Acció d\'obertura preferida @@ -559,7 +559,7 @@ Mostra contingut que podria ser inadequat pels infants Notificació No s\'ha pogut reconèixer l\'adreça URL. Obrir-la amb una altra aplicació\? - Cua automàtica + Posa a la cua automàticament Desactiveu-ho per deixar de mostrar les metadades, que contenen informació addicional sobre el creador del directe, el contingut o una sol·licitud de cerca Mostra les metadades La cua de reproducció activa serà sobreescrita @@ -652,4 +652,7 @@ Inicia el reproductor principal en pantalla completa Llisqueu els elements per eliminar-los Si la rotació automàtica està bloquejada, no inicieu vídeos al mini reproductor, sinó que aneu directament al mode de pantalla completa. Podeu accedir igualment al mini reproductor sortint de pantalla completa + Ja s\'està reproduint en segon pla + Notificació d\'informe d\'error + Tancar abruptament el reproductor \ No newline at end of file From 0d8b7e23e7b716fdf446e852a53f24b95b083685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allan=20Nordh=C3=B8y?= Date: Thu, 13 Jan 2022 13:45:58 +0000 Subject: [PATCH 027/119] Translated using Weblate (English) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5336861b3..f7ad41ba8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -537,7 +537,7 @@ queued post-processing recovering - Queue + Enqueue Action denied by the system Checking for updates… From bef8882a7c84b42c8b777bda72382a963698901f Mon Sep 17 00:00:00 2001 From: translator Date: Sun, 9 Jan 2022 14:34:11 +0000 Subject: [PATCH 028/119] Translated using Weblate (French) Currently translated at 99.2% (635 of 640 strings) --- app/src/main/res/values-fr/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index f27d9b4e7..00ad4b357 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -690,4 +690,6 @@ Montrer une erreur en bas de l\'écran Aucun gestionnaire de fichier approprié n\'a été trouvé pour cette action. \nVeuillez installer un gestionnaire de fichier ou essayez de désactiver \'%s\' dans les paramètres de téléchargement. + Comentaire épinglé + Une lecture est déjà en arrière-plan \ No newline at end of file From ba50de236cab295a74c0c1072c78e3bf45d81a90 Mon Sep 17 00:00:00 2001 From: ssantos Date: Wed, 12 Jan 2022 18:15:42 +0000 Subject: [PATCH 029/119] Translated using Weblate (Portuguese) Currently translated at 99.8% (639 of 640 strings) --- app/src/main/res/values-pt/strings.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index d827a4d12..bae06cc0f 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -664,7 +664,7 @@ %s descargas concluídas Deslizar itens para removê-los - Não iniciar vídeos no reprodutor mini, mas ir diretamente para ecrã completo se a rotação automática estiver bloqueada. Ainda pode aceder o reprodutor mini se sair do modo de ecrã completo. + Não iniciar vídeos no reprodutor mini, mas ir diretamente ao ecrã completo se a rotação automática estiver bloqueada. Ainda pode aceder o reprodutor mini se sair do modo de ecrã completo Iniciar reprodutor principal em ecrã completo Enfileirado o próximo Enfileirar o próximo @@ -688,4 +688,6 @@ \nPor favor, instale um gestor de ficheiros ou tente desativar \'%s\' nas configurações de descarregar. Nenhum gestor de ficheiros apropriado foi encontrado para esta ação. \nPor favor, instale um gestor de ficheiros compatível com o Storage Access Framework. + Já está a reproduzir em segundo plano + Comentário fixado \ No newline at end of file From 6c1222ea32ddebd0125e6bb686c987022cdde5e2 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 12 Jan 2022 04:17:44 +0000 Subject: [PATCH 030/119] Translated using Weblate (Romanian) Currently translated at 96.4% (617 of 640 strings) --- app/src/main/res/values-ro/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 7def09d68..7f24b073d 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -681,4 +681,8 @@ Afișați indicatorii de imagine Dezactivați tunelarea media dacă întâmpinați un ecran negru sau blocaje la redarea video Procesarea.. Poate dura un moment + Verifică dacă există actualizări + Verifică manual dacă există versiuni noi + Se redă deja pe fundal + Comentariu lipit \ No newline at end of file From 2f21523da9b81178972165248522702221840dd8 Mon Sep 17 00:00:00 2001 From: Mohammed Anas <6daf084a-8eaf-40fb-86c7-8500077c3b69@anonaddy.me> Date: Sun, 9 Jan 2022 17:39:42 +0000 Subject: [PATCH 031/119] Translated using Weblate (Arabic) Currently translated at 99.6% (638 of 640 strings) --- app/src/main/res/values-ar/strings.xml | 60 +++++++++++++------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index d996feeb5..007d4dc7a 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -107,7 +107,7 @@ استرداد المشغل من الخطأ عذرًا، لم ينبغِ أن يحدث ذلك. الإبلاغ عن هذا الخطأ عبر البريد الإلكتروني - عذرا، حدث خطأ ما. + عذرًا، حدث خطأ ما. أبلِغ معلومات: ماذا حدث: @@ -157,7 +157,7 @@ التراخيص تطبيق مجاني خفيف البث على أندرويد. ساهم - إذا كانت لديك أفكار؛ أو ترجمة، أو تغييرات تخص التصميم، أو تنظيف و تحسين الشفرة البرمجية ، أو تعديلات عميقة عليها، فتذكر أنّ مساعدتك دائما موضع ترحيب. وكلما أتممنا شيئا كلما كان ذلك أفضل ! + إذا كانت لديك أفكار؛ أو ترجمة، أو تغييرات تخص التصميم، أو تنظيف و تحسين الشفرة البرمجية، أو تعديلات عميقة عليها، فتذكر أنّ مساعدتك دائما موضع ترحيب. وكلما أتممنا شيئا كلما كان ذلك أفضل! عرض على GitHub تبرع يتم تطوير NewPipe من قبل متطوعين يقضون وقت فراغهم لتقديم أفضل تجربة لك. حان الوقت لرد المساعدة مع المطورين وجعل NewPipe أكثر و أفضل بينما يستمتعون بفنجان من القهوة. @@ -290,7 +290,7 @@ لا يوجد بث متاح للتنزيل تم حذف عنصر واحد. لم يتم تثبيت أي تطبيق لتشغيل هذا الملف - NewPipe هو برنامج مفتوح المصدر و بحقوق متروكة: يمكنك استخدام الكود ودراسته وتحسينه كما شئت. و على وجه التحديد يمكنك إعادة توزيعه / أو تعديله تحت شروط رخصة GNU العمومية والتي نشرتها مؤسسة البرمجيات الحرة، سواء الإصدار 3 من الرخصة، أو (باختيارك) أي إصدار جديد. + NewPipe هو برنامج مفتوح المصدر وبحقوق متروكة: يمكنك استخدام الكود ودراسته وتحسينه كما شئت. وعلى وجه التحديد يمكنك إعادة توزيعه / أو تعديله تحت شروط رخصة GNU العمومية والتي نشرتها مؤسسة البرمجيات الحرة، سواء الإصدار 3 من الرخصة، أو (باختيارك) أي إصدار جديد. آخر ما تم تشغيله الأكثر تشغيلا هذا سوف يُزيل إعداداتك الحالية. @@ -325,10 +325,10 @@ إلغاء الإرتباط (قد يسبب تشويه) هل تريد أيضا استيراد الإعدادات؟ سياسة خصوصية NewPipe - يأخذ مشروع NewPipe خصوصيتك على محمل الجد. لذلك ، لا يجمع التطبيق أي بيانات دون موافقتك. + يأخذ مشروع NewPipe خصوصيتك على محمل الجد. لذلك، لا يجمع التطبيق أي بيانات دون موافقتك. \nتوضح سياسة خصوصية NewPipe بالتفصيل البيانات التي يتم إرسالها وتخزينها عند إرسال تقرير الأعطال. الإطلاع على سياسة الخصوصية - من أجل الامتثال للائحة الأوروبية العامة لحماية البيانات (GDPR) ، فإننا نلفت انتباهك إلى سياسة خصوصية NewPipe. يرجى قراءتها بعناية. + من أجل الامتثال للائحة الأوروبية العامة لحماية البيانات (GDPR)، فإننا نلفت انتباهك إلى سياسة خصوصية NewPipe. يرجى قراءتها بعناية. \nو يجب عليك قبولها لإرسال تقرير الأخطاء إلينا. قبول رفض @@ -433,7 +433,7 @@ حذف مواقف التشغيل حذف كل مواقف التشغيل حذف كل مواقف التشغيل؟ - تبديل الخدمة ، المحدد حاليًا: + تبديل الخدمة، المحدد حاليًا: الكشك الافتراضي لا توجد مشاهدة لا أحد يستمع @@ -480,21 +480,21 @@ الفيديوهات %d ثانية - %d ثواني - %d ثواني + %d ثانية + %d ثانية %d ثواني - %d ثواني - %d ثواني + %d ثانية + %d ثانية - هل تعتقد تحميل تغذية بطيء جدا؟ إذا كان الأمر كذلك ، فحاول تمكين التحميل السريع (يمكنك تغييره في الإعدادات أو بالضغط على الزر أدناه). + هل تعتقد تحميل التغذية بطيء جدا؟ إذا كان الأمر كذلك، فحاول تمكين التحميل السريع (يمكنك تغييره في الإعدادات أو بالضغط على الزر أدناه). \n \nيقدم NewPipe استراتيجيتين لتحميل الخلاصة: -\n• جلب قناة الاشتراك بأكملها ، وهي بطيئة ولكنها كاملة. -\n• استخدام نقطة نهاية خدمة مخصصة ، وهي سريعة ولكنها عادة لا تكتمل. +\n• جلب قناة الاشتراك بأكملها، وهي بطيئة ولكنها كاملة. +\n• استخدام نقطة نهاية خدمة مخصصة، وهي سريعة ولكنها عادة لا تكتمل. \n -\nالفرق بين الاثنين هو أن العنصر السريع عادة ما يفتقر إلى بعض المعلومات ، مثل مدة العنصر أو نوعه (لا يمكن التمييز بين مقاطع الفيديو المباشرة والأخرى العادية) وقد يعيد عناصر أقل. +\nالفرق بين الاثنين هو أن العنصر السريع عادة ما يفتقر إلى بعض المعلومات، مثل مدة العنصر أو نوعه (لا يمكن التمييز بين مقاطع الفيديو المباشرة والأخرى العادية) وقد يعيد عناصر أقل. \n -\n يوتيوب هو مثال على الخدمة التي تقدمها هذه طريقة سريعة مع تغذية RSS الخاصة بها. +\nيوتيوب هو مثال على الخدمة التي تقدمها هذه طريقة سريعة مع تغذية RSS الخاصة بها. \n \nلذا فإن الاختيار يتلخص في ما تفضله: السرعة أو المعلومات الدقيقة. تعطيل الوضع السريع @@ -533,19 +533,19 @@ %d ساعة - %d ساعات - %d ساعات + %d ساع + %d ساعة %d ساعات - %d ساعات - %d ساعات + %d ساعة + %d ساعة %d دقيقة - %d الدقائق - %d الدقائق - %d الدقائق - %d الدقائق - %d الدقائق + %d دقيقة + %d دقيقة + %d دقائق + %d دقيقة + %d دقيقة نظرا لقيود مشغل ExoPlayer مدة التقديم تم ضبطها الى %d ثانية إلغاء كتم الصوت @@ -594,7 +594,7 @@ لا شيء جارٍ التحميل خلط - كرّر + تكرار يمكنك تحديد ثلاثة إجراءات كحد أقصى لإظهارها في الإشعار المضغوط! قم بتحرير كل إشعار أدناه من خلال النقر عليه. حدد ما يصل إلى ثلاثة منها لتظهر في الإشعار المضغوط باستخدام مربعات الاختيار الموجودة على اليمين زر الإجراء الخامس @@ -631,9 +631,9 @@ إظهار الوصف فتح مع يتوفر هذا المحتوى فقط للمستخدمين الذين قاموا بالدفع، لذلك لا يمكن بثه أو تنزيله عبر NewPipe. - يتوفر هذا الفيديو فقط لأعضاء YouTube Music Premium ، لذلك لا يمكن بثه أو تنزيله من قبل NewPipe. + يتوفر هذا الفيديو فقط لأعضاء YouTube Music Premium، لذلك لا يمكن بثه أو تنزيله من قبل NewPipe. هذا المحتوى خاص، لذلك لا يمكن دفقه أو تنزيله بواسطة NewPipe. - هذا هو مسار SoundCloud Go+ ، على الأقل في بلدك ، لذلك لا يمكن بثها أو تنزيلها من قبل NewPipe. + هذا هو مسار SoundCloud Go+، على الأقل في بلدك، لذلك لا يمكن بثها أو تنزيلها من قبل NewPipe. هذا المحتوى غير متوفر في بلدك. اغلق التطبيق قسريا هذا الفيديو مقيد بالفئة العمرية. @@ -674,10 +674,10 @@ \nهل تريد إلغاء الاشتراك من هذه القناة؟ تعذر تحميل تغذية ل \'%s\'. خطأ في تحميل الخلاصة - بدءًا من Android 10 ، يتم دعم \"Storage Access Framework\" فقط + بدءًا من Android 10، يتم دعم \"Storage Access Framework\" فقط لا يتم دعم \"Storage Access Framework\" على Android KitKat والإصدارات الأقدم سيتم سؤالك عن مكان حفظ كل تنزيل - لم يتم تعيين مجلد التحميل ، الرجاء اختيار مجلد التحميل الافتراضي الآن + لم يتم تعيين مجلد التحميل، الرجاء اختيار مجلد التحميل الافتراضي الآن إيقاف تشغيل وضع الجهاز اللوحي @@ -729,7 +729,7 @@ إشعار الإبلاغ عن الأخطاء التنبيهات المتعلقة بالإبلاغ عن الأخطاء واجه NewPipe خطأ، اضغط للتقرير - حدث خطأ ، انظر للإشعار + حدث خطأ، انظر للإشعار قم بإنشاء تنبيه بالخطأ لم يتم العثور على مدير ملفات مناسب لهذا الإجراء. \nالرجاء تثبيت مدير ملفات أو محاولة تعطيل \"%s\" في إعدادات التنزيل. From 4206ae84c1f425e40bb7cf3897f97054d236b014 Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Thu, 13 Jan 2022 15:47:15 +0000 Subject: [PATCH 032/119] Translated using Weblate (Ukrainian) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-uk/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index c00cbd017..238e07fef 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -370,7 +370,7 @@ призупинено додано в чергу пост-обробка - Черга + Додати у чергу Дію заборонено системою Помилка завантаження Згенерувати унікальну назву @@ -596,8 +596,8 @@ Рекомендовані Збій застосунку Початковий час оприлюднення - Додано в чергу - Додати в чергу + Додано у чергу + Додати у чергу Розв\'язати Обчислення гешу Очистити збережені під час вирішення reCAPTCHA реп\'яшки (cookies) From 96ab2f855e05ace205b760189df1bd1966ec6b94 Mon Sep 17 00:00:00 2001 From: Karl Tammik Date: Sat, 8 Jan 2022 16:02:06 +0000 Subject: [PATCH 033/119] Translated using Weblate (Estonian) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-et/strings.xml | 27 ++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index e75443607..cea43d7ef 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -103,7 +103,7 @@ Üks kord Fail NewPipe teavitus - Teavitused NewPipe tausta- ja hüpikpleierile + Teavitused NewPipe pleierile [Tundmatu] Lülita taustale Lülita hüpikpleierile @@ -287,8 +287,8 @@ \n3. Klõpsa \"Kõigi andmetega\", vali \"Tühista kõik\", vali ainult \"Tellimused\" ja klõpsa \"OK\". \n4. Klõpsa \"Järgmine samm\" ja seejärel \"Loo eksport\". \n5. Klõpsa nupul \"Laadi alla\" siis, kui ta ilmub. -\n6. Klõpsi siitsamast \"Impordi fail\" linki ning vali allalaaditud zip fail. -\n7. Kui zip faili importimine ei toimi, siis paki .csv fail lahti (tavaliselt on see fail \"YouTube ja YouTube Muusika/tellimused/tellimused\" või \"YouTube and YouTube Music/subscriptions/subscriptions\") ja klõpsi siitsamast \"Impordi fail\" linki ning vali lahtipakitud csv fail. +\n6. Klõpsi siitsamast \"Impordi fail\" linki ning vali allalaaditud .zip fail. +\n7. Kui .zip faili importimine ei toimi, siis paki .csv fail lahti (tavaliselt on see fail \"YouTube ja YouTube Muusika/tellimused/tellimused\" või \"YouTube and YouTube Music/subscriptions/subscriptions\") ja klõpsi siitsamast \"Impordi fail\" linki ning vali lahtipakitud csv fail. See toiming võib põhjustada suurt võrguliiklust. \n \nKas jätkata? @@ -316,7 +316,7 @@ Teavita elutsüklist väljas vigadest Impordi SoundCloudi profiil trükkides URL või oma ID: \n -\n1. Luba \"töölaua režiim\" veebilehitsejas (lmobiilsete seadmete jaoks leht pole kättesaadav) +\n1. Luba \"töölaua režiim\" veebilehitsejas (mobiilsete seadmete jaoks leht pole kättesaadav) \n2. Ava URL: %1$s \n3. Logi sisse \n4. Kopeeri suunatud profiili URL. @@ -343,8 +343,8 @@ Uuendused Sündmused Fail kustutati - Rakenduse värskenduse teatis - NewPipe uuest versioonist teavitamine + Rakenduse värskenduse teavitus + Teavitus NewPipe uuetest versioonidest Väline andmekandja pole saadaval Allalaadimine välisele SD-kaardile ei ole võimalik. Kas lähtestada allalaadimiste kataloogi asukoht\? Tõrge salvestatud vahekaaride lugemisel; kasutatakse vaikeväärtusi @@ -673,4 +673,19 @@ Kontrolli uuendusi Kontrolli uuendusi käsitsi Uued andmevoo kirjed + Näita „jooksuta meediamängija kokku“ nupukest + Näitab valikut meediamängija kokkujooksutamiseks + NewPipe töös tekkis viga, sellest teavitamiseks klõpsi + Jooksuta meediamängija kokku + Näita veateate akent + Meedia esitamine taustal toimib juba + Teavitus vigadest + Teavitused vigadest informeerimiseks + Tekkis viga, vaata vastavat teadet + Koosta veateade + Selle tegevuse jaoks ei leidunud sobilikku failihaldurit. +\nPalun paigalda nutiseadmesse failihaldur või proovi allalaadimiste seadistustest „%s“ välja lülitada. + Selle tegevuse jaoks ei leidunud sobilikku failihaldurit. +\nPalun paigalda nutiseadmesse failihaldur, mis järgib Storage Access Framework reeglistikku. + Esiletõstetud kommentaar \ No newline at end of file From 80be089ca9946416912af09fb4f3ad496b94aaf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Thu, 13 Jan 2022 21:53:55 +0000 Subject: [PATCH 034/119] Translated using Weblate (Estonian) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-et/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index cea43d7ef..e7f75ea09 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -366,7 +366,7 @@ peatatud järjekorras järeltöötlus - Esitusjärjekord + Lisa esitusjärjekorda Tegevus keelati süsteemi poolt Allalaadimine nurjus Loo kordumatu nimi From 85950780539e111d9fed12b5209f7769eb093f0f Mon Sep 17 00:00:00 2001 From: Mikkel Date: Tue, 11 Jan 2022 19:31:16 +0000 Subject: [PATCH 035/119] Translated using Weblate (Danish) Currently translated at 51.2% (328 of 640 strings) --- app/src/main/res/values-da/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 7e75ca57b..23abdc2da 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -1,8 +1,8 @@ - Tryk søg for at komme i gang + Tryk på forstørrelsesglasset for at komme i gang. Udgivet %1$s - Ingen streamafspiller blev fundet. Vil du installere VLC\? + Ingen streamafspiller blev fundet. Installer VLC\? Ingen streamafspiller fundet (du kan installere VLC for at afspille den). Installer Annuller From fdfdf94cb9a0ef4e5d4eb87bcf314ac7e8a34d01 Mon Sep 17 00:00:00 2001 From: MohammedSR Vevo Date: Sun, 9 Jan 2022 22:55:40 +0000 Subject: [PATCH 036/119] Translated using Weblate (Kurdish (Central)) Currently translated at 99.2% (635 of 640 strings) --- app/src/main/res/values-ckb/strings.xml | 42 ++++++++++++++++--------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/app/src/main/res/values-ckb/strings.xml b/app/src/main/res/values-ckb/strings.xml index d602ea8d9..36de64297 100644 --- a/app/src/main/res/values-ckb/strings.xml +++ b/app/src/main/res/values-ckb/strings.xml @@ -45,7 +45,7 @@ سڕینەوەی مێژووی گەڕان هەڵە ئەمە لەسەر ڕێکخستنەکانی ئێستات جێگیر دەبێت. - ئاگانامەکانی نیوپایپ + پەیامەکانی نیوپایپ نیوپایپ لەلایەن چەند خۆبەخشێکەوە دروستکراوە کە کاته‌كانی خۆیان پێ بەخشیووە تاکو باشترین خزمەتگوزاریت پێشکەش بکەن. هیچ نەبێت بە کڕینی کوپێک قاوە یارمەتی گەشەپێدەرەکانمان بدە بۆ ئەوەی کاتی زیاتر تەرخان بکەین بۆ بەرەوپێشبردنی نیوپایپ. ملیار گەڕانی پێشنیارکراوەکان @@ -237,9 +237,9 @@ كردنه‌وه‌ له‌ وێبگه‌ر ڕاژەکە هیچ داتایەک نانێرێت شوێنی کارپێکراوەکان سڕانەوە - ئاگانامەکانی وەشانی نوێی نیوپایپ + پەیامەکانی وەشانە نوێیەکانی نیوپایپ تەنها چەند مۆبایلێک پشتگیری لێدانی ڤیدیۆی 2K/4K دەکەن - ئاگانامەکانی پاشبنەمای نیوپایپ و لێدانه‌كانی پەنجەرە + پەیامەکانی لێدەری نیوپایپ لەهەندێ خزمەتگوزاریدا بەردەستە، بەزۆری خێراترینە بەڵام ڕەنگە هەندێک لە بابەتەکان زانیارییەکانیان ناتەواو بێت (وەک نەبوونی ماوە، جۆری بابەت ، نەبوونی پەخش) %d چرکە @@ -275,7 +275,7 @@ هیچ پەخشێکی ڤیدیۆیی نەدۆزرایەوە هاوردە لە كرتە بکە لەسەر ”كرا” کاتێك کە چارەسەرکرا - ئاگانامەی نوێکاری بەرنامە + پەیامی نوێکردنەوەی بەرنامە ناتوانرێت هەموو وێنۆچکەکان باربکرێن هەناردەی پێشووتر فایلی ZIP دروست نییە @@ -394,7 +394,7 @@ نیشانه‌كردنی خشته‌لێدان ناوی فایل ناکرێت بەتاڵ بێت ناتوانرێت واژووی بەستەری ڤیدیۆ بخوێنرێتەوە - پیشاندانی ئاگانامەیەک بۆ ئامادەبوونی به‌رنامه‌ لەکاتی بەردەست بوونی وەشانی نوێ + پیشاندانی پەیامێک بۆ ئامادەبوونی به‌رنامه‌ لەکاتی بەردەست بوونی وەشانی نوێ مێژووی سەیرکردن سکاڵا لەسەر کێشەکان خۆکار-دانراو (هیچ بەرزکەرەوەیەک نەدۆزرایەوە) @@ -542,7 +542,7 @@ تكایه‌ پشكنینێك بكه‌ كه‌ ئاخۆ كێشه‌یه‌ك هه‌یه‌ باسی كڕاشه‌كه‌ت بكات. له‌كاتی سازدانی پلیتی لێكچوو ، كات له‌ ئێمه‌ ده‌گریت كه‌ ئێمه‌ سه‌رقاڵی چاره‌سه‌ركردنی هه‌مان كێشه‌ ده‌كه‌یت. سكاڵا لەسەر GitHub له‌به‌رگرتنه‌وه‌ی سكاڵای جۆركراو - ئاگانامە + پەیام ناتوانرێت به‌سته‌ره‌كه‌ بناسرێتەوە. بە بەرنامەیەکی دیكه‌ بکرێتەوە؟ خستنه‌ نۆبه‌تی-خۆكاری نۆبه‌ته‌كه‌ لە لێدەری چالاکەوە جێگۆڕکێی دەکرێت @@ -552,14 +552,14 @@ نێوانگری تێکەڵکردن دووبارە - دەتوانیت تا سێ كردار دیار بكه‌یت تا پیشان بدرێن له‌ ئاگانامه‌كه‌دا! - ده‌ستكاری هه‌ر یه‌كێك له‌م كردارانه‌ی خواره‌وه‌ بكه‌ له‌ڕێگه‌ی كرته‌ له‌سه‌ریان. ده‌توانیت تا زیاتر له‌ سێ دانه‌یان هه‌ڵبژێریت له‌ ڕێگای چوارگۆشه‌كانی لای ڕاسته‌وه‌یان، تا پیشان بدرێن له‌ ئاگانامه‌كاندا + دەتوانیت تا سێ كردار دیار بكه‌یت تا پیشان بدرێن له‌ پەیامەکەدا! + ده‌ستكاری هه‌ر یه‌كێك له‌م كردارانه‌ی خواره‌وه‌ بكه‌ له‌ڕێگه‌ی كرته‌ له‌سه‌ریان. ده‌توانیت تا زیاتر له‌ سێ دانه‌یان هه‌ڵبژێریت له‌ ڕێگای چوارگۆشه‌كانی لای ڕاسته‌وه‌یان، تا پیشان بدرێن له‌ پەیامەکاندا پێنجه‌م كرداری دوگمه‌ چواره‌م كرداری دوگمه‌ سێیه‌م كرداری دوگمه‌ دووه‌م كرداری دوگمه‌ یه‌كه‌م كرداری دوگمه‌ - وێنۆچكه‌ی ڤیدیۆ پێوانه‌ ده‌كرێته‌وه‌ له‌ ئاگانامه‌كاندا له‌ ڕه‌هه‌ندی 16:9 ه‌وه‌ بۆ ڕه‌هه‌ندی 1:1 + وێنۆچكه‌ی ڤیدیۆ پێوانه‌ ده‌كرێته‌وه‌ له‌ پەیامەکاندا له‌ ڕه‌هه‌ندی 16:9 ه‌وه‌ بۆ ڕه‌هه‌ندی 1:1 پێوانەكردنی وێنۆچكه‌ بۆ ڕه‌هه‌ندی 1:1 پیشاندانی ئەنجامەکانی: %s كردنه‌وه‌ له‌ @@ -568,8 +568,8 @@ ناكارایبكه‌ بۆ شاردنه‌وه‌ی دیسکریپشن له‌سه‌ر ڤیدیۆ و زانیاری زیاتر پیشاندانی دیسکریپشن ڕووكاری شه‌و - ئه‌ندرۆید ڕه‌نگی ئاگانامه‌ دڵخواز ده‌كات به‌پێی ڕه‌نگی سه‌ره‌كی وێنۆچكه‌كه‌ ( ڕه‌چاوی ئه‌وه‌ بكه‌ كه‌ ئه‌م تایبه‌تمه‌ندییه‌ هه‌موو ئامێرێك ناگرێته‌وه‌ ) - ڕه‌نگكردنی ئاگانامه‌ + ئه‌ندرۆید ڕه‌نگی پەیام دڵخواز ده‌كات به‌پێی ڕه‌نگی سه‌ره‌كی وێنۆچكه‌كه‌ ( ڕه‌چاوی ئه‌وه‌ بكه‌ كه‌ ئه‌م تایبه‌تمه‌ندییه‌ هه‌موو ئامێرێك ناگرێته‌وه‌ ) + ڕه‌نگكردنی پەیام یوتوب ”دۆخی قه‌ده‌غه‌كراو” پێشكه‌ش ده‌كات كه‌ بابەتە نه‌شیاوه‌كان ده‌شارێته‌وه‌ ئه‌ژماركردنی هاش لێدوانه‌كان ناكاراكراون @@ -581,8 +581,8 @@ خاوێنكردنه‌وی ئه‌و شه‌كرۆكانه‌ی كه‌ له‌ نیوپایپ كۆگاكراون ، ئه‌مه‌ش له‌دوای شیكار كردنی reCAPTCHA شه‌كرۆكه‌كانی reCAPTCHA خاوێنكرانه‌وه‌ سڕینه‌وه‌ی شه‌كرۆكه‌كانی reCAPTCHA - ئاگانامه‌كانی ئه‌نجامدانی هاشكردنی ڤیدیۆ - ئاگانامه‌ی هاشی ڤیدیۆ + پەیامەکانی ئه‌نجامدانی هاش كردنی ڤیدیۆ + پەیامی هاش ڤیدیۆ ناکاراکردنی دیار کردنی نوسینی نێو دیسکریبشن کاراکردنی دیار کردنی نوسینی نێو دیسکریبشن لە ئێستادا دەتوانیت نوسینی نێو دیسکریپشن دیار بکەیت. بەڵام ڕەچاوی ئەوە بکە کە ئەو پەڕەیە ڕەنگە تێکبچێت و لینکەکان کرتەیان لەسەر نەکرێت لە دۆخی دیار کردندا. @@ -621,7 +621,7 @@ هیچ به‌رنامه‌یه‌كی نێو مۆبایله‌كه‌ت ناتوانێت ئه‌مه‌ بكاته‌وه‌ به‌شه‌كان دواین - وێنۆچكه‌كه‌ بۆ پاشبنه‌مای ڕوونماداخراو و ئاگانامه‌كان به‌كاربهێنرێن + وێنۆچكه‌كه‌ بۆ پاشبنه‌مای ڕوونماداخراو و پەیامەکان به‌كاردەهێنرێن پیشاندانی وێنۆچكه‌ تەماشاکراوەکان پیشان بدرێن بۆ دابه‌زاندنی هه‌ر بابه‌تێك پرست پێ ده‌كرێت له‌باره‌ی شوێنی دابه‌زاندنیان @@ -668,4 +668,18 @@ لە نۆبەت دانان بۆ دواتر لە نۆبەت دانرا بۆ دواتر جێبەجێ دەکرێت... ڕەنگە ساتێک بخایەنێت + دەپشکنرێت بۆ نوێکردنەوە… + پشکنینی خۆیی بۆ وەشانی نوێ + بژاردەی کڕاش کردن پیشان دەدات لەکاتی بەکارهێنانی لێدەرەکە + کێشەیەک ڕوویدا ، پەیامەکە ببینە + نیوپایپ تووشی کێشەیەک بوو ، کرتە بکە بۆ سکاڵاکردن + پیشاندانی ”کڕاش کردنی لێدەرەکە“ + سازاندنی پەیامی کێشەیەک + پشکنین بۆ نوێکردنەوە + وا لە پاشبنەمادا لێدەدرێت + کێشە لە سکاڵا کردنی پەیام + پەیامەکانی سکاڵاکردن لە کێشەکان + بابەتە نوێیەکانی فیید + لێدوانی هەڵواسراو + کڕاش کردنی لێدەر \ No newline at end of file From 0f74c2463ee9fe12a86c5a681e5cb078aff4c1fc Mon Sep 17 00:00:00 2001 From: ssantos Date: Tue, 11 Jan 2022 15:02:02 +0000 Subject: [PATCH 037/119] Translated using Weblate (Portuguese (Portugal)) Currently translated at 99.8% (639 of 640 strings) --- app/src/main/res/values-pt-rPT/strings.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index b66cc6a08..21acd0519 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -664,7 +664,7 @@ %s descargas concluídas Deslizar itens para removê-los - Não iniciar vídeos no reprodutor mini, mas ir diretamente para ecrã completo se a rotação automática estiver bloqueada. Ainda pode aceder o reprodutor mini se sair do modo de ecrã completo. + Não iniciar vídeos no reprodutor mini, mas ir diretamente ao ecrã completo se a rotação automática estiver bloqueada. Ainda pode aceder o reprodutor mini se sair do modo de ecrã completo Iniciar reprodutor principal em ecrã completo Enfileirado o próximo Enfileirar o próximo @@ -688,4 +688,6 @@ \nPor favor, instale um gestor de ficheiros ou tente desativar \'%s\' nas configurações de descarregar. Nenhum gestor de ficheiros apropriado foi encontrado para esta ação. \nPor favor, instale um gestor de ficheiros compatível com o Storage Access Framework. + Comentário fixado + Já está a reproduzir em segundo plano \ No newline at end of file From b5662c2d07a9f5b29e7e4adcd90483adff6ab28b Mon Sep 17 00:00:00 2001 From: TiA4f8R Date: Sat, 15 Jan 2022 13:00:20 +0000 Subject: [PATCH 038/119] Translated using Weblate (French) Currently translated at 99.2% (635 of 640 strings) --- app/src/main/res/values-fr/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 00ad4b357..7d9c3435c 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -689,7 +689,7 @@ \nVeuillez installer un gestionnaire de fichiers compatible avec l\'Infrastructure d\'accès au stockage. Montrer une erreur en bas de l\'écran Aucun gestionnaire de fichier approprié n\'a été trouvé pour cette action. -\nVeuillez installer un gestionnaire de fichier ou essayez de désactiver \'%s\' dans les paramètres de téléchargement. - Comentaire épinglé +\nVeuillez installer un gestionnaire de fichiers ou essayez de désactiver \'%s\' dans les paramètres de téléchargement. + Commentaire épinglé Une lecture est déjà en arrière-plan \ No newline at end of file From 6632720bc3bdbf5bc69560865f90e82328838323 Mon Sep 17 00:00:00 2001 From: mm4c Date: Sat, 15 Jan 2022 11:47:52 +0000 Subject: [PATCH 039/119] Translated using Weblate (Dutch) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-nl/strings.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index b85d48476..365e251aa 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -66,7 +66,7 @@ Downloads Foutrapport App/UI gecrasht - Wat:\\nVerzoek:\\nTaal van inhoud:\\nTaal van land:\\nTaal van Applicatie:\\nDienst:\\nGMT-tijd:\\nPakket:\\nVersie:\\nVersie van besturingssysteem: + Wat:\\nVerzoek:\\nTaal van inhoud:\\nTaal van land:\\nTaal van Toepassing:\\nDienst:\\nGMT-tijd:\\nPakket:\\nVersie:\\nVersie van besturingssysteem: Begin Pauzeren Verwijderen @@ -292,7 +292,7 @@ Alle gecachete webpagina-gegevens wissen Metagegevens-cache gewist Afspeelsnelheidbesturing - Tempo + Snelheid Toon Ontlinken (kan ruis veroorzaken) Voorkeursactie voor openen @@ -340,7 +340,7 @@ Gebruik gebaren om het volume van de speler aan te passen Gebaarbesturing voor helderheid Gebruik gebaren om de helderheid van de speler aan te passen - Updates + Bijwerken Bestand verwijderd App update melding Meldingen voor nieuwe New Pipe versies @@ -351,7 +351,7 @@ Wil je de standaardinstellingen herstellen\? Aantal abonnees niet beschikbaar Welke tabbladen worden weergegeven op de hoofdpagina - Updates + Bijwerken Toon een melding om de applicatie te updaten wanneer er een nieuwe versie beschikbaar is Lijstweergavemodus Lijst From 89c540c520d05df200dcb772d18af6e4ebd892f3 Mon Sep 17 00:00:00 2001 From: S3aBreeze Date: Fri, 14 Jan 2022 03:26:29 +0000 Subject: [PATCH 040/119] Translated using Weblate (Russian) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-ru/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index a2da5e1d6..71c96bd89 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -371,7 +371,7 @@ Завершено приостановлено в очереди - Очередь + Добавить в очередь Действие запрещено системой Ошибка загрузки Перезаписать From 15e6f1cb3b9638fbc55c45313c23424e7182a793 Mon Sep 17 00:00:00 2001 From: ssantos Date: Fri, 14 Jan 2022 22:41:08 +0000 Subject: [PATCH 041/119] Translated using Weblate (Portuguese) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-pt/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index bae06cc0f..f45c852eb 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -363,7 +363,7 @@ em pausa na fila pós-processamento - Fila + Enfileirar Ação recusada pelo sistema Falha ao descarregar Gerar nome único From a3e68c93f8bf7c3588c4be1ed45bfab45073d5d0 Mon Sep 17 00:00:00 2001 From: Sergio Varela Date: Fri, 14 Jan 2022 22:32:21 +0000 Subject: [PATCH 042/119] Translated using Weblate (Basque) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-eu/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 5d2fe379a..88b8d90f9 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -366,7 +366,7 @@ pausatuta ilaran post-prozesua - Gehitu ilarara + Enkargatu Ekintza sistemak ukatu du Deskargak huts egin du Sortu izen bakana From 3bc2ec90ef9cb8a8da7b9564e8a0ba50f77c0782 Mon Sep 17 00:00:00 2001 From: Vasilis K Date: Fri, 14 Jan 2022 09:54:14 +0000 Subject: [PATCH 043/119] Translated using Weblate (Greek) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-el/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index b8a3277c5..2706da83d 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -366,7 +366,7 @@ σε παύση σε ουρά σε μετεπεξεργασία - Ουρά + Προσθήκη σε ουρά Η ενέργεια απορρίφθηκε από το σύστημα Η λήψη απέτυχε Δημιουργία μοναδικού ονόματος From afef793fbb7da9e021fe53b27b3093548d071ddf Mon Sep 17 00:00:00 2001 From: Soare Robert Daniel Date: Mon, 17 Jan 2022 20:27:50 +0000 Subject: [PATCH 044/119] Translated using Weblate (Romanian) Currently translated at 97.9% (627 of 640 strings) --- app/src/main/res/values-ro/strings.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 7f24b073d..802b2ab69 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -685,4 +685,14 @@ Verifică manual dacă există versiuni noi Se redă deja pe fundal Comentariu lipit + Notificare cu raport de eroare + Afișează opțiunea de a întrerupe atunci când utilizați playerul + A apărut o eroare, verifică notificarea + NewPipe a întămpinat o eroare, apăsați ca să raportați + Se verifică actualizări… + Notificări pentru a raporta erori + Crează o notificare de eroare + Arată \"închiderea bruscă a player-ului video\" + Arată o eroare de tip snackbar + Elemente de flux noi \ No newline at end of file From 31635c122e7022a9406706933cca3efd54533a8a Mon Sep 17 00:00:00 2001 From: Rex_sa Date: Fri, 14 Jan 2022 08:32:40 +0000 Subject: [PATCH 045/119] Translated using Weblate (Arabic) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-ar/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 007d4dc7a..d9107d03f 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -378,7 +378,7 @@ متوقف في قائمة الانتظار قيد المعالجة - طابور + قائمة الانتظار تم رفضها من قبل النظام فشل التنزيل إنشاء اسم فريد @@ -633,7 +633,7 @@ يتوفر هذا المحتوى فقط للمستخدمين الذين قاموا بالدفع، لذلك لا يمكن بثه أو تنزيله عبر NewPipe. يتوفر هذا الفيديو فقط لأعضاء YouTube Music Premium، لذلك لا يمكن بثه أو تنزيله من قبل NewPipe. هذا المحتوى خاص، لذلك لا يمكن دفقه أو تنزيله بواسطة NewPipe. - هذا هو مسار SoundCloud Go+، على الأقل في بلدك، لذلك لا يمكن بثها أو تنزيلها من قبل NewPipe. + هذا مسار SoundCloud Go + ، على الأقل في بلدك ، لذلك لا يمكن دفقه أو تنزيله بواسطة NewPipe. هذا المحتوى غير متوفر في بلدك. اغلق التطبيق قسريا هذا الفيديو مقيد بالفئة العمرية. From d77c23ed34859541e4289551160a0956b537858e Mon Sep 17 00:00:00 2001 From: Agnieszka C Date: Fri, 14 Jan 2022 10:56:24 +0000 Subject: [PATCH 046/119] Translated using Weblate (Polish) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-pl/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 8393bf1ad..cd911ba60 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -347,7 +347,7 @@ Kontrola jasności gestami Używaj gestów do sterowania jasnością odtwarzacza Aktualizacje - Plik usunięty + Usunięto plik Powiadomienie o aktualizacji aplikacji Powiadomienia o nowych wersjach NewPipe Pamięć zewnętrzna niedostępna @@ -405,7 +405,7 @@ Pozycje odtwarzania na listach Pokazuj wskaźniki pozycji odtwarzania na listach Wyczyść dane - Pozycje odtwarzania usunięte + Usunięto pozycje odtwarzania Plik usunięty albo przeniesiony Plik z tą nazwą już istnieje nie można nadpisać pliku @@ -413,7 +413,7 @@ NewPipe został zamknięty podczas pracy nad plikiem Brak miejsca na urządzeniu Utracono postęp, ponieważ plik został usunięty - Czy chcesz wyczyścić historię pobierania lub usunąć wszystkie pobrane pliki\? + Czy chcesz wyczyścić historię pobierania, czy usunąć wszystkie pobrane pliki\? Ogranicz kolejkę pobierania Tylko jedno pobieranie zostanie uruchomione w tym samym czasie Rozpocznij pobieranie From 4b72ee53b028af1353baf94912f67ffa01ae69a1 Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Fri, 14 Jan 2022 02:31:19 +0000 Subject: [PATCH 047/119] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-zh-rTW/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index d43ceb155..8dbeb8aa5 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -358,7 +358,7 @@ 已暫停 已排入佇列 正在後處理 - 佇列 + 排入佇列 動作被系統拒絕 下載失敗 生成獨特的名稱 From 388a4860b505c75005db1937837375fc2ae1f80e Mon Sep 17 00:00:00 2001 From: Yaron Shahrabani Date: Fri, 14 Jan 2022 15:15:40 +0000 Subject: [PATCH 048/119] Translated using Weblate (Hebrew) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-he/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index 8aa6a5136..d04fba39e 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -144,7 +144,7 @@ גיבוב לאימות אישור שם קובץ - תת־דיונים + תהליכי משנה שגיאה NewPipe בהורדה יש לגעת לפרטים נוספים @@ -371,7 +371,7 @@ מושהה בתור עיבוד מאוחר - תור + הוספה לתור הפעולה נדחתה על ידי המערכת ההורדה נכשלה יצירת שם ייחודי From a437672dc117e5791369cde08ffc5cbb3e6a401d Mon Sep 17 00:00:00 2001 From: Zi Date: Sun, 16 Jan 2022 05:23:19 +0000 Subject: [PATCH 049/119] Translated using Weblate (Javanese) Currently translated at 9.5% (61 of 640 strings) --- app/src/main/res/values-jv/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-jv/strings.xml b/app/src/main/res/values-jv/strings.xml index 35f5b075e..6b518b2e2 100644 --- a/app/src/main/res/values-jv/strings.xml +++ b/app/src/main/res/values-jv/strings.xml @@ -72,5 +72,5 @@ Ra ono pamuter (Sampeyan iso masang VLC kanggo muter iku). Pamuter ora ditemokke. Pasang VLC\? Diterbitake ing %1$s - Pencet suryakanta kanggo nglekasi + Pencet lup kanggo nglekasi \ No newline at end of file From f5dbb0789332f576a00496fa3e86e6ad8192898b Mon Sep 17 00:00:00 2001 From: ssantos Date: Mon, 17 Jan 2022 18:43:17 +0000 Subject: [PATCH 050/119] Translated using Weblate (Portuguese (Portugal)) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-pt-rPT/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 21acd0519..22fbfaf03 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -139,7 +139,7 @@ Desative para parar o carregamento de miniaturas, poupar dados e utilização da memória. As alterações limpam a cache de imagens do disco e da memória Será que queria dizer \"%1$s\"\? Mostrar uma notificação para pedir a atualização da aplicação se existir uma nova versão - Fila + Enfileirar Ninguém está a ver Remover ficheiros descarregados Idioma da aplicação From 2d907706eabdfe3cd99619ee2f06347f37d5ecc5 Mon Sep 17 00:00:00 2001 From: qqqq1 Date: Fri, 21 Jan 2022 01:29:22 +0000 Subject: [PATCH 051/119] Translated using Weblate (Persian) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-fa/strings.xml | 112 ++++++++++++------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index d6569e137..ba82881a3 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -2,32 +2,32 @@ برای شروع، ذره‌بین را بزنید. منتشر شده در %1$s - هیچ پخش‌کنندهٔ جریانی پیدا نشد. مایلید وی‌ال‌سی نصب شود؟ + هیچ پخش‌کنندهٔ شناور پیدا نشد. مایلید VLC نصب شود؟ نصب لغو - گشودن در مرورگر - هم‌رسانی - بارگیری + باز کردن در مرورگر + اشتراک‌گذاری + دانلود جست‌وجو تنظیمات منظورتان «%1$s» بود؟ - هم‌رسانی با - استفاده از پخش‌کنندهٔ ویدیوی خارجی - استفاده از پخش‌کنندهٔ صدای خارجی - پوشه بارگیری ویدیو - ویدیوهای بارگیری شده اینجا ذخیره می‌شوند - پوشه بارگیری ویدیوها را انتخاب کنید - پوشه بارگیری صدا - صداهای بارگیری شده در این‌جا ذخیره می‌شوند - پوشه بارگیری صداها را انتخاب کنید - وضوح پیش‌گزیده - پخش با کودی - کارهٔ کُره (Kore) پیدا نشد. نصب شود؟ - نمایش گزینهٔ «پخش با کودی» - نمایش گزینه‌ای برای پخش ویدیو با مرکز رسانهٔ کودی + اشتراک‌گذاری با + استفاده از پخش‌کنندهٔ ویدئوی خارجی + استفاده از پخش‌کنندهٔ صوتی خارجی + پوشه دانلود ویدئو + ویدئوهای دانلود شده اینجا ذخیره می‌شوند + پوشه دانلود ویدئوها را انتخاب کنید + پوشه دانلود صدا + صداهای دانلود شده در اینجا ذخیره می‌شوند + پوشه دانلود صداها را انتخاب کنید + کیفیت پیشفرض + پخش با Kodi + اپ Kore نصب نیست، نصب شود؟ + نمایش گزینهٔ «پخش با Kodi» + نمایش گزینه‌ای برای پخش ویدئو با Kodi media center صدا - قالب صدای پیش‌گزیده - زمینه + قالب صدای پیش‌فرض + تم تیره روشن بارگیری @@ -69,7 +69,7 @@ مکث حذف مجموع مقابله‌ای - قبول + تاييد نام پرونده رشته‌ها خطا @@ -78,23 +78,23 @@ لطفاً صبر کنید… در حافظه رونوشت شد پوشه بارگیری را بعدا در تنظیمات مشخص کنید - هیچ پخش کننده جریانی پیدا نشد (شما می‌توانید برنامه وی‌ال‌سی را برای پخش آن نصب کنید). - بارگیری پرونده جریان - حذف صدا در برخی کیفیت‌ها - اشتراک + هیچ پخش‌کنندهٔ شناور پیدا نشد (می‌توانید برای پخش، اپ VLC را نصب کنید). + دانلود فایل شناور + برخی کیفیت‌ها صوت ندارند + مشترک شدن مشترک شده اشتراک کانال لغو شد - ناتوانی در تغییر وضعیت اشتراک - ناتوانی در به‌روزرسانی اشتراک + امکان تغییر وضعیت اشتراک وجود ندارد + امکان آپدیت اشتراک وجود ندارد نمایش اطلاعات اشتراک‌ها - فهرست‌های پخش دارای نشانک + لیست‌های پخش نشانه‌گذاری شده موارد جدید - پس زمینه + پس‌زمینه افزودن به - نمایش کیفیت بالاتر + نمایش کیفیت‌های بالاتر تنها برخی دستگاه‌ها توانایی پخش ویدیوهای 2K و 4K را دارند - قالب ویدیویی پیش‌گزیده + قالب ویدئوی پیش‌فرض سیاه بار کردن بندانگشتی‌ها قرار دادن خودکار جریان بعدی در صف @@ -156,17 +156,17 @@ B %s مشترک - %s مشترک + %s مشترکین بدون بازدید %s بازدید - %s بازدید + %s بازدیدها بدون ویدیو - %s ویدیو - %s ویدیو + %s ویدئو + %s ویدئوها ایجاد صرف نظر @@ -225,14 +225,14 @@ بدون توضیحات توضحیات لغو اشتراک - انتخاب زبانه + انتخاب سربرگ تاریخچه تماشا تاریخچه و حافظه نهان اشکال‌زدایی به‌روزرسانی‌ها - گشودن در حالت تصویر در تصویر - دقّت پیش‌گزیدهٔ تصویر در تصویر - تصویر در تصویر + باز کردن در حالت تصویر در تصویر + کیفیت پیشفرض تصویر در تصویر + تصویر در تصویر به یاد داشتن ویژگی‌های تصویر در تصویر به یاد داشتن آخرین اندازه و موقعیت تصویر در تصویر زمان فعلی پخش کننده را به صورت تقریبی و سریع جلو ببر @@ -288,7 +288,7 @@ کنترل روشنایی اشاره ای از اشارات برای کنترل روشنایی استفاده شود بازگردانی - چه:\\nدرخواست:\\nزبان محتوا:\\nکشور محتوا:\\nزبان کاره:\\nخدمت:\\nزمان GMT\\nبسته:T:\\nنگارش:\\nنگارش س.ع: + چی:\\nدرخواست:\\nزبان محتوا:\\nکشور محتوا:\\nزبان اپ:\\nخدمات:\\nزمانGMT\\nپکیج:T:\\nنسخه:\\nنسخه سیستم‌عامل: چالش ری‌کپچا نیاز به چالش ری‌کپچا است این اجازه برای گشودن در حالت @@ -439,8 +439,8 @@ جدید می‌خواهید این گروه را پاک کنید؟ - %d مورد انتخاب شده - %d مورد انتخاب شده + %d انتخاب شده + %d انتخاب شدگان پردازش خوراک… بارگیری خوراک… @@ -487,12 +487,12 @@ بیش از ۱۰۰ ویدیو %s شنونده - %s شنونده + %s شنوندگان کسی در حال شنیدن نیست %s بیننده - %s بیننده + %s بینندگان کسی در حال مشاهده نیست تغییر خدمت، مورد انتخاب شده: @@ -536,7 +536,7 @@ آستانه به‌روزرسانی خوراک به دنبال محدودیت‌های ExoPlayer، مدت جابجایی زمان پخش روی %d ثانیه تنظیم شد متن‌های اصلی از خدمات در جریان‌ها قابل دیدن خواهند بود - میان گرفتن + بافر کردن خالی کردن نام گروه توقف روی شبکه‌های محدودشده هرگز @@ -549,18 +549,18 @@ صف پخش‌کنندهٔ فعال جایگزین می‌شود تغییر پخش کننده می‌تواند باعث جایگزین شدن صف شود پیش از پاک کردن صف، سوال شود - هیچ - برزنی + هیچی + تصادفی تکرار - حداکثر تا سه کنش را می‌توانید برای نمایش در اعلان فشرده انتخاب کنید! - هر کنش آگاهی را با لمس کردنش ویرایش کنید. با استفاده از جعبه‌های تیک، تا سه کنش را برای نمایش در آگاهی فشرده بگزینید + حداکثر سه کنش را می‌توانید برای نمایش در اعلان فشرده انتخاب کنید! + هر اعلان کنش را با لمس کردنش ویرایش کنید. با استفاده از جعبه‌های تیک سمت راست، حداکثر سه مورد را انتخاب کنید تا در اعلان فشرده نمایش داده شوند پنجمین دکمه کنشی چهارمین دکمه کنشی سومین دکمه کنشی دومین دکمه کنشی اولین دکمه کنشی - تصویر بندانگشتی ویدیو که در اعلان نمایش می‌یابد، از نسبت ۱۶:۹ به ۱:۱ تغییر اندازه پیدا کند (ممکن است منجر به اعوجاج شود) - تغییر مقیاس تصویر بندانگشتی به نسبت ۱:۱ + تصاویر بندانگشتی ویدیو که در اعلان نمایش می‌یابد، از نسبت 16:9 به 1:1 تغییر اندازه پیدا کند (ممکن است منجر به اعوجاج شود) + تغییر مقیاس تصاویر بندانگشتی به نسبت 1:1 کیفیت پایین (کوچک‌تر) کیفیت بالا (بزرگ‌تر) نظرها از کار افتاده‌اند @@ -607,12 +607,12 @@ به تازگی در صف شد صف کردن - زمینهٔ شب - رنگی کردن آگاهی - گشودن با - نشانه به عنوان دیده‌شده + تم شب + رنگی کردن اعلان + باز کردن با + علامت‌گذاری به عنوان دیده‌شده نمایش روبان‌های رنگی پیکاسو در بالای تصویرها کهنشانگر منبعشان است: قرمز برای شبکه ، آبی برای دیسک و سبز برای حافظه - درخواست از اندروید برای سفارشی‌سازی رنگ آگاهی براساس رنگ اصلی در بندانگشتی (توجّه داشته باشید که روی همهٔ افزاره‌ها در دسترس نیست) + درخواست از اندروید برای سفارشی‌سازی رنگ اعلان براساس رنگ اصلی در بندانگشتی (اگرچه روی همه دستگاه‌ها ممکن نیست) این ویدیو محدود به سن است. \n \nاگر می‌خواهید ببینیدش، «%1$s» را در تنظیمات روشن کنید. From 15dc99f110692e7182cf3485ca8753a65241ffb1 Mon Sep 17 00:00:00 2001 From: translator Date: Tue, 18 Jan 2022 14:21:59 +0000 Subject: [PATCH 052/119] Translated using Weblate (French) Currently translated at 99.2% (635 of 640 strings) --- app/src/main/res/values-fr/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 7d9c3435c..afc014a90 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -229,7 +229,7 @@ Nouvelle liste de lecture Renommer Nom - Ajouter à la liste de lecture + Ajouter à une liste de lecture Définir comme miniature de la liste de lecture Enregister la liste de lecture Supprimer le signet @@ -569,7 +569,7 @@ Redimensionner la miniature au format 1:1 Afficher les fuites de mémoire Ajouté à la file d’attente - Ajouter à la file d’attente + Ajouter à la file de lecture Effacer les cookies que NewPipe garde lorsque vous résolvez un reCAPTCHA Les cookies reCAPTCHA ont été effacés Effacer les cookies reCAPTCHA From 2f87305f2d85b0a20381d1cef7ac1911eb67cdd5 Mon Sep 17 00:00:00 2001 From: VfBFan Date: Wed, 19 Jan 2022 06:29:53 +0000 Subject: [PATCH 053/119] Translated using Weblate (German) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-de/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 3e2a881ad..de52b5b93 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -370,7 +370,7 @@ pausiert eingereiht Nachbearbeitung - Warteschlange + In Wiedergabe einreihen System verweigert den Zugriff Herunterladen fehlgeschlagen Eindeutigen Namen erzeugen From b8e5e036b258c8401a3fd01dce524f5e9f8e3c1d Mon Sep 17 00:00:00 2001 From: TiA4f8R Date: Sun, 23 Jan 2022 17:31:16 +0000 Subject: [PATCH 054/119] Translated using Weblate (French) Currently translated at 99.2% (635 of 640 strings) --- app/src/main/res/values-fr/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index afc014a90..7d9c3435c 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -229,7 +229,7 @@ Nouvelle liste de lecture Renommer Nom - Ajouter à une liste de lecture + Ajouter à la liste de lecture Définir comme miniature de la liste de lecture Enregister la liste de lecture Supprimer le signet @@ -569,7 +569,7 @@ Redimensionner la miniature au format 1:1 Afficher les fuites de mémoire Ajouté à la file d’attente - Ajouter à la file de lecture + Ajouter à la file d’attente Effacer les cookies que NewPipe garde lorsque vous résolvez un reCAPTCHA Les cookies reCAPTCHA ont été effacés Effacer les cookies reCAPTCHA From 60c3a2dc9c60aa5fadd3da07ebfb59e8d8d0fe1b Mon Sep 17 00:00:00 2001 From: Danial Behzadi Date: Sat, 22 Jan 2022 14:25:59 +0000 Subject: [PATCH 055/119] Translated using Weblate (Persian) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-fa/strings.xml | 114 ++++++++++++------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index ba82881a3..774d3e020 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -2,32 +2,32 @@ برای شروع، ذره‌بین را بزنید. منتشر شده در %1$s - هیچ پخش‌کنندهٔ شناور پیدا نشد. مایلید VLC نصب شود؟ + هیچ پخش‌کنندهٔ جریانی پیدا نشد. مایلید وی‌ال‌سی نصب شود؟ نصب لغو - باز کردن در مرورگر - اشتراک‌گذاری - دانلود + گشودن در مرورگر + هم‌رسانی + بارگیری جست‌وجو تنظیمات منظورتان «%1$s» بود؟ - اشتراک‌گذاری با - استفاده از پخش‌کنندهٔ ویدئوی خارجی - استفاده از پخش‌کنندهٔ صوتی خارجی - پوشه دانلود ویدئو - ویدئوهای دانلود شده اینجا ذخیره می‌شوند - پوشه دانلود ویدئوها را انتخاب کنید - پوشه دانلود صدا - صداهای دانلود شده در اینجا ذخیره می‌شوند - پوشه دانلود صداها را انتخاب کنید - کیفیت پیشفرض - پخش با Kodi - اپ Kore نصب نیست، نصب شود؟ - نمایش گزینهٔ «پخش با Kodi» - نمایش گزینه‌ای برای پخش ویدئو با Kodi media center + هم‌رسانی با + استفاده از پخش‌کنندهٔ ویدیوی خارجی + استفاده از پخش‌کنندهٔ صدای خارجی + شاخهٔ بارگیری ویدیو + پرونده‌های ویدیویی بارگرفته این‌جا ذخیره می‌شوند + گزینش شاخه برای بارگیری پرونده‌های ویدیویی + شاخهٔ بارگیری صدا + پرونده‌های صوتی بارگرفته این‌جا ذخیره می‌شوند + گزینش شاخهٔ بارگیری برای پرونده‌های صوتی + وضوح پیش‌گزیده + پخش با کودی + کارهٔ کُره (Kore) پیدا نشد. نصب شود؟ + نمایش گزینهٔ «پخش با کودی» + نمایش گزینه‌ای برای پخش ویدیو با مرکز رسانهٔ کودی صدا - قالب صدای پیش‌فرض - تم + قالب صدای پیش‌گزیده + زمینه تیره روشن بارگیری @@ -69,7 +69,7 @@ مکث حذف مجموع مقابله‌ای - تاييد + قبول نام پرونده رشته‌ها خطا @@ -78,23 +78,23 @@ لطفاً صبر کنید… در حافظه رونوشت شد پوشه بارگیری را بعدا در تنظیمات مشخص کنید - هیچ پخش‌کنندهٔ شناور پیدا نشد (می‌توانید برای پخش، اپ VLC را نصب کنید). - دانلود فایل شناور - برخی کیفیت‌ها صوت ندارند - مشترک شدن + هیچ پخش کنندهٔ جریانی پیدا نشد (می‌توانید برای پخشش وی‌ال‌سی را نصب کنید). + بارگیری پروندهٔ جریان + صدا را در برخی وضوح‌ها برمی‌دارد + اشتراک مشترک شده اشتراک کانال لغو شد - امکان تغییر وضعیت اشتراک وجود ندارد - امکان آپدیت اشتراک وجود ندارد + ناتوانی در تغییر وضعیت اشتراک + ناتوانی در به‌روزرسانی اشتراک نمایش اطلاعات اشتراک‌ها - لیست‌های پخش نشانه‌گذاری شده + سیاههٔ پخش‌های نشان شده موارد جدید پس‌زمینه افزودن به - نمایش کیفیت‌های بالاتر + نمایش وضوح‌های بالاتر تنها برخی دستگاه‌ها توانایی پخش ویدیوهای 2K و 4K را دارند - قالب ویدئوی پیش‌فرض + قالب ویدیویی پیش‌گزیده سیاه بار کردن بندانگشتی‌ها قرار دادن خودکار جریان بعدی در صف @@ -156,17 +156,17 @@ B %s مشترک - %s مشترکین + %s مشترک بدون بازدید %s بازدید - %s بازدیدها + %s بازدید بدون ویدیو - %s ویدئو - %s ویدئوها + %s ویدیو + %s ویدیو ایجاد صرف نظر @@ -225,14 +225,14 @@ بدون توضیحات توضحیات لغو اشتراک - انتخاب سربرگ + گزینش زبانه تاریخچه تماشا تاریخچه و حافظه نهان اشکال‌زدایی به‌روزرسانی‌ها - باز کردن در حالت تصویر در تصویر - کیفیت پیشفرض تصویر در تصویر - تصویر در تصویر + گشودن در حالت تصویردرتصویر + وضوح پیش‌گزیدهٔ تصویردرتصویر + تصویردرتصویر به یاد داشتن ویژگی‌های تصویر در تصویر به یاد داشتن آخرین اندازه و موقعیت تصویر در تصویر زمان فعلی پخش کننده را به صورت تقریبی و سریع جلو ببر @@ -259,7 +259,7 @@ برای بارگیری، لمس کنید تمام در انتظار - صف + صف‌گذاری بارگیری ناموفق بود یافت نشد شکست در پساپردازش @@ -288,7 +288,7 @@ کنترل روشنایی اشاره ای از اشارات برای کنترل روشنایی استفاده شود بازگردانی - چی:\\nدرخواست:\\nزبان محتوا:\\nکشور محتوا:\\nزبان اپ:\\nخدمات:\\nزمانGMT\\nپکیج:T:\\nنسخه:\\nنسخه سیستم‌عامل: + چه:\\nدرخواست:\\nزبان محتوا:\\nکشور محتوا:\\nزبان کاره:\\nخدمت:\\nزمان GMT\\nبسته:T:\\nنگارش:\\nنگارش س.ع: چالش ری‌کپچا نیاز به چالش ری‌کپچا است این اجازه برای گشودن در حالت @@ -370,7 +370,7 @@ متوقف در صف در حال پساپردازش - این کنش توسط سیستم متوقف شد + کنش به دست سامانه متوقف شد تولید نام یگانه بازنویسی یک بارگیری دیگر با همین نام در جریان است @@ -439,8 +439,8 @@ جدید می‌خواهید این گروه را پاک کنید؟ - %d انتخاب شده - %d انتخاب شدگان + %d مورد گزیده + %d مورد گزیده پردازش خوراک… بارگیری خوراک… @@ -487,12 +487,12 @@ بیش از ۱۰۰ ویدیو %s شنونده - %s شنوندگان + %s شنونده کسی در حال شنیدن نیست %s بیننده - %s بینندگان + %s بیننده کسی در حال مشاهده نیست تغییر خدمت، مورد انتخاب شده: @@ -536,7 +536,7 @@ آستانه به‌روزرسانی خوراک به دنبال محدودیت‌های ExoPlayer، مدت جابجایی زمان پخش روی %d ثانیه تنظیم شد متن‌های اصلی از خدمات در جریان‌ها قابل دیدن خواهند بود - بافر کردن + میان گرفتن خالی کردن نام گروه توقف روی شبکه‌های محدودشده هرگز @@ -549,18 +549,18 @@ صف پخش‌کنندهٔ فعال جایگزین می‌شود تغییر پخش کننده می‌تواند باعث جایگزین شدن صف شود پیش از پاک کردن صف، سوال شود - هیچی - تصادفی + هیچ + بُرزنی تکرار - حداکثر سه کنش را می‌توانید برای نمایش در اعلان فشرده انتخاب کنید! - هر اعلان کنش را با لمس کردنش ویرایش کنید. با استفاده از جعبه‌های تیک سمت راست، حداکثر سه مورد را انتخاب کنید تا در اعلان فشرده نمایش داده شوند + می‌توانید تا سه کنش را برای نمایش در آگاهی فشرده برگزینید! + هر کنش آگاهی را با لمس کردنش ویرایش کنید. با استفاده از جعبه‌های تیک، تا سه کنش را برای نمایش در آگاهی فشرده بگزینید پنجمین دکمه کنشی چهارمین دکمه کنشی سومین دکمه کنشی دومین دکمه کنشی اولین دکمه کنشی - تصاویر بندانگشتی ویدیو که در اعلان نمایش می‌یابد، از نسبت 16:9 به 1:1 تغییر اندازه پیدا کند (ممکن است منجر به اعوجاج شود) - تغییر مقیاس تصاویر بندانگشتی به نسبت 1:1 + تصویر بندانگشتی ویدیو که در اعلان نمایش می‌یابد، از نسبت ۱۶:۹ به ۱:۱ تغییر اندازه پیدا کند (ممکن است منجر به اعوجاج شود) + تغییر مقیاس تصویر بندانگشتی به نسبت ۱:۱ کیفیت پایین (کوچک‌تر) کیفیت بالا (بزرگ‌تر) نظرها از کار افتاده‌اند @@ -607,12 +607,12 @@ به تازگی در صف شد صف کردن - تم شب - رنگی کردن اعلان - باز کردن با - علامت‌گذاری به عنوان دیده‌شده + زمینهٔ شب + رنگی کردن آگاهی + گشودن با + نشانه به عنوان دیده شده نمایش روبان‌های رنگی پیکاسو در بالای تصویرها کهنشانگر منبعشان است: قرمز برای شبکه ، آبی برای دیسک و سبز برای حافظه - درخواست از اندروید برای سفارشی‌سازی رنگ اعلان براساس رنگ اصلی در بندانگشتی (اگرچه روی همه دستگاه‌ها ممکن نیست) + درخواست از اندروید برای سفارشی‌سازی رنگ آگاهی براساس رنگ اصلی در بندانگشتی (توجّه داشته باشید که روی همهٔ افزاره‌ها در دسترس نیست) این ویدیو محدود به سن است. \n \nاگر می‌خواهید ببینیدش، «%1$s» را در تنظیمات روشن کنید. From 69dacb34b93d58c358fbcb021197f7c9d96d5972 Mon Sep 17 00:00:00 2001 From: subba raidu Date: Fri, 21 Jan 2022 19:24:02 +0000 Subject: [PATCH 056/119] Translated using Weblate (Telugu) Currently translated at 66.0% (423 of 640 strings) --- app/src/main/res/values-te/strings.xml | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml index 5bdecf730..624e50335 100644 --- a/app/src/main/res/values-te/strings.xml +++ b/app/src/main/res/values-te/strings.xml @@ -107,7 +107,7 @@ వివరాల కోసం నొక్కండి దయచేసి వేచి ఉండండి… క్లిప్బోర్డ్కు కాపీ చేయబడింది - దయచేసి అందుబాటులో ఉన్న డౌన్లోడ్ ఫోల్డర్ను ఎంచుకోండి + డౌన్లోడ్ ఫోల్డర్ను అమరికలలో తరువాత ఎంచుకోండి డౌన్లోడ్ ఫైల్ పేర్లలో అనుమతించిన అక్షరాలు చెల్లని అక్షరాలు ఈ విలువతో భర్తీ చేయబడతాయి @@ -129,7 +129,7 @@ ఖాళీ పేజీ ఛానెల్ పేజీ ఛానెల్ని ఎంచుకోండి - ఇంకా ఛానెల్ ఏదీ చందా చేయలేదు + ఇంకా ఏ ఛానెల్ సభ్యత్వం లేదు ట్రెండింగ్ టాప్ 50 క్రొత్తది మరియు వేడి @@ -289,7 +289,7 @@ మొత్తం వీక్షణ చరిత్రను తొలగించాలా\? ప్లేబ్యాక్ స్థానాలను తొలగించండి బాహ్య నిల్వ అందుబాటులో లేదు - యాప్/UI క్రాష్ అయింది + యాప్/UI విఫలమైనది ఆడియో స్ట్రీమ్‌లు ఏవీ కనుగొనబడలేదు అటువంటి ఫోల్డర్ లేదు ఇతర యాప్‌లలో ప్రదర్శించడానికి అనుమతి ఇవ్వండి @@ -410,4 +410,17 @@ చలనచిత్ర ప్లేయర్ తేలియాడే ప్లేయర్ ప్రాసెస్ చేస్తోంది... కొంత సమయం పట్టవచ్చు + వినోదజాబితా సూక్ష్మచిత్రం మార్చబడింది. + శీర్షికలు లేవు + వినోదజాబితా రూపొందించబడింది + వినోదజాబితా చేయబడింది + అన్‌మ్యూట్ చేయండి + వినోదజాబితాకు సూక్ష్మచిత్రంగా మార్చుము + వినోదజాబితాను ఇష్టంశంగా మార్చుము + ఇష్టంశాన్ని తొలగించండి + ఇష్టంశాన్ని నాశనం చేయాలా\? + తగినది + పూరించండి + పరివీక్షణ + తేలియాడే విధంగా మార్చు \ No newline at end of file From 08c928e1d0ddc5325b9fc9ab701ca1e93ebd4374 Mon Sep 17 00:00:00 2001 From: retiolus Date: Thu, 20 Jan 2022 19:48:08 +0000 Subject: [PATCH 057/119] Translated using Weblate (Catalan) Currently translated at 98.5% (631 of 640 strings) --- app/src/main/res/values-ca/strings.xml | 34 +++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 28c55cd59..327175f1c 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -136,7 +136,7 @@ Llengua per defecte dels continguts S\'està reproduint en rerefons S\'està reproduint en mode emergent - Notificació del NewPipe + Notificació de NewPipe Notificacions per al reproductor de NewPipe No s\'han pogut carregar totes les miniatures No s\'ha pogut desxifrar la signatura de l\'URL del vídeo @@ -655,4 +655,36 @@ Ja s\'està reproduint en segon pla Notificació d\'informe d\'error Tancar abruptament el reproductor + Comprovar si hi ha actualitzacions + Comprovar manualment si hi ha noves versions + + Baixada finalitzada + %s baixades finalitzades + + Vista prèvia de les miniatures de la barra de cerca + No s\'ha trobat cap gestor de fitxers adequat per a aquesta acció. +\nInstal·leu un gestor de fitxers compatible amb l\'entorn d\'accés d\'emmagatzematge. + No s\'ha trobat cap gestor de fitxers adequat per a aquesta acció. +\nInstal·leu un gestor de fitxers o intenteu desactivar «%s» als paràmetres de baixada. + S\'ha produït un error, consulteu la notificació + Afegit el següent vídeo a la cua + NewPipe ha trobat un error, toca per informar + Posa a la cua el següent vídeo + Crear una notificació d\'error + Error en mostrar els detalls del canal + Notificacions per informar d\'errors + Mostra una barra d\'errors + S\'estan comprovant les actualitzacions… + + S\'ha suprimit %1$s baixada + S\'han suprimit %1$s baixades + + El \"Sistema d\'Accés a l\'Emmagatzematge\" no està implementat a Android KitKat i a versions anteriors + A partir de l\'Android 10 només s\'admet el \"Sistema d\'Accés a l\'Emmagatzematge\" + Elements de feed nous + El mode d\'alimentació ràpida no proporciona més informació sobre això. + Comentari fixat + Mostrar \"tancar de forma violenta el reproductor\" + Mostra una opció de fallada quan s\'utilitza el reproductor + Mostra les cintes de color Picasso a la part superior de les imatges que indiquen la seva font: vermell per a la xarxa, blau per al disc i verd per a la memòria \ No newline at end of file From 194e43f5cb2b5fe2f80bd439bdff6bc92a60c279 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Sun, 23 Jan 2022 22:34:38 +0100 Subject: [PATCH 058/119] Remove unused strings report_player_errors_title and report_player_errors_summary were removed in #7482 --- app/src/main/res/values-ar/strings.xml | 2 -- app/src/main/res/values-b+zh+HANS+CN/strings.xml | 2 -- app/src/main/res/values-de/strings.xml | 2 -- app/src/main/res/values-el/strings.xml | 2 -- app/src/main/res/values-es/strings.xml | 2 -- app/src/main/res/values-fa/strings.xml | 2 -- app/src/main/res/values-fr/strings.xml | 2 -- app/src/main/res/values-he/strings.xml | 2 -- app/src/main/res/values-in/strings.xml | 2 -- app/src/main/res/values-it/strings.xml | 2 -- app/src/main/res/values-ja/strings.xml | 2 -- app/src/main/res/values-nb-rNO/strings.xml | 2 -- app/src/main/res/values-nl/strings.xml | 2 -- app/src/main/res/values-pl/strings.xml | 2 -- app/src/main/res/values-pt-rBR/strings.xml | 2 -- app/src/main/res/values-pt-rPT/strings.xml | 2 -- app/src/main/res/values-pt/strings.xml | 2 -- app/src/main/res/values-ru/strings.xml | 2 -- app/src/main/res/values-sr/strings.xml | 1 - app/src/main/res/values-sv/strings.xml | 2 -- app/src/main/res/values-te/strings.xml | 2 -- app/src/main/res/values-uk/strings.xml | 2 -- app/src/main/res/values-zh-rTW/strings.xml | 2 -- 23 files changed, 45 deletions(-) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index d9107d03f..0b17fdfd2 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -721,11 +721,9 @@ التحقق يدويا من وجود إصدارات جديدة جاري التحقق من وجود تحديثات… عناصر تغذية جديدة - الإبلاغ عن أخطاء المشغل إظهار خيار تعطل عند استخدام المشغل إظهار \"تعطل المشغل\" تحطيم المشغل - رفع تقرير لأخطاء المشغل بالتفصيل الكامل بدلا من إظهار رسالة اشعار قصيرة الأجل (مفيدة لتشخيص المشاكل) إشعار الإبلاغ عن الأخطاء التنبيهات المتعلقة بالإبلاغ عن الأخطاء واجه NewPipe خطأ، اضغط للتقرير 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 34043af94..10777db8f 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 @@ -661,11 +661,9 @@ 检查更新中… 检查更新 新订阅源条目 - 完整报告播放器错误,而不是弹出一个临时Toast(对诊断应用很有用) 显示\"使播放器崩溃\" 在使用播放器时显示一个崩溃选项 使播放器崩溃 - 报告播放器错误 错误报告通知 提示报告错误的通知 发生错误,详见通知 diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index de52b5b93..a4c622087 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -675,9 +675,7 @@ Neue Feed-Elemente \"Absturz des Players\" anzeigen Absturz des Players - Meldet Playerfehler mit allen Details, anstatt eine kurzlebige Popupmeldung anzuzeigen (nützlich für die Diagnose von Problemen) Zeigt eine Absturzoption an, wenn der Player verwendet wird - Playerfehler melden Benachrichtigung über Fehlerberichte Benachrichtigungen zur Meldung von Fehlern Bei NewPipe ist ein Fehler aufgetreten. Zum Melden antippen diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 2706da83d..804cbc5bc 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -675,8 +675,6 @@ Νέα αντικείμενα τροφοδοσίας Εμφάνιση «κατάρρευσης αναπαραγωγέα» Εμφανίζει μια επιλογή κατάρρευσης κατά τη χρήση του αναπαραγωγέα - Αναφορά σφαλμάτων αναπαραγωγέα - Αναφορά σφαλμάτων αναπαραγωγέα με λεπτομέρειες αντί για ένα σύντομο μήνυμα (χρήσιμο για διάγνωση προβλημάτων) Κατάρρευση αναπαραγωγέα Ειδοποίηση αναφοράς σφάλματος Ειδοποιήσεις για την αναφορά σφαλμάτων diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 11d4aa494..442bfeb24 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -677,9 +677,7 @@ Buscando actualizaciones… Nuevos elementos en el muro Cerrar abruptamente el reproductor - Informar de errores del reproductor Muestra una opción de cierre abrupto al usar el reproductor - Informar de errores del reproductor con detalle en lugar de mostrar un mensaje emergente efímero (útil para diagnosticar problemas) Mostrar \"Cerrar abruptamente el reproductor\" Notificaciones para informar errores Notificación de informe de errores diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index 774d3e020..20494637d 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -674,9 +674,7 @@ بررسی کردن به‌روز رسانی‌ها… موارد خوراک جدید فروپاشی پخش‌کننده - گزارش خطاهای پخش کننده نمایش یک گزینهٔ فروپاشی هنگام استفاده از پخش کننده - گزارش خطاهای پخش کننده با جزییات کامل به جای نشان دادن پیامی با عمر کوتاه (مناسب برای تشخیص مشکلات) نمایش «فروپاشی پخش کننده» مدیر پروندهٔ مناسبی برای این کنش یافت نشد. \nلطفاً مدیر پرونده‌ای نصب کرده یا در تنظیمات بارگیری، «%s» را خاموش کنید. diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 7d9c3435c..d4946f545 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -675,8 +675,6 @@ Vérification des mises à jour… Vérifier les mises à jours Nouveaux éléments du flux - Signaler les erreurs du lecteur de manière détaillée au lieu de montrer un bref message éphémère (utile pour diagnostiquer les problèmes) - Signaler les erreurs du lecteur Faire planter le lecteur Afficher « Faire planter le lecteur » Montrer une option de plantage lors de l\'utilisation du lecteur diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index d04fba39e..dfbca0e4a 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -699,8 +699,6 @@ פריטים חדשים בהזנה להקריס את הנגן הצגת „להקריס את הנגן” - דיווח על שגיאות בנגן - מדווח על שגיאות בנגן בפירוט מלא במקום להציג הודעה שקופצת למסך לזמן קצר (יעיל לניתוח תקלות) הצגת אפשרות קריסה בעת שימוש בנגן התראות לדיווח על שגיאות הצגת חלונית בזק עם שגיאה diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 5eb00875a..bed00bfe5 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -663,8 +663,6 @@ Item feed baru Tampilkan \"hentikan pemain video\" Menampilkan opsi penghentian ketika menggunakan pemain video - Melaporkan kesalahan pemain video dalam detail yang penuh daripada menampilkan pesan toast yang muncul sebentar (berguna untuk memeriksa masalah) - Laporkan kesalahan pemain video Hentikan pemain video Notifikasi untuk melaporkan kegalatan Notifikasi laporan kegalatan diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index f9e620e3d..66932597e 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -673,9 +673,7 @@ Verifica manualmente la presenza di nuove versioni Controllo aggiornamenti… Nuovi elementi feed - Segnala errori del lettore multimediale Quando il lettore multimediale è in uso, mostra un\'opzione per farlo crashare - Invece di mostrare un messaggio popup di breve durata, gli errori del lettore multimediale saranno visualizzati in modo dettagliato (utile per diagnosticare i problemi) Mostra \"Fai crashare il lettore\" Fai crashare il lettore NewPipe ha riscontrato un errore, tocca per segnalarlo diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 6f00ff0e1..1b191c994 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -660,8 +660,6 @@ 次をキューに追加 次をキューに追加しました クリエイターの心をこめて - プレーヤーのエラーを、短時間のトーストメッセージではなく、詳細に報告する(問題の診断に役立ちます) - プレイヤーのエラーを報告 \"プレイヤーがクラッシュ\"を表示 プレイヤーがクラッシュ 新しいフィードアイテム diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index ff82fce20..92b3a30ed 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -669,8 +669,6 @@ Se etter oppdateringer Behandler … Kan ta sin tid Krasj avspilleren - Rapporter avspillerfeil - Sirlig rapportering av feil, istedenfor å kun vise et lite oppsprett en stund (nyttig i avlusningsøyemed) Vis «Krasj spilleren» Se etter nye versjoner manuelt Nye informasjonskanalelementer diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 365e251aa..f3837ef7d 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -668,10 +668,8 @@ Veeg items om ze te verwijderen Start geen video\'s in de minispeler, maar ga direct naar de volledige schermmodus, als automatisch draaien is vergrendeld. Je hebt nog steeds toegang tot de minispeler door de volledige schermmodus af te sluiten Start hoofdspeler als volledig scherm - Rapporteer fouten van de speler in volledig detail in plaats van een kortstondige toastmelding te tonen (handig voor het diagnosticeren van problemen) Verwerken... Dit kan even duren Crash de speler - Rapporteer fouten van de speler Toon \"crash de speler\" Toon een crash overzicht bij gebruik van de speler Controleer handmatig op nieuwe versies diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index cd911ba60..0577f2f5d 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -692,11 +692,9 @@ Ręcznie sprawdź dostępność nowych wersji Sprawdź dostępność aktualizacji Nowe pozycje kanału - Zgłaszaj błędy odtwarzacza Pokazuje opcję psucia podczas korzystania z odtwarzacza Zepsuj odtwarzacz Pokazuj „zepsuj odtwarzacz” - Zgłasza szczegółowo błędy odtwarzacza zamiast pokazywać krótkotrwałą wiadomość toast (przydatne do diagnozowania problemów) Powiadomienie raportu o błędach Powiadomienia do zgłaszania błędów NewPipe napotkał błąd. Naciśnij, aby zgłosić diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index b90c45ca9..a77d38f97 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -673,9 +673,7 @@ Procurar manualmente por novas versões Procurando por atualizações… Travar o player - Reporta os erros do player em detalhes completos, em vez de mostrar uma mensagem de notificação de curta duração (útil para diagnosticar problemas) Mostrar \"travar o player\" - Reportar erros do player Mostra uma opção de travamento ao usar o player Novos itens do feed Notificação de relatório de erro diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 22fbfaf03..85fe30ca1 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -674,8 +674,6 @@ A procurar atualizações… Novos itens Travar o reprodutor - Relata os erros do reprodutor com todos os detalhes em vez de mostrar uma mensagem de notificação por pouco tempo (útil para diagnosticar problemas) - Relatar erros do reprodutor Mostrar \"travar o reprodutor\" Mostra uma opção de travamento ao usar o reprodutor Notificação de relatório de erros diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index f45c852eb..326bab03b 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -674,8 +674,6 @@ A procurar atualizações… Novos itens Travar o reprodutor - Relata os erros do reprodutor com todos os detalhes em vez de mostrar uma mensagem de notificação por pouco tempo (útil para diagnosticar problemas) - Relatar erros do reprodutor Mostrar \"travar o reprodutor\" Mostra uma opção de travamento ao usar o reprodutor Notificação de relatório de erros diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 71c96bd89..6c357fa13 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -689,8 +689,6 @@ Проверить обновления Проверка обновлений… Новое на канале - Отчёт об ошибках плеера - Подробные отчёты об ошибках плеера вместо коротких всплывающих сообщений (полезно при диагностике проблем) Показать \"Вызвать сбой плеера\" Показать функцию вызова сбоя при работе плеера Вызвать сбой плеера diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 3fb178acb..82e8eb953 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -660,6 +660,5 @@ Обрађујем… Може потрајати пар тренутака Приказуј указиваче слике Не покрећи видео у малом прозору, већ пређи одмах у пун приказ заслона, уколико је обртање приказа закључано. И даље можете приступити малом приказу извођача изласком из пуног приказа - Пријави грешке програма извођача видеа Покрени пуни главни приказ извођача \ No newline at end of file diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 4dd02cf4a..0f0aaf53f 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -674,10 +674,8 @@ Söker efter uppdateringar… Nya flödes objekt Visa \"krascha spelaren\" - Rapportera spelarfel Krascha spelaren Visar ett kraschalternativ vid användning av spelaren - Rapporterar spelarfel i detalj i stället för att visa ett kortvarigt popup-meddelande (användbart för att diagnostisera problem) Felrapport-avisering Avisering för att rapportera fel NewPipe stötte på ett fel, tryck för att rapportera diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml index 624e50335..157ad1729 100644 --- a/app/src/main/res/values-te/strings.xml +++ b/app/src/main/res/values-te/strings.xml @@ -198,9 +198,7 @@ HTTPS URLలకు మాత్రమే మద్దతు ఉంది రెండవ చర్య బటన్ నాల్గవ చర్య బటన్ - స్వల్పకాలిక టోస్ట్ సందేశాన్ని చూపించే బదులు పూర్తి వివరాలతో ప్లేయర్ లోపాలను నివేదిస్తుంది (సమస్యలను నిర్ధారించడానికి ఉపయోగపడుతుంది) ప్లేయర్ క్రాష్ చేయండి - ప్లేయర్ లోపాలను నివేదించండి మొదటి చర్య బటన్ ఐదవ చర్య బటన్ మీరు కాంపాక్ట్ నోటిఫికేషన్‌లో చూపడానికి గరిష్టంగా మూడు చర్యలను ఎంచుకోవచ్చు! diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 238e07fef..9c8e57b81 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -690,9 +690,7 @@ Нові записи стрічки Показати «збій програвача» Показує параметр збою під час використання програвача - Повідомити про помилки програвача Збій програвача - Повне повідомлення про помилки програвача замість, короткого звіту (корисно для діагностики проблем) Сповіщення про звіт про помилку Сповіщення для звітів про помилки Сталася помилка NewPipe, торкніться, щоб звітувати diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 8dbeb8aa5..2696962de 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -661,9 +661,7 @@ 手動檢查新版本 正在檢查更新…… 新 feed 項目 - 回報播放器錯誤 播放器當機 - 完整回報播放器錯誤,而非顯示短暫的 toast 訊息(用於診斷問題) 顯示「播放器當機」 使用播放器時顯示當機選項 錯誤回報通知 From c38389672a8736fe53a820d696157d34fd58f428 Mon Sep 17 00:00:00 2001 From: Alex25820 Date: Mon, 24 Jan 2022 16:10:03 +0000 Subject: [PATCH 059/119] Translated using Weblate (Swedish) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-sv/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 0f0aaf53f..59d7e9b75 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -362,7 +362,7 @@ pausad köad efterbehandling - + Köa Åtgärden nekas av systemet Hämtningen misslyckades Generera unikt namn From 983c98d2621360b5faf9ff189cc0c611d220260a Mon Sep 17 00:00:00 2001 From: Ajeje Brazorf Date: Mon, 24 Jan 2022 00:08:55 +0000 Subject: [PATCH 060/119] Translated using Weblate (Sardinian) Currently translated at 100.0% (640 of 640 strings) --- app/src/main/res/values-sc/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml index 3cea8cc97..3ca5ae972 100644 --- a/app/src/main/res/values-sc/strings.xml +++ b/app/src/main/res/values-sc/strings.xml @@ -254,7 +254,7 @@ A disponimentu in unos cantos servìtzios, de sòlitu est meda prus lestru ma diat pòdere frunire unu nùmeru limitadu de elementos e, fatu-fatu, informatziones no intreas (es. peruna longària, casta de elementu, indicadore de istadu in direta) Recùperu dae una fonte de cuntenutos dedicada, cando est a disponimentu Agiorna semper - Tempus chi depet colare a pustis de s\'ùrtimu agiornamentu, in antis chi un\'abbonamebèngiat cunsiderada tropu betza — %s + Tempus chi depet colare a pustis de s\'ùrtimu agiornamentu, in antis chi un\'abbonamentu bèngiat cunsideradu tropu betzu — %s Lìmite de agiornamentu de sa fonte de cuntenutos Fonte de cuntenutos Nou @@ -338,7 +338,7 @@ Ingendra unu nùmene ùnivocu Iscarrigamentu fallidu Atzione vietada dae su sistema - Elencu + Pone in lista recuperende post-protzessamentu in pàusa From 683d9816cb21124cc1f0f04ee26130cb5c4e5a4c Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 24 Dec 2021 21:27:45 +0100 Subject: [PATCH 061/119] Removed dead code --- .../newpipe/settings/AppearanceSettingsFragment.java | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java index 1e1b03b4f..4bc5a210e 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java @@ -2,7 +2,6 @@ package org.schabi.newpipe.settings; import android.content.ActivityNotFoundException; import android.content.Intent; -import android.os.Build; import android.os.Bundle; import android.provider.Settings; import android.widget.Toast; @@ -15,10 +14,6 @@ import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.ThemeHelper; public class AppearanceSettingsFragment extends BasePreferenceFragment { - private static final boolean CAPTIONING_SETTINGS_ACCESSIBLE = - Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; - - private String captionSettingsKey; @Override public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) { @@ -51,16 +46,11 @@ public class AppearanceSettingsFragment extends BasePreferenceFragment { } else { removePreference(nightThemeKey); } - - captionSettingsKey = getString(R.string.caption_settings_key); - if (!CAPTIONING_SETTINGS_ACCESSIBLE) { - removePreference(captionSettingsKey); - } } @Override public boolean onPreferenceTreeClick(final Preference preference) { - if (preference.getKey().equals(captionSettingsKey) && CAPTIONING_SETTINGS_ACCESSIBLE) { + if (preference.getKey().equals(getString(R.string.caption_settings_key))) { try { startActivity(new Intent(Settings.ACTION_CAPTIONING_SETTINGS)); } catch (final ActivityNotFoundException e) { From 12acaf29dd824ee21baadf26dceadd3ce0284aa7 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 24 Dec 2021 21:29:22 +0100 Subject: [PATCH 062/119] Added credit to the project which inspired the preference search --- app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt b/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt index a8fdcae26..1e5bd8799 100644 --- a/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt +++ b/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt @@ -185,7 +185,11 @@ class AboutActivity : AppCompatActivity() { SoftwareComponent( "RxJava", "2016 - 2020", "RxJava Contributors", "https://github.com/ReactiveX/RxJava", StandardLicenses.APACHE2 - ) + ), + SoftwareComponent( + "SearchPreference", "2018", "ByteHamster", + "https://github.com/ByteHamster/SearchPreference", StandardLicenses.MIT + ), ) private const val POS_ABOUT = 0 private const val POS_LICENSE = 1 From f3be89b503649067ba33638a3881c987adc3ec42 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 24 Dec 2021 21:30:49 +0100 Subject: [PATCH 063/119] Abstracted methods for the Android keyboard --- .../fragments/list/search/SearchFragment.java | 23 ++-------- .../org/schabi/newpipe/util/KeyboardUtil.java | 43 +++++++++++++++++++ 2 files changed, 46 insertions(+), 20 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/util/KeyboardUtil.java diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java index 15424334d..055c27733 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java @@ -25,7 +25,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.animation.DecelerateInterpolator; import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.TextView; @@ -34,7 +33,6 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.TooltipCompat; -import androidx.core.content.ContextCompat; import androidx.core.text.HtmlCompat; import androidx.preference.PreferenceManager; import androidx.recyclerview.widget.ItemTouchHelper; @@ -65,6 +63,7 @@ import org.schabi.newpipe.settings.NewPipeSettings; import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.ExtractorHelper; +import org.schabi.newpipe.util.KeyboardUtil; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.ServiceHelper; @@ -670,31 +669,15 @@ public class SearchFragment extends BaseListFragment + * See also https://stackoverflow.com/q/1109022 + *

+ */ +public final class KeyboardUtil { + private KeyboardUtil() { + } + + public static void showKeyboard(final Activity activity, final EditText editText) { + if (activity == null || editText == null) { + return; + } + + if (editText.requestFocus()) { + final InputMethodManager imm = ContextCompat.getSystemService(activity, + InputMethodManager.class); + imm.showSoftInput(editText, InputMethodManager.SHOW_FORCED); + } + } + + public static void hideKeyboard(final Activity activity, final EditText editText) { + if (activity == null || editText == null) { + return; + } + + final InputMethodManager imm = ContextCompat.getSystemService(activity, + InputMethodManager.class); + imm.hideSoftInputFromWindow(editText.getWindowToken(), + InputMethodManager.RESULT_UNCHANGED_SHOWN); + + editText.clearFocus(); + } +} From 4a061f20edc95467673600ca387393f2fa90ff30 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 24 Dec 2021 21:32:13 +0100 Subject: [PATCH 064/119] Code cleanup --- .../newpipe/settings/SelectKioskFragment.java | 18 ------------------ .../settings/tabs/ChooseTabsFragment.java | 15 +++------------ app/src/main/res/layout/settings_layout.xml | 8 ++++---- app/src/main/res/xml/update_settings.xml | 1 - 4 files changed, 7 insertions(+), 35 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/SelectKioskFragment.java b/app/src/main/java/org/schabi/newpipe/settings/SelectKioskFragment.java index a766ee074..383390506 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SelectKioskFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SelectKioskFragment.java @@ -1,6 +1,5 @@ package org.schabi.newpipe.settings; -import android.content.DialogInterface; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -51,16 +50,11 @@ public class SelectKioskFragment extends DialogFragment { private SelectKioskAdapter selectKioskAdapter = null; private OnSelectedListener onSelectedListener = null; - private OnCancelListener onCancelListener = null; public void setOnSelectedListener(final OnSelectedListener listener) { onSelectedListener = listener; } - public void setOnCancelListener(final OnCancelListener listener) { - onCancelListener = listener; - } - /*////////////////////////////////////////////////////////////////////////// // Init //////////////////////////////////////////////////////////////////////////*/ @@ -91,14 +85,6 @@ public class SelectKioskFragment extends DialogFragment { // Handle actions //////////////////////////////////////////////////////////////////////////*/ - @Override - public void onCancel(@NonNull final DialogInterface dialogInterface) { - super.onCancel(dialogInterface); - if (onCancelListener != null) { - onCancelListener.onCancel(); - } - } - private void clickedItem(final SelectKioskAdapter.Entry entry) { if (onSelectedListener != null) { onSelectedListener.onKioskSelected(entry.serviceId, entry.kioskId, entry.kioskName); @@ -114,10 +100,6 @@ public class SelectKioskFragment extends DialogFragment { void onKioskSelected(int serviceId, String kioskId, String kioskName); } - public interface OnCancelListener { - void onCancel(); - } - private class SelectKioskAdapter extends RecyclerView.Adapter { private final List kioskList = new Vector<>(); diff --git a/app/src/main/java/org/schabi/newpipe/settings/tabs/ChooseTabsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/tabs/ChooseTabsFragment.java index 95f7f50ba..490e299bd 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/tabs/ChooseTabsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/tabs/ChooseTabsFragment.java @@ -44,8 +44,6 @@ import java.util.List; import static org.schabi.newpipe.settings.tabs.Tab.typeFrom; public class ChooseTabsFragment extends Fragment { - private static final int MENU_ITEM_RESTORE_ID = 123456; - private TabsManager tabsManager; private final List tabList = new ArrayList<>(); @@ -110,21 +108,14 @@ public class ChooseTabsFragment extends Fragment { @NonNull final MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); - final MenuItem restoreItem = menu.add(Menu.NONE, MENU_ITEM_RESTORE_ID, Menu.NONE, - R.string.restore_defaults); + final MenuItem restoreItem = menu.add(R.string.restore_defaults); restoreItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); restoreItem.setIcon(AppCompatResources.getDrawable(requireContext(), R.drawable.ic_settings_backup_restore)); - } - - @Override - public boolean onOptionsItemSelected(final MenuItem item) { - if (item.getItemId() == MENU_ITEM_RESTORE_ID) { + restoreItem.setOnMenuItemClickListener(ev -> { restoreDefaults(); return true; - } - - return super.onOptionsItemSelected(item); + }); } /*////////////////////////////////////////////////////////////////////////// diff --git a/app/src/main/res/layout/settings_layout.xml b/app/src/main/res/layout/settings_layout.xml index 33237d7b0..1b7b8b5e2 100644 --- a/app/src/main/res/layout/settings_layout.xml +++ b/app/src/main/res/layout/settings_layout.xml @@ -6,14 +6,14 @@ android:orientation="vertical" tools:context="org.schabi.newpipe.MainActivity"> + + - -
diff --git a/app/src/main/res/xml/update_settings.xml b/app/src/main/res/xml/update_settings.xml index ef121ec4e..a44555edf 100644 --- a/app/src/main/res/xml/update_settings.xml +++ b/app/src/main/res/xml/update_settings.xml @@ -1,7 +1,6 @@ Date: Fri, 24 Dec 2021 21:33:40 +0100 Subject: [PATCH 065/119] Added preference search "framework" --- .../preferencesearch/PreferenceParser.java | 201 ++++++++++++++++++ .../PreferenceSearchAdapter.java | 91 ++++++++ .../PreferenceSearchConfiguration.java | 163 ++++++++++++++ .../PreferenceSearchFragment.java | 116 ++++++++++ .../PreferenceSearchItem.java | 91 ++++++++ .../PreferenceSearchResultHighlighter.java | 125 +++++++++++ .../PreferenceSearchResultListener.java | 7 + .../preferencesearch/PreferenceSearcher.java | 36 ++++ .../preferencesearch/package-info.java | 10 + 9 files changed, 840 insertions(+) create mode 100644 app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java create mode 100644 app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchAdapter.java create mode 100644 app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java create mode 100644 app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java create mode 100644 app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchItem.java create mode 100644 app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultHighlighter.java create mode 100644 app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultListener.java create mode 100644 app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearcher.java create mode 100644 app/src/main/java/org/schabi/newpipe/settings/preferencesearch/package-info.java diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java new file mode 100644 index 000000000..1cf401892 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java @@ -0,0 +1,201 @@ +package org.schabi.newpipe.settings.preferencesearch; + +import android.content.Context; +import android.text.TextUtils; +import android.util.Log; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.preference.PreferenceManager; + +import org.xmlpull.v1.XmlPullParser; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * Parses the corresponding preference-file(s). + */ +class PreferenceParser { + private static final String TAG = "PreferenceParser"; + + private static final String NS_ANDROID = "http://schemas.android.com/apk/res/android"; + private static final String NS_SEARCH = "http://schemas.android.com/apk/preferencesearch"; + + private final Context context; + private final Map allPreferences; + private final PreferenceSearchConfiguration searchConfiguration; + + PreferenceParser( + final Context context, + final PreferenceSearchConfiguration searchConfiguration + ) { + this.context = context; + this.allPreferences = PreferenceManager.getDefaultSharedPreferences(context).getAll(); + this.searchConfiguration = searchConfiguration; + } + + public List parse( + final PreferenceSearchConfiguration.SearchIndexItem item + ) { + Objects.requireNonNull(item, "item can't be null"); + + final List results = new ArrayList<>(); + final XmlPullParser xpp = context.getResources().getXml(item.getResId()); + + try { + xpp.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); + xpp.setFeature(XmlPullParser.FEATURE_REPORT_NAMESPACE_ATTRIBUTES, true); + + final List breadcrumbs = new ArrayList<>(); + if (!TextUtils.isEmpty(item.getBreadcrumb())) { + breadcrumbs.add(item.getBreadcrumb()); + } + while (xpp.getEventType() != XmlPullParser.END_DOCUMENT) { + if (xpp.getEventType() == XmlPullParser.START_TAG) { + final PreferenceSearchItem result = parseSearchResult( + xpp, + joinBreadcrumbs(breadcrumbs), + item.getResId() + ); + + if (!searchConfiguration.getParserIgnoreElements().contains(xpp.getName()) + && result.hasData() + && !"true".equals(getAttribute(xpp, NS_SEARCH, "ignore"))) { + results.add(result); + } + if (searchConfiguration.getParserContainerElements().contains(xpp.getName())) { + breadcrumbs.add(result.getTitle() == null ? "" : result.getTitle()); + } + } else if (xpp.getEventType() == XmlPullParser.END_TAG + && searchConfiguration.getParserContainerElements() + .contains(xpp.getName())) { + breadcrumbs.remove(breadcrumbs.size() - 1); + } + + xpp.next(); + } + } catch (final Exception e) { + Log.w(TAG, "Failed to parse resid=" + item.getResId(), e); + } + return results; + } + + private String joinBreadcrumbs(final List breadcrumbs) { + return breadcrumbs.stream() + .filter(crumb -> !TextUtils.isEmpty(crumb)) + .reduce("", searchConfiguration.getBreadcrumbConcat()); + } + + private String getAttribute( + final XmlPullParser xpp, + @NonNull final String attribute + ) { + final String nsSearchAttr = getAttribute(xpp, NS_SEARCH, attribute); + if (nsSearchAttr != null) { + return nsSearchAttr; + } + return getAttribute(xpp, NS_ANDROID, attribute); + } + + private String getAttribute( + final XmlPullParser xpp, + @NonNull final String namespace, + @NonNull final String attribute + ) { + return xpp.getAttributeValue(namespace, attribute); + } + + private PreferenceSearchItem parseSearchResult( + final XmlPullParser xpp, + final String breadcrumbs, + final int searchIndexItemResId + ) { + final String key = readString(getAttribute(xpp, "key")); + final String[] entries = readStringArray(getAttribute(xpp, "entries")); + final String[] entryValues = readStringArray(getAttribute(xpp, "entryValues")); + + return new PreferenceSearchItem( + key, + tryFillInPreferenceValue( + readString(getAttribute(xpp, "title")), + key, + entries, + entryValues), + tryFillInPreferenceValue( + readString(getAttribute(xpp, "summary")), + key, + entries, + entryValues), + TextUtils.join(",", entries), + readString(getAttribute(xpp, NS_SEARCH, "keywords")), + breadcrumbs, + searchIndexItemResId + ); + } + + private String[] readStringArray(@Nullable final String s) { + if (s == null) { + return new String[0]; + } + if (s.startsWith("@")) { + try { + return context.getResources().getStringArray(Integer.parseInt(s.substring(1))); + } catch (final Exception e) { + Log.w(TAG, "Unable to readStringArray from '" + s + "'", e); + } + } + return new String[0]; + } + + private String readString(@Nullable final String s) { + if (s == null) { + return ""; + } + if (s.startsWith("@")) { + try { + return context.getString(Integer.parseInt(s.substring(1))); + } catch (final Exception e) { + Log.w(TAG, "Unable to readString from '" + s + "'", e); + } + } + return s; + } + + private String tryFillInPreferenceValue( + @Nullable final String s, + @Nullable final String key, + final String[] entries, + final String[] entryValues + ) { + if (s == null) { + return ""; + } + if (key == null) { + return s; + } + + // Resolve value + Object prefValue = allPreferences.get(key); + if (prefValue == null) { + return s; + } + + /* + * Resolve ListPreference values + * + * entryValues = Values/Keys that are saved + * entries = Actual human readable names + */ + if (entries.length > 0 && entryValues.length == entries.length) { + final int entryIndex = Arrays.asList(entryValues).indexOf(prefValue); + if (entryIndex != -1) { + prefValue = entries[entryIndex]; + } + } + + return String.format(s, prefValue.toString()); + } +} diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchAdapter.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchAdapter.java new file mode 100644 index 000000000..527a4a595 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchAdapter.java @@ -0,0 +1,91 @@ +package org.schabi.newpipe.settings.preferencesearch; + +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import org.schabi.newpipe.R; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +class PreferenceSearchAdapter + extends RecyclerView.Adapter { + private List dataset = new ArrayList<>(); + private Consumer onItemClickListener; + + @NonNull + @Override + public PreferenceSearchAdapter.PreferenceViewHolder onCreateViewHolder( + @NonNull final ViewGroup parent, + final int viewType + ) { + return new PreferenceViewHolder( + LayoutInflater + .from(parent.getContext()) + .inflate(R.layout.settings_preferencesearch_list_item_result, parent, false)); + } + + @Override + public void onBindViewHolder( + @NonNull final PreferenceSearchAdapter.PreferenceViewHolder holder, + final int position + ) { + final PreferenceSearchItem item = dataset.get(position); + + holder.title.setText(item.getTitle()); + + if (TextUtils.isEmpty(item.getSummary())) { + holder.summary.setVisibility(View.GONE); + } else { + holder.summary.setVisibility(View.VISIBLE); + holder.summary.setText(item.getSummary()); + } + + if (TextUtils.isEmpty(item.getBreadcrumbs())) { + holder.breadcrumbs.setVisibility(View.GONE); + } else { + holder.breadcrumbs.setVisibility(View.VISIBLE); + holder.breadcrumbs.setText(item.getBreadcrumbs()); + } + + holder.itemView.setOnClickListener(v -> { + if (onItemClickListener != null) { + onItemClickListener.accept(item); + } + }); + } + + void setContent(final List items) { + dataset = new ArrayList<>(items); + this.notifyDataSetChanged(); + } + + @Override + public int getItemCount() { + return dataset.size(); + } + + void setOnItemClickListener(final Consumer onItemClickListener) { + this.onItemClickListener = onItemClickListener; + } + + static class PreferenceViewHolder extends RecyclerView.ViewHolder { + final TextView title; + final TextView summary; + final TextView breadcrumbs; + + PreferenceViewHolder(final View v) { + super(v); + title = v.findViewById(R.id.title); + summary = v.findViewById(R.id.summary); + breadcrumbs = v.findViewById(R.id.breadcrumbs); + } + } +} diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java new file mode 100644 index 000000000..b4d1c8985 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java @@ -0,0 +1,163 @@ +package org.schabi.newpipe.settings.preferencesearch; + +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +import androidx.annotation.XmlRes; +import androidx.preference.PreferenceCategory; +import androidx.preference.PreferenceScreen; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.function.BinaryOperator; +import java.util.stream.Stream; + +public class PreferenceSearchConfiguration { + private final ArrayList itemsToIndex = new ArrayList<>(); + + private BinaryOperator breadcrumbConcat = + (s1, s2) -> TextUtils.isEmpty(s1) ? s2 : (s1 + " > " + s2); + + private PreferenceSearchFunction searcher = + (itemStream, keyword) -> + itemStream + // Filter the items by the keyword + .filter(item -> item.getAllRelevantSearchFields().stream() + .filter(str -> !TextUtils.isEmpty(str)) + .anyMatch(str -> + str.toLowerCase().contains(keyword.toLowerCase()))) + // Limit the search results + .limit(100); + + private final List parserIgnoreElements = Arrays.asList( + PreferenceCategory.class.getSimpleName()); + private final List parserContainerElements = Arrays.asList( + PreferenceCategory.class.getSimpleName(), + PreferenceScreen.class.getSimpleName()); + + + public void setBreadcrumbConcat(final BinaryOperator breadcrumbConcat) { + this.breadcrumbConcat = Objects.requireNonNull(breadcrumbConcat); + } + + public void setSearcher(final PreferenceSearchFunction searcher) { + this.searcher = Objects.requireNonNull(searcher); + } + + /** + * Adds a new file to the index. + * + * @param resId The preference file to index + * @return SearchIndexItem + */ + public SearchIndexItem index(@XmlRes final int resId) { + final SearchIndexItem item = new SearchIndexItem(resId, this); + itemsToIndex.add(item); + return item; + } + + List getFiles() { + return itemsToIndex; + } + + public BinaryOperator getBreadcrumbConcat() { + return breadcrumbConcat; + } + + public PreferenceSearchFunction getSearchMatcher() { + return searcher; + } + + public List getParserIgnoreElements() { + return parserIgnoreElements; + } + + public List getParserContainerElements() { + return parserContainerElements; + } + + /** + * Adds a given R.xml resource to the search index. + */ + public static final class SearchIndexItem implements Parcelable { + private String breadcrumb = ""; + @XmlRes + private final int resId; + private final PreferenceSearchConfiguration searchConfiguration; + + /** + * Includes the given R.xml resource in the index. + * + * @param resId The resource to index + * @param searchConfiguration The configuration for the search + */ + private SearchIndexItem( + @XmlRes final int resId, + final PreferenceSearchConfiguration searchConfiguration + ) { + this.resId = resId; + this.searchConfiguration = searchConfiguration; + } + + /** + * Adds a breadcrumb. + * + * @param breadcrumb The breadcrumb to add + * @return For chaining + */ + @SuppressWarnings("HiddenField") + public SearchIndexItem withBreadcrumb(final String breadcrumb) { + this.breadcrumb = + searchConfiguration.getBreadcrumbConcat().apply(this.breadcrumb, breadcrumb); + return this; + } + + @XmlRes + int getResId() { + return resId; + } + + String getBreadcrumb() { + return breadcrumb; + } + + public static final Creator CREATOR = new Creator<>() { + @Override + public SearchIndexItem createFromParcel(final Parcel in) { + return new SearchIndexItem(in); + } + + @Override + public SearchIndexItem[] newArray(final int size) { + return new SearchIndexItem[size]; + } + }; + + private SearchIndexItem(final Parcel parcel) { + this.breadcrumb = parcel.readString(); + this.resId = parcel.readInt(); + this.searchConfiguration = null; + } + + @Override + public void writeToParcel(final Parcel dest, final int flags) { + dest.writeString(this.breadcrumb); + dest.writeInt(this.resId); + } + + @Override + public int describeContents() { + return 0; + } + } + + @FunctionalInterface + public interface PreferenceSearchFunction { + Stream search( + Stream allAvailable, + String keyword); + } +} diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java new file mode 100644 index 000000000..a90d1084e --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java @@ -0,0 +1,116 @@ +package org.schabi.newpipe.settings.preferencesearch; + +import android.os.Bundle; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import org.schabi.newpipe.R; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * Displays the search results. + */ +public class PreferenceSearchFragment extends Fragment { + public static final String NAME = PreferenceSearchFragment.class.getSimpleName(); + + private final PreferenceSearchConfiguration searchConfiguration; + + private final PreferenceSearcher searcher; + private SearchViewHolder viewHolder; + private PreferenceSearchAdapter adapter; + + public PreferenceSearchFragment(final PreferenceSearchConfiguration searchConfiguration) { + this.searchConfiguration = searchConfiguration; + this.searcher = new PreferenceSearcher(searchConfiguration); + } + + @Override + public void onCreate(@Nullable final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + final PreferenceParser parser = + new PreferenceParser( + getContext(), + searchConfiguration); + + searchConfiguration.getFiles().stream() + .map(parser::parse) + .forEach(searcher::add); + } + + @Nullable + @Override + public View onCreateView( + @NonNull final LayoutInflater inflater, + @Nullable final ViewGroup container, + @Nullable final Bundle savedInstanceState + ) { + final View rootView = + inflater.inflate(R.layout.settings_preferencesearch_fragment, container, false); + + viewHolder = new SearchViewHolder(rootView); + viewHolder.recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + + adapter = new PreferenceSearchAdapter(); + adapter.setOnItemClickListener(this::onItemClicked); + viewHolder.recyclerView.setAdapter(adapter); + + return rootView; + } + + public void updateSearchResults(final String keyword) { + if (adapter == null) { + return; + } + + final List results = + !TextUtils.isEmpty(keyword) + ? searcher.searchFor(keyword) + : new ArrayList<>(); + + adapter.setContent(new ArrayList<>(results)); + + setEmptyViewShown(!TextUtils.isEmpty(keyword) && results.isEmpty()); + } + + private void setEmptyViewShown(final boolean shown) { + viewHolder.emptyStateView.setVisibility(shown ? View.VISIBLE : View.GONE); + viewHolder.recyclerView.setVisibility(shown ? View.GONE : View.VISIBLE); + } + + public void onItemClicked(final PreferenceSearchItem item) { + if (!(getActivity() instanceof PreferenceSearchResultListener)) { + throw new ClassCastException( + getActivity().toString() + " must implement SearchPreferenceResultListener"); + } + + ((PreferenceSearchResultListener) getActivity()).onSearchResultClicked(item); + } + + @Override + public void onDestroy() { + searcher.close(); + super.onDestroy(); + } + + private static class SearchViewHolder { + private final RecyclerView recyclerView; + private final View emptyStateView; + + SearchViewHolder(final View root) { + recyclerView = Objects.requireNonNull(root.findViewById(R.id.list)); + emptyStateView = Objects.requireNonNull(root.findViewById(R.id.empty_state_view)); + } + } +} diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchItem.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchItem.java new file mode 100644 index 000000000..3030a78bb --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchItem.java @@ -0,0 +1,91 @@ +package org.schabi.newpipe.settings.preferencesearch; + +import androidx.annotation.NonNull; + +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +/** + * Represents a preference-item inside the search. + */ +public class PreferenceSearchItem { + @NonNull + private final String key; + @NonNull + private final String title; + @NonNull + private final String summary; + @NonNull + private final String entries; + @NonNull + private final String keywords; + @NonNull + private final String breadcrumbs; + private final int searchIndexItemResId; + + public PreferenceSearchItem( + @NonNull final String key, + @NonNull final String title, + @NonNull final String summary, + @NonNull final String entries, + @NonNull final String keywords, + @NonNull final String breadcrumbs, + final int searchIndexItemResId + ) { + this.key = Objects.requireNonNull(key); + this.title = Objects.requireNonNull(title); + this.summary = Objects.requireNonNull(summary); + this.entries = Objects.requireNonNull(entries); + this.keywords = Objects.requireNonNull(keywords); + this.breadcrumbs = Objects.requireNonNull(breadcrumbs); + this.searchIndexItemResId = searchIndexItemResId; + } + + public String getKey() { + return key; + } + + public String getTitle() { + return title; + } + + public String getSummary() { + return summary; + } + + public String getEntries() { + return entries; + } + + public String getBreadcrumbs() { + return breadcrumbs; + } + + public String getKeywords() { + return keywords; + } + + public int getSearchIndexItemResId() { + return searchIndexItemResId; + } + + boolean hasData() { + return !key.isEmpty() && !title.isEmpty(); + } + + public List getAllRelevantSearchFields() { + return Arrays.asList( + getTitle(), + getSummary(), + getEntries(), + getBreadcrumbs(), + getKeywords()); + } + + + @Override + public String toString() { + return "PreferenceItem: " + title + " " + summary + " " + key; + } +} diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultHighlighter.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultHighlighter.java new file mode 100644 index 000000000..4ddb2caa8 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultHighlighter.java @@ -0,0 +1,125 @@ +package org.schabi.newpipe.settings.preferencesearch; + +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.RippleDrawable; +import android.os.Build; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; +import android.util.TypedValue; + +import androidx.appcompat.content.res.AppCompatResources; +import androidx.preference.Preference; +import androidx.preference.PreferenceFragmentCompat; +import androidx.preference.PreferenceGroup; +import androidx.recyclerview.widget.RecyclerView; + +import org.schabi.newpipe.R; + + +public final class PreferenceSearchResultHighlighter { + private static final String TAG = "PrefSearchResHighlter"; + + private PreferenceSearchResultHighlighter() { + } + + /** + * Highlight the specified preference. + * + * @param item + * @param prefsFragment + */ + public static void highlight( + final PreferenceSearchItem item, + final PreferenceFragmentCompat prefsFragment + ) { + new Handler(Looper.getMainLooper()).post(() -> doHighlight(item, prefsFragment)); + } + + private static void doHighlight( + final PreferenceSearchItem item, + final PreferenceFragmentCompat prefsFragment + ) { + final Preference prefResult = prefsFragment.findPreference(item.getKey()); + + if (prefResult == null) { + Log.w(TAG, "Preference '" + item.getKey() + "' not found on '" + prefsFragment + "'"); + return; + } + + final RecyclerView recyclerView = prefsFragment.getListView(); + final RecyclerView.Adapter adapter = recyclerView.getAdapter(); + if (adapter instanceof PreferenceGroup.PreferencePositionCallback) { + final int position = ((PreferenceGroup.PreferencePositionCallback) adapter) + .getPreferenceAdapterPosition(prefResult); + if (position != RecyclerView.NO_POSITION) { + recyclerView.scrollToPosition(position); + recyclerView.postDelayed(() -> { + final RecyclerView.ViewHolder holder = + recyclerView.findViewHolderForAdapterPosition(position); + if (holder != null) { + final Drawable background = holder.itemView.getBackground(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP + && background instanceof RippleDrawable) { + showRippleAnimation((RippleDrawable) background); + return; + } + } + highlightFallback(prefsFragment, prefResult); + }, 150); + return; + } + } + highlightFallback(prefsFragment, prefResult); + } + + /** + * Alternative highlighting (shows an → arrow in front of the setting)if ripple does not work. + * + * @param prefsFragment + * @param prefResult + */ + private static void highlightFallback( + final PreferenceFragmentCompat prefsFragment, + final Preference prefResult + ) { + // Get primary color from text for highlight icon + final TypedValue typedValue = new TypedValue(); + final Resources.Theme theme = prefsFragment.getActivity().getTheme(); + theme.resolveAttribute(android.R.attr.textColorPrimary, typedValue, true); + final TypedArray arr = prefsFragment.getActivity() + .obtainStyledAttributes( + typedValue.data, + new int[]{android.R.attr.textColorPrimary}); + final int color = arr.getColor(0, 0xffE53935); + arr.recycle(); + + // Show highlight icon + final Drawable oldIcon = prefResult.getIcon(); + final boolean oldSpaceReserved = prefResult.isIconSpaceReserved(); + final Drawable highlightIcon = + AppCompatResources.getDrawable( + prefsFragment.requireContext(), + R.drawable.ic_play_arrow); + highlightIcon.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)); + prefResult.setIcon(highlightIcon); + + prefsFragment.scrollToPreference(prefResult); + + new Handler(Looper.getMainLooper()).postDelayed(() -> { + prefResult.setIcon(oldIcon); + prefResult.setIconSpaceReserved(oldSpaceReserved); + }, 1000); + } + + private static void showRippleAnimation(final RippleDrawable rippleDrawable) { + rippleDrawable.setState( + new int[]{android.R.attr.state_pressed, android.R.attr.state_enabled}); + new Handler(Looper.getMainLooper()) + .postDelayed(() -> rippleDrawable.setState(new int[]{}), 1000); + } +} diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultListener.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultListener.java new file mode 100644 index 000000000..1f0636454 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultListener.java @@ -0,0 +1,7 @@ +package org.schabi.newpipe.settings.preferencesearch; + +import androidx.annotation.NonNull; + +public interface PreferenceSearchResultListener { + void onSearchResultClicked(@NonNull PreferenceSearchItem result); +} diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearcher.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearcher.java new file mode 100644 index 000000000..f9427a1ca --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearcher.java @@ -0,0 +1,36 @@ +package org.schabi.newpipe.settings.preferencesearch; + +import android.text.TextUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +class PreferenceSearcher implements AutoCloseable { + private final List allEntries = new ArrayList<>(); + + private final PreferenceSearchConfiguration configuration; + + PreferenceSearcher(final PreferenceSearchConfiguration configuration) { + this.configuration = configuration; + } + + void add(final List items) { + allEntries.addAll(items); + } + + List searchFor(final String keyword) { + if (TextUtils.isEmpty(keyword)) { + return new ArrayList<>(); + } + + return configuration.getSearchMatcher() + .search(allEntries.stream(), keyword) + .collect(Collectors.toList()); + } + + @Override + public void close() { + allEntries.clear(); + } +} diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/package-info.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/package-info.java new file mode 100644 index 000000000..00929235e --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/package-info.java @@ -0,0 +1,10 @@ +/** + * Contains classes for searching inside the preferences. + *
+ * This code is based on + * ByteHamster/SearchPreference + * (MIT license) but was heavily modified/refactored for our use. + * + * @author litetex + */ +package org.schabi.newpipe.settings.preferencesearch; From 07fb319e886f8bee02a4d1de96ecd2185999efa0 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 24 Dec 2021 21:35:15 +0100 Subject: [PATCH 066/119] Applied code changes for preference search framework --- .../settings/AppearanceSettingsFragment.java | 2 +- .../settings/BasePreferenceFragment.java | 5 + .../settings/ContentSettingsFragment.java | 8 +- .../settings/DownloadSettingsFragment.java | 2 +- .../settings/HistorySettingsFragment.java | 2 +- .../settings/MainSettingsFragment.java | 43 +++- .../settings/NotificationSettingsFragment.kt | 2 +- .../newpipe/settings/SettingsActivity.java | 206 +++++++++++++++++- .../settings/SettingsResourceRegistry.java | 151 +++++++++++++ .../settings/UpdateSettingsFragment.java | 2 +- .../settings/VideoAudioSettingsFragment.java | 2 +- 11 files changed, 408 insertions(+), 17 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/settings/SettingsResourceRegistry.java diff --git a/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java index 4bc5a210e..e08562908 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java @@ -17,7 +17,7 @@ public class AppearanceSettingsFragment extends BasePreferenceFragment { @Override public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) { - addPreferencesFromResource(R.xml.appearance_settings); + addPreferencesFromResourceRegistry(); final String themeKey = getString(R.string.theme_key); // the key of the active theme when settings were opened (or recreated after theme change) diff --git a/app/src/main/java/org/schabi/newpipe/settings/BasePreferenceFragment.java b/app/src/main/java/org/schabi/newpipe/settings/BasePreferenceFragment.java index a745861ad..619579f3a 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/BasePreferenceFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/BasePreferenceFragment.java @@ -28,6 +28,11 @@ public abstract class BasePreferenceFragment extends PreferenceFragmentCompat { super.onCreate(savedInstanceState); } + protected void addPreferencesFromResourceRegistry() { + addPreferencesFromResource( + SettingsResourceRegistry.getInstance().getPreferencesResId(this.getClass())); + } + @Override public void onViewCreated(@NonNull final View rootView, @Nullable final Bundle savedInstanceState) { diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java index 1c8eb5cd2..d79ea0cd5 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java @@ -1,5 +1,8 @@ package org.schabi.newpipe.settings; +import static org.schabi.newpipe.extractor.utils.Utils.isBlank; +import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; + import android.app.Activity; import android.content.Context; import android.content.Intent; @@ -38,9 +41,6 @@ import java.util.Date; import java.util.Locale; import java.util.Objects; -import static org.schabi.newpipe.extractor.utils.Utils.isBlank; -import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; - public class ContentSettingsFragment extends BasePreferenceFragment { private static final String ZIP_MIME_TYPE = "application/zip"; @@ -70,7 +70,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment { importExportDataPathKey = getString(R.string.import_export_data_path); youtubeRestrictedModeEnabledKey = getString(R.string.youtube_restricted_mode_enabled); - addPreferencesFromResource(R.xml.content_settings); + addPreferencesFromResourceRegistry(); final Preference importDataPreference = requirePreference(R.string.import_data); importDataPreference.setOnPreferenceClickListener((Preference p) -> { diff --git a/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java index 681aee409..fe327e1b5 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java @@ -54,7 +54,7 @@ public class DownloadSettingsFragment extends BasePreferenceFragment { @Override public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) { - addPreferencesFromResource(R.xml.download_settings); + addPreferencesFromResourceRegistry(); downloadPathVideoPreference = getString(R.string.download_path_video_key); downloadPathAudioPreference = getString(R.string.download_path_audio_key); diff --git a/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java index 33e0ba16b..868618110 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java @@ -29,7 +29,7 @@ public class HistorySettingsFragment extends BasePreferenceFragment { @Override public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) { - addPreferencesFromResource(R.xml.history_settings); + addPreferencesFromResourceRegistry(); cacheWipeKey = getString(R.string.metadata_cache_wipe_key); viewsHistoryClearKey = getString(R.string.clear_views_history_key); diff --git a/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java index 12599b828..6cd165861 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java @@ -1,7 +1,11 @@ package org.schabi.newpipe.settings; import android.os.Bundle; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import androidx.annotation.NonNull; import androidx.preference.Preference; import org.schabi.newpipe.App; @@ -12,10 +16,15 @@ import org.schabi.newpipe.R; public class MainSettingsFragment extends BasePreferenceFragment { public static final boolean DEBUG = MainActivity.DEBUG; + private SettingsActivity settingsActivity; + @Override public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) { - addPreferencesFromResource(R.xml.main_settings); + addPreferencesFromResourceRegistry(); + setHasOptionsMenu(true); // Otherwise onCreateOptionsMenu is not called + + // Check if the app is updatable if (!CheckForNewAppVersion.isReleaseApk(App.getApp())) { final Preference update = findPreference(getString(R.string.update_pref_screen_key)); @@ -24,4 +33,36 @@ public class MainSettingsFragment extends BasePreferenceFragment { defaultPreferences.edit().putBoolean(getString(R.string.update_app_key), false).apply(); } } + + @Override + public void onCreateOptionsMenu( + @NonNull final Menu menu, + @NonNull final MenuInflater inflater + ) { + super.onCreateOptionsMenu(menu, inflater); + + // -- Link settings activity and register menu -- + settingsActivity = (SettingsActivity) getActivity(); + + inflater.inflate(R.menu.menu_settings_main_fragment, menu); + + final MenuItem menuSearchItem = menu.getItem(0); + + settingsActivity.setMenuSearchItem(menuSearchItem); + + menuSearchItem.setOnMenuItemClickListener(ev -> { + settingsActivity.setSearchActive(true); + return true; + }); + } + + @Override + public void onDestroy() { + // Unlink activity so that we don't get memory problems + if (settingsActivity != null) { + settingsActivity.setMenuSearchItem(null); + settingsActivity = null; + } + super.onDestroy(); + } } diff --git a/app/src/main/java/org/schabi/newpipe/settings/NotificationSettingsFragment.kt b/app/src/main/java/org/schabi/newpipe/settings/NotificationSettingsFragment.kt index e03aa4074..6bea8b69e 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/NotificationSettingsFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/settings/NotificationSettingsFragment.kt @@ -7,7 +7,7 @@ import org.schabi.newpipe.R class NotificationSettingsFragment : BasePreferenceFragment() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { - addPreferencesFromResource(R.xml.notification_settings) + addPreferencesFromResourceRegistry() if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { val colorizePref: Preference? = findPreference(getString(R.string.notification_colorize_key)) diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java index 02e2538c5..787740cc2 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java @@ -1,22 +1,42 @@ package org.schabi.newpipe.settings; +import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; + import android.os.Bundle; +import android.util.Log; import android.view.Menu; import android.view.MenuItem; +import android.view.View; +import android.widget.EditText; +import androidx.annotation.IdRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; +import com.jakewharton.rxbinding4.widget.RxTextView; + +import org.schabi.newpipe.App; +import org.schabi.newpipe.CheckForNewAppVersion; +import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; import org.schabi.newpipe.databinding.SettingsLayoutBinding; +import org.schabi.newpipe.settings.preferencesearch.PreferenceSearchConfiguration; +import org.schabi.newpipe.settings.preferencesearch.PreferenceSearchFragment; +import org.schabi.newpipe.settings.preferencesearch.PreferenceSearchItem; +import org.schabi.newpipe.settings.preferencesearch.PreferenceSearchResultHighlighter; +import org.schabi.newpipe.settings.preferencesearch.PreferenceSearchResultListener; import org.schabi.newpipe.util.DeviceUtils; +import org.schabi.newpipe.util.KeyboardUtil; import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.views.FocusOverlayView; -import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; +import java.util.concurrent.TimeUnit; /* * Created by Christian Schabesberger on 31.08.15. @@ -39,7 +59,23 @@ import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; */ public class SettingsActivity extends AppCompatActivity - implements BasePreferenceFragment.OnPreferenceStartFragmentCallback { + implements + BasePreferenceFragment.OnPreferenceStartFragmentCallback, + PreferenceSearchResultListener { + private static final String TAG = "SettingsActivity"; + private static final boolean DEBUG = MainActivity.DEBUG; + + @IdRes + private static final int FRAGMENT_HOLDER_ID = R.id.settings_fragment_holder; + + private PreferenceSearchFragment searchFragment; + + @Nullable + private MenuItem menuSearchItem; + + private View searchContainer; + private EditText searchEditText; + @Override protected void onCreate(final Bundle savedInstanceBundle) { setTheme(ThemeHelper.getSettingsThemeStyle(this)); @@ -49,6 +85,7 @@ public class SettingsActivity extends AppCompatActivity final SettingsLayoutBinding settingsLayoutBinding = SettingsLayoutBinding.inflate(getLayoutInflater()); setContentView(settingsLayoutBinding.getRoot()); + initSearch(settingsLayoutBinding); setSupportActionBar(settingsLayoutBinding.settingsToolbarLayout.toolbar); @@ -78,6 +115,12 @@ public class SettingsActivity extends AppCompatActivity public boolean onOptionsItemSelected(final MenuItem item) { final int id = item.getItemId(); if (id == android.R.id.home) { + // Check if the search is active and if so: Close it + if (isSearchActive()) { + setSearchActive(false); + return true; + } + if (getSupportFragmentManager().getBackStackEntryCount() == 0) { finish(); } else { @@ -91,14 +134,165 @@ public class SettingsActivity extends AppCompatActivity @Override public boolean onPreferenceStartFragment(final PreferenceFragmentCompat caller, final Preference preference) { - final Fragment fragment = Fragment - .instantiate(this, preference.getFragment(), preference.getExtras()); + showSettingsFragment(instantiateFragment(preference.getFragment())); + return true; + } + + private Fragment instantiateFragment(@NonNull final String className) { + return getSupportFragmentManager() + .getFragmentFactory() + .instantiate(this.getClassLoader(), className); + } + + private void showSettingsFragment(final Fragment fragment) { getSupportFragmentManager().beginTransaction() .setCustomAnimations(R.animator.custom_fade_in, R.animator.custom_fade_out, R.animator.custom_fade_in, R.animator.custom_fade_out) - .replace(R.id.settings_fragment_holder, fragment) + .replace(FRAGMENT_HOLDER_ID, fragment) .addToBackStack(null) .commit(); - return true; } + + @Override + protected void onDestroy() { + setMenuSearchItem(null); + super.onDestroy(); + } + + /*////////////////////////////////////////////////////////////////////////// + // Search + //////////////////////////////////////////////////////////////////////////*/ + //region Search + + private void initSearch(final SettingsLayoutBinding settingsLayoutBinding) { + searchContainer = + settingsLayoutBinding.settingsToolbarLayout.toolbar + .findViewById(R.id.toolbar_search_container); + + // Configure input field for search + searchEditText = searchContainer.findViewById(R.id.toolbar_search_edit_text); + RxTextView.textChanges(searchEditText) + // Wait some time after the last input before actually searching + .debounce(200, TimeUnit.MILLISECONDS) + .subscribe(v -> runOnUiThread(() -> onSearchChanged())); + + // Configure clear button + searchContainer.findViewById(R.id.toolbar_search_clear) + .setOnClickListener(ev -> resetSearchText()); + + // Build search configuration using SettingsResourceRegistry + prepareSearchConfig(); + + final PreferenceSearchConfiguration config = new PreferenceSearchConfiguration(); + SettingsResourceRegistry.getInstance().getAllEntries().stream() + .filter(SettingsResourceRegistry.SettingRegistryEntry::isSearchable) + .map(SettingsResourceRegistry.SettingRegistryEntry::getPreferencesResId) + .forEach(config::index); + + searchFragment = new PreferenceSearchFragment(config); + } + + private void prepareSearchConfig() { + // Check if the update settings should be available + if (!CheckForNewAppVersion.isReleaseApk(App.getApp())) { + SettingsResourceRegistry.getInstance() + .getEntryByPreferencesResId(R.xml.update_settings) + .setSearchable(false); + } + } + + public void setMenuSearchItem(final MenuItem menuSearchItem) { + this.menuSearchItem = menuSearchItem; + } + + public void setSearchActive(final boolean active) { + // Ignore if search is already in correct state + if (isSearchActive() == active) { + return; + } + + if (DEBUG) { + Log.d(TAG, "setSearchActive called active=" + active); + } + + searchContainer.setVisibility(active ? View.VISIBLE : View.GONE); + if (menuSearchItem != null) { + menuSearchItem.setVisible(!active); + } + + final FragmentManager fm = getSupportFragmentManager(); + if (active) { + fm.beginTransaction() + .add(FRAGMENT_HOLDER_ID, searchFragment, PreferenceSearchFragment.NAME) + .addToBackStack(PreferenceSearchFragment.NAME) + .commit(); + } else if (searchFragment != null) { + fm.beginTransaction().remove(searchFragment).commit(); + fm.popBackStack( + PreferenceSearchFragment.NAME, + FragmentManager.POP_BACK_STACK_INCLUSIVE); + + KeyboardUtil.hideKeyboard(this, searchEditText); + } + + resetSearchText(); + } + + private void resetSearchText() { + searchEditText.setText(""); + } + + private boolean isSearchActive() { + return searchContainer.getVisibility() == View.VISIBLE; + } + + private void onSearchChanged() { + if (!isSearchActive()) { + return; + } + + if (searchFragment != null) { + searchFragment.updateSearchResults(this.searchEditText.getText().toString()); + } + } + + @Override + public void onSearchResultClicked(@NonNull final PreferenceSearchItem result) { + if (DEBUG) { + Log.d(TAG, "onSearchResultClicked called result=" + result); + } + + // Hide the search + setSearchActive(false); + + // -- Highlight the result -- + // Find out which fragment class we need + final Class targetedFragmentClass = + SettingsResourceRegistry.getInstance() + .getFragmentClass(result.getSearchIndexItemResId()); + + if (targetedFragmentClass == null) { + // This should never happen + Log.w(TAG, "Unable to locate fragment class for resId=" + + result.getSearchIndexItemResId()); + return; + } + + // Check if the currentFragment is the one which contains the result + Fragment currentFragment = + getSupportFragmentManager().findFragmentById(FRAGMENT_HOLDER_ID); + if (!targetedFragmentClass.equals(currentFragment.getClass())) { + // If it's not the correct one display the correct one + currentFragment = instantiateFragment(targetedFragmentClass.getName()); + showSettingsFragment(currentFragment); + } + + // Run the highlighting + if (currentFragment instanceof PreferenceFragmentCompat) { + PreferenceSearchResultHighlighter + .highlight(result, (PreferenceFragmentCompat) currentFragment); + } + } + + //endregion } diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingsResourceRegistry.java b/app/src/main/java/org/schabi/newpipe/settings/SettingsResourceRegistry.java new file mode 100644 index 000000000..c4db9f93d --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/settings/SettingsResourceRegistry.java @@ -0,0 +1,151 @@ +package org.schabi.newpipe.settings; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.XmlRes; +import androidx.fragment.app.Fragment; + +import org.schabi.newpipe.R; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +/** + * A registry that contains information about SettingsFragments. + *
+ * includes: + *
    + *
  • Class of the SettingsFragment
  • + *
  • XML-Resource
  • + *
  • ...
  • + *
+ * + * E.g. used by the preference search. + */ +public final class SettingsResourceRegistry { + + private static final SettingsResourceRegistry INSTANCE = new SettingsResourceRegistry(); + + private final Set registeredEntries = new HashSet<>(); + + private SettingsResourceRegistry() { + add(MainSettingsFragment.class, R.xml.main_settings).setSearchable(false); + + add(AppearanceSettingsFragment.class, R.xml.appearance_settings); + add(ContentSettingsFragment.class, R.xml.content_settings); + add(DownloadSettingsFragment.class, R.xml.download_settings); + add(HistorySettingsFragment.class, R.xml.history_settings); + add(NotificationSettingsFragment.class, R.xml.notification_settings); + add(UpdateSettingsFragment.class, R.xml.update_settings); + add(VideoAudioSettingsFragment.class, R.xml.video_audio_settings); + } + + private SettingRegistryEntry add( + @NonNull final Class fragmentClass, + @XmlRes final int preferencesResId + ) { + final SettingRegistryEntry entry = + new SettingRegistryEntry(fragmentClass, preferencesResId); + this.registeredEntries.add(entry); + return entry; + } + + @Nullable + public SettingRegistryEntry getEntryByFragmentClass( + final Class fragmentClass + ) { + Objects.requireNonNull(fragmentClass); + return registeredEntries.stream() + .filter(e -> Objects.equals(e.getFragmentClass(), fragmentClass)) + .findFirst() + .orElse(null); + } + + @Nullable + public SettingRegistryEntry getEntryByPreferencesResId(@XmlRes final int preferencesResId) { + return registeredEntries.stream() + .filter(e -> Objects.equals(e.getPreferencesResId(), preferencesResId)) + .findFirst() + .orElse(null); + } + + public int getPreferencesResId(@NonNull final Class fragmentClass) { + final SettingRegistryEntry entry = getEntryByFragmentClass(fragmentClass); + if (entry == null) { + return -1; + } + return entry.getPreferencesResId(); + } + + @Nullable + public Class getFragmentClass(@XmlRes final int preferencesResId) { + final SettingRegistryEntry entry = getEntryByPreferencesResId(preferencesResId); + if (entry == null) { + return null; + } + return entry.getFragmentClass(); + } + + public Set getAllEntries() { + return new HashSet<>(registeredEntries); + } + + public static SettingsResourceRegistry getInstance() { + return INSTANCE; + } + + + public static class SettingRegistryEntry { + @NonNull + private final Class fragmentClass; + @XmlRes + private final int preferencesResId; + + private boolean searchable = true; + + public SettingRegistryEntry( + @NonNull final Class fragmentClass, + @XmlRes final int preferencesResId + ) { + this.fragmentClass = Objects.requireNonNull(fragmentClass); + this.preferencesResId = preferencesResId; + } + + @SuppressWarnings("HiddenField") + public SettingRegistryEntry setSearchable(final boolean searchable) { + this.searchable = searchable; + return this; + } + + public Class getFragmentClass() { + return fragmentClass; + } + + public int getPreferencesResId() { + return preferencesResId; + } + + public boolean isSearchable() { + return searchable; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final SettingRegistryEntry that = (SettingRegistryEntry) o; + return getPreferencesResId() == that.getPreferencesResId() + && getFragmentClass().equals(that.getFragmentClass()); + } + + @Override + public int hashCode() { + return Objects.hash(getFragmentClass(), getPreferencesResId()); + } + } +} diff --git a/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java index bc183d08a..04bad3815 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java @@ -38,7 +38,7 @@ public class UpdateSettingsFragment extends BasePreferenceFragment { @Override public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) { - addPreferencesFromResource(R.xml.update_settings); + addPreferencesFromResourceRegistry(); findPreference(getString(R.string.update_app_key)) .setOnPreferenceChangeListener(updatePreferenceChange); diff --git a/app/src/main/java/org/schabi/newpipe/settings/VideoAudioSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/VideoAudioSettingsFragment.java index c0d274fe0..039f00c1d 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/VideoAudioSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/VideoAudioSettingsFragment.java @@ -23,7 +23,7 @@ public class VideoAudioSettingsFragment extends BasePreferenceFragment { @Override public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) { - addPreferencesFromResource(R.xml.video_audio_settings); + addPreferencesFromResourceRegistry(); updateSeekOptions(); From 8fc935b09db56f597b824e248f445cd7b30579d4 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 24 Dec 2021 21:35:41 +0100 Subject: [PATCH 067/119] Added resource files Forgot to commit them before... --- .../settings_preferencesearch_fragment.xml | 49 +++++++++++++++++++ ...ings_preferencesearch_list_item_result.xml | 36 ++++++++++++++ .../res/menu/menu_settings_main_fragment.xml | 11 +++++ 3 files changed, 96 insertions(+) create mode 100644 app/src/main/res/layout/settings_preferencesearch_fragment.xml create mode 100644 app/src/main/res/layout/settings_preferencesearch_list_item_result.xml create mode 100644 app/src/main/res/menu/menu_settings_main_fragment.xml diff --git a/app/src/main/res/layout/settings_preferencesearch_fragment.xml b/app/src/main/res/layout/settings_preferencesearch_fragment.xml new file mode 100644 index 000000000..b8aaa60f6 --- /dev/null +++ b/app/src/main/res/layout/settings_preferencesearch_fragment.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/settings_preferencesearch_list_item_result.xml b/app/src/main/res/layout/settings_preferencesearch_list_item_result.xml new file mode 100644 index 000000000..2e20f274c --- /dev/null +++ b/app/src/main/res/layout/settings_preferencesearch_list_item_result.xml @@ -0,0 +1,36 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_settings_main_fragment.xml b/app/src/main/res/menu/menu_settings_main_fragment.xml new file mode 100644 index 000000000..fbe3b4e09 --- /dev/null +++ b/app/src/main/res/menu/menu_settings_main_fragment.xml @@ -0,0 +1,11 @@ + + + + + From 22db4175f37205f650df7a67f3017705404eda2b Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 24 Dec 2021 21:37:04 +0100 Subject: [PATCH 068/119] Moved reset-reCAPTCHA-cookie to cache tab and made it read-only so that the search works as expected --- .../settings/ContentSettingsFragment.java | 16 ---------------- .../settings/HistorySettingsFragment.java | 17 +++++++++++++++++ app/src/main/res/xml/content_settings.xml | 7 ------- app/src/main/res/xml/history_settings.xml | 7 +++++++ 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java index d79ea0cd5..47458ad3f 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java @@ -24,7 +24,6 @@ import org.schabi.newpipe.DownloaderImpl; import org.schabi.newpipe.NewPipeDatabase; import org.schabi.newpipe.R; import org.schabi.newpipe.error.ErrorUtil; -import org.schabi.newpipe.error.ReCaptchaActivity; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.localization.ContentCountry; import org.schabi.newpipe.extractor.localization.Localization; @@ -105,21 +104,6 @@ public class ContentSettingsFragment extends BasePreferenceFragment { .getPreferredContentCountry(requireContext()); initialLanguage = defaultPreferences.getString(getString(R.string.app_language_key), "en"); - final Preference clearCookiePref = requirePreference(R.string.clear_cookie_key); - clearCookiePref.setOnPreferenceClickListener(preference -> { - defaultPreferences.edit() - .putString(getString(R.string.recaptcha_cookies_key), "").apply(); - DownloaderImpl.getInstance().setCookie(ReCaptchaActivity.RECAPTCHA_COOKIES_KEY, ""); - Toast.makeText(getActivity(), R.string.recaptcha_cookies_cleared, - Toast.LENGTH_SHORT).show(); - clearCookiePref.setVisible(false); - return true; - }); - - if (defaultPreferences.getString(getString(R.string.recaptcha_cookies_key), "").isEmpty()) { - clearCookiePref.setVisible(false); - } - findPreference(getString(R.string.download_thumbnail_key)).setOnPreferenceChangeListener( (preference, newValue) -> { PicassoHelper.setShouldLoadImages((Boolean) newValue); diff --git a/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java index 868618110..86e651e2b 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java @@ -8,9 +8,11 @@ import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.preference.Preference; +import org.schabi.newpipe.DownloaderImpl; import org.schabi.newpipe.R; import org.schabi.newpipe.error.ErrorInfo; import org.schabi.newpipe.error.ErrorUtil; +import org.schabi.newpipe.error.ReCaptchaActivity; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.InfoCache; @@ -37,6 +39,21 @@ public class HistorySettingsFragment extends BasePreferenceFragment { searchHistoryClearKey = getString(R.string.clear_search_history_key); recordManager = new HistoryRecordManager(getActivity()); disposables = new CompositeDisposable(); + + final Preference clearCookiePref = requirePreference(R.string.clear_cookie_key); + clearCookiePref.setOnPreferenceClickListener(preference -> { + defaultPreferences.edit() + .putString(getString(R.string.recaptcha_cookies_key), "").apply(); + DownloaderImpl.getInstance().setCookie(ReCaptchaActivity.RECAPTCHA_COOKIES_KEY, ""); + Toast.makeText(getActivity(), R.string.recaptcha_cookies_cleared, + Toast.LENGTH_SHORT).show(); + clearCookiePref.setEnabled(false); + return true; + }); + + if (defaultPreferences.getString(getString(R.string.recaptcha_cookies_key), "").isEmpty()) { + clearCookiePref.setEnabled(false); + } } @Override diff --git a/app/src/main/res/xml/content_settings.xml b/app/src/main/res/xml/content_settings.xml index 23b782ffd..e754b3a30 100644 --- a/app/src/main/res/xml/content_settings.xml +++ b/app/src/main/res/xml/content_settings.xml @@ -128,13 +128,6 @@ app:singleLineTitle="false" app:iconSpaceReserved="false" /> - - + +
From 7fc0a3841a206e0b82f887e7da82cb47eff18734 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 24 Dec 2021 21:51:44 +0100 Subject: [PATCH 069/119] Fine tuning --- .../main/java/org/schabi/newpipe/settings/SettingsActivity.java | 2 ++ .../preferencesearch/PreferenceSearchResultHighlighter.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java index 787740cc2..88c8fcba5 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java @@ -226,6 +226,8 @@ public class SettingsActivity extends AppCompatActivity .add(FRAGMENT_HOLDER_ID, searchFragment, PreferenceSearchFragment.NAME) .addToBackStack(PreferenceSearchFragment.NAME) .commit(); + + KeyboardUtil.showKeyboard(this, searchEditText); } else if (searchFragment != null) { fm.beginTransaction().remove(searchFragment).commit(); fm.popBackStack( diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultHighlighter.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultHighlighter.java index 4ddb2caa8..e48ca28ce 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultHighlighter.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultHighlighter.java @@ -70,7 +70,7 @@ public final class PreferenceSearchResultHighlighter { } } highlightFallback(prefsFragment, prefResult); - }, 150); + }, 200); return; } } From 52542e04e82e36a4c201b29c98b6bef11e81fe2d Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sat, 25 Dec 2021 00:06:06 +0100 Subject: [PATCH 070/119] Added fuzzy searching + Some minor code refactoring --- .../newpipe/settings/SettingsActivity.java | 9 ++ .../PreferenceFuzzySearchFunction.java | 121 ++++++++++++++ .../PreferenceSearchConfiguration.java | 11 +- .../PreferenceSearchFragment.java | 2 +- .../similarity/FuzzyScore.java | 148 ++++++++++++++++++ 5 files changed, 280 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceFuzzySearchFunction.java create mode 100644 app/src/main/java/org/schabi/newpipe/settings/preferencesearch/similarity/FuzzyScore.java diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java index 88c8fcba5..1f917e771 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java @@ -111,6 +111,15 @@ public class SettingsActivity extends AppCompatActivity return super.onCreateOptionsMenu(menu); } + @Override + public void onBackPressed() { + if (isSearchActive()) { + setSearchActive(false); + return; + } + super.onBackPressed(); + } + @Override public boolean onOptionsItemSelected(final MenuItem item) { final int id = item.getItemId(); diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceFuzzySearchFunction.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceFuzzySearchFunction.java new file mode 100644 index 000000000..48f507a41 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceFuzzySearchFunction.java @@ -0,0 +1,121 @@ +package org.schabi.newpipe.settings.preferencesearch; + +import android.text.TextUtils; + +import androidx.annotation.NonNull; + +import org.schabi.newpipe.settings.preferencesearch.similarity.FuzzyScore; + +import java.util.Comparator; +import java.util.Locale; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Stream; + +public class PreferenceFuzzySearchFunction + implements PreferenceSearchConfiguration.PreferenceSearchFunction { + + private static final FuzzyScore FUZZY_SCORE = new FuzzyScore(Locale.ROOT); + + @Override + public Stream search( + final Stream allAvailable, + final String keyword + ) { + final float maxScore = (keyword.length() + 1) * 3 - 2; // First can't get +2 bonus score + + return allAvailable + // General search + // Check all fields if anyone contains something that kind of matches the keyword + .map(item -> new FuzzySearchGeneralDTO(item, keyword)) + .filter(dto -> dto.getScore() / maxScore >= 0.3f) + .map(FuzzySearchGeneralDTO::getItem) + // Specific search - Used for determining order of search results + // Calculate a score based on specific search fields + .map(item -> new FuzzySearchSpecificDTO(item, keyword)) + .sorted(Comparator.comparing(FuzzySearchSpecificDTO::getScore).reversed()) + .map(FuzzySearchSpecificDTO::getItem) + // Limit the amount of search results + .limit(20); + } + + private float computeFuzzyScore( + @NonNull final PreferenceSearchItem item, + @NonNull final Function resolver, + @NonNull final String keyword + ) { + return FUZZY_SCORE.fuzzyScore(resolver.apply(item), keyword); + } + + static class FuzzySearchGeneralDTO { + private final PreferenceSearchItem item; + private final float score; + + FuzzySearchGeneralDTO( + final PreferenceSearchItem item, + final String keyword) { + this.item = item; + this.score = FUZZY_SCORE.fuzzyScore( + TextUtils.join(";", item.getAllRelevantSearchFields()), + keyword); + } + + public PreferenceSearchItem getItem() { + return item; + } + + public float getScore() { + return score; + } + } + + static class FuzzySearchSpecificDTO { + private static final Map, Float> WEIGHT_MAP = Map.of( + // The user will most likely look for the title -> prioritize it + PreferenceSearchItem::getTitle, 1.5f, + // The summary is also important as it usually contains a larger desc + // Example: Searching for '4k' → 'show higher resolution' is shown + PreferenceSearchItem::getSummary, 1f, + // Entries are also important as they provide all known/possible values + // Example: Searching where the resolution can be changed to 720p + PreferenceSearchItem::getEntries, 1f + ); + + private final PreferenceSearchItem item; + private final float score; + + FuzzySearchSpecificDTO( + final PreferenceSearchItem item, + final String keyword) { + this.item = item; + + float attributeScoreSum = 0; + int countOfAttributesWithScore = 0; + for (final Map.Entry, Float> we + : WEIGHT_MAP.entrySet()) { + final String valueToProcess = we.getKey().apply(item); + if (valueToProcess.isEmpty()) { + continue; + } + + attributeScoreSum += + FUZZY_SCORE.fuzzyScore(valueToProcess, keyword) * we.getValue(); + countOfAttributesWithScore++; + } + + if (countOfAttributesWithScore != 0) { + this.score = attributeScoreSum / countOfAttributesWithScore; + } else { + this.score = 0; + } + } + + public PreferenceSearchItem getItem() { + return item; + } + + public float getScore() { + return score; + } + } +} diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java index b4d1c8985..37b98035a 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java @@ -21,16 +21,7 @@ public class PreferenceSearchConfiguration { private BinaryOperator breadcrumbConcat = (s1, s2) -> TextUtils.isEmpty(s1) ? s2 : (s1 + " > " + s2); - private PreferenceSearchFunction searcher = - (itemStream, keyword) -> - itemStream - // Filter the items by the keyword - .filter(item -> item.getAllRelevantSearchFields().stream() - .filter(str -> !TextUtils.isEmpty(str)) - .anyMatch(str -> - str.toLowerCase().contains(keyword.toLowerCase()))) - // Limit the search results - .limit(100); + private PreferenceSearchFunction searcher = new PreferenceFuzzySearchFunction(); private final List parserIgnoreElements = Arrays.asList( PreferenceCategory.class.getSimpleName()); diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java index a90d1084e..d9a17da16 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java @@ -81,7 +81,7 @@ public class PreferenceSearchFragment extends Fragment { adapter.setContent(new ArrayList<>(results)); - setEmptyViewShown(!TextUtils.isEmpty(keyword) && results.isEmpty()); + setEmptyViewShown(results.isEmpty()); } private void setEmptyViewShown(final boolean shown) { diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/similarity/FuzzyScore.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/similarity/FuzzyScore.java new file mode 100644 index 000000000..4ab6bf60a --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/similarity/FuzzyScore.java @@ -0,0 +1,148 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.schabi.newpipe.settings.preferencesearch.similarity; + +import java.util.Locale; + +/** + * A matching algorithm that is similar to the searching algorithms implemented in editors such + * as Sublime Text, TextMate, Atom and others. + * + *

+ * One point is given for every matched character. Subsequent matches yield two bonus points. + * A higher score indicates a higher similarity. + *

+ * + *

+ * This code has been adapted from Apache Commons Lang 3.3. + *

+ * + * @since 1.0 + * + * Note: This class was forked from + * + * apache/commons-text (8cfdafc) FuzzyScore.java + * + */ +public class FuzzyScore { + + /** + * Locale used to change the case of text. + */ + private final Locale locale; + + + /** + * This returns a {@link Locale}-specific {@link FuzzyScore}. + * + * @param locale The string matching logic is case insensitive. + A {@link Locale} is necessary to normalize both Strings to lower case. + * @throws IllegalArgumentException + * This is thrown if the {@link Locale} parameter is {@code null}. + */ + public FuzzyScore(final Locale locale) { + if (locale == null) { + throw new IllegalArgumentException("Locale must not be null"); + } + this.locale = locale; + } + + /** + * Find the Fuzzy Score which indicates the similarity score between two + * Strings. + * + *
+     * score.fuzzyScore(null, null)                          = IllegalArgumentException
+     * score.fuzzyScore("not null", null)                    = IllegalArgumentException
+     * score.fuzzyScore(null, "not null")                    = IllegalArgumentException
+     * score.fuzzyScore("", "")                              = 0
+     * score.fuzzyScore("Workshop", "b")                     = 0
+     * score.fuzzyScore("Room", "o")                         = 1
+     * score.fuzzyScore("Workshop", "w")                     = 1
+     * score.fuzzyScore("Workshop", "ws")                    = 2
+     * score.fuzzyScore("Workshop", "wo")                    = 4
+     * score.fuzzyScore("Apache Software Foundation", "asf") = 3
+     * 
+ * + * @param term a full term that should be matched against, must not be null + * @param query the query that will be matched against a term, must not be + * null + * @return result score + * @throws IllegalArgumentException if the term or query is {@code null} + */ + public Integer fuzzyScore(final CharSequence term, final CharSequence query) { + if (term == null || query == null) { + throw new IllegalArgumentException("CharSequences must not be null"); + } + + // fuzzy logic is case insensitive. We normalize the Strings to lower + // case right from the start. Turning characters to lower case + // via Character.toLowerCase(char) is unfortunately insufficient + // as it does not accept a locale. + final String termLowerCase = term.toString().toLowerCase(locale); + final String queryLowerCase = query.toString().toLowerCase(locale); + + // the resulting score + int score = 0; + + // the position in the term which will be scanned next for potential + // query character matches + int termIndex = 0; + + // index of the previously matched character in the term + int previousMatchingCharacterIndex = Integer.MIN_VALUE; + + for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++) { + final char queryChar = queryLowerCase.charAt(queryIndex); + + boolean termCharacterMatchFound = false; + for (; termIndex < termLowerCase.length() + && !termCharacterMatchFound; termIndex++) { + final char termChar = termLowerCase.charAt(termIndex); + + if (queryChar == termChar) { + // simple character matches result in one point + score++; + + // subsequent character matches further improve + // the score. + if (previousMatchingCharacterIndex + 1 == termIndex) { + score += 2; + } + + previousMatchingCharacterIndex = termIndex; + + // we can leave the nested loop. Every character in the + // query can match at most one character in the term. + termCharacterMatchFound = true; + } + } + } + + return score; + } + + /** + * Gets the locale. + * + * @return The locale + */ + public Locale getLocale() { + return locale; + } + +} From 0f45c69388a2da0a465dff19813ec0e09face67f Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sun, 26 Dec 2021 23:46:22 +0100 Subject: [PATCH 071/119] Code cleanup + indexing improvements * Removed unused method * Only index all settings once -> Saves performance * Fixed some SonarLint reported problems --- .../newpipe/settings/SettingsActivity.java | 23 +++++++++----- .../PreferenceFuzzySearchFunction.java | 12 +------- .../preferencesearch/PreferenceParser.java | 4 +-- .../PreferenceSearchConfiguration.java | 2 +- .../PreferenceSearchFragment.java | 30 ++++--------------- .../preferencesearch/PreferenceSearcher.java | 9 +++--- 6 files changed, 29 insertions(+), 51 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java index 1f917e771..92bc21c9d 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java @@ -26,11 +26,13 @@ import org.schabi.newpipe.CheckForNewAppVersion; import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; import org.schabi.newpipe.databinding.SettingsLayoutBinding; +import org.schabi.newpipe.settings.preferencesearch.PreferenceParser; import org.schabi.newpipe.settings.preferencesearch.PreferenceSearchConfiguration; import org.schabi.newpipe.settings.preferencesearch.PreferenceSearchFragment; import org.schabi.newpipe.settings.preferencesearch.PreferenceSearchItem; import org.schabi.newpipe.settings.preferencesearch.PreferenceSearchResultHighlighter; import org.schabi.newpipe.settings.preferencesearch.PreferenceSearchResultListener; +import org.schabi.newpipe.settings.preferencesearch.PreferenceSearcher; import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.KeyboardUtil; import org.schabi.newpipe.util.ThemeHelper; @@ -58,9 +60,8 @@ import java.util.concurrent.TimeUnit; * along with NewPipe. If not, see . */ -public class SettingsActivity extends AppCompatActivity - implements - BasePreferenceFragment.OnPreferenceStartFragmentCallback, +public class SettingsActivity extends AppCompatActivity implements + PreferenceFragmentCompat.OnPreferenceStartFragmentCallback, PreferenceSearchResultListener { private static final String TAG = "SettingsActivity"; private static final boolean DEBUG = MainActivity.DEBUG; @@ -165,6 +166,7 @@ public class SettingsActivity extends AppCompatActivity @Override protected void onDestroy() { setMenuSearchItem(null); + searchFragment = null; super.onDestroy(); } @@ -183,26 +185,33 @@ public class SettingsActivity extends AppCompatActivity RxTextView.textChanges(searchEditText) // Wait some time after the last input before actually searching .debounce(200, TimeUnit.MILLISECONDS) - .subscribe(v -> runOnUiThread(() -> onSearchChanged())); + .subscribe(v -> runOnUiThread(this::onSearchChanged)); // Configure clear button searchContainer.findViewById(R.id.toolbar_search_clear) .setOnClickListener(ev -> resetSearchText()); - // Build search configuration using SettingsResourceRegistry prepareSearchConfig(); + // Build search configuration using SettingsResourceRegistry final PreferenceSearchConfiguration config = new PreferenceSearchConfiguration(); SettingsResourceRegistry.getInstance().getAllEntries().stream() .filter(SettingsResourceRegistry.SettingRegistryEntry::isSearchable) .map(SettingsResourceRegistry.SettingRegistryEntry::getPreferencesResId) .forEach(config::index); - searchFragment = new PreferenceSearchFragment(config); + // Build search items + final PreferenceParser parser = new PreferenceParser(getApplicationContext(), config); + final PreferenceSearcher searcher = new PreferenceSearcher(config); + config.getFiles().stream() + .map(parser::parse) + .forEach(searcher::add); + + searchFragment = new PreferenceSearchFragment(searcher); } private void prepareSearchConfig() { - // Check if the update settings should be available + // Check if the update settings are available if (!CheckForNewAppVersion.isReleaseApk(App.getApp())) { SettingsResourceRegistry.getInstance() .getEntryByPreferencesResId(R.xml.update_settings) diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceFuzzySearchFunction.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceFuzzySearchFunction.java index 48f507a41..88ef790c8 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceFuzzySearchFunction.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceFuzzySearchFunction.java @@ -2,8 +2,6 @@ package org.schabi.newpipe.settings.preferencesearch; import android.text.TextUtils; -import androidx.annotation.NonNull; - import org.schabi.newpipe.settings.preferencesearch.similarity.FuzzyScore; import java.util.Comparator; @@ -22,7 +20,7 @@ public class PreferenceFuzzySearchFunction final Stream allAvailable, final String keyword ) { - final float maxScore = (keyword.length() + 1) * 3 - 2; // First can't get +2 bonus score + final int maxScore = (keyword.length() + 1) * 3 - 2; // First can't get +2 bonus score return allAvailable // General search @@ -39,14 +37,6 @@ public class PreferenceFuzzySearchFunction .limit(20); } - private float computeFuzzyScore( - @NonNull final PreferenceSearchItem item, - @NonNull final Function resolver, - @NonNull final String keyword - ) { - return FUZZY_SCORE.fuzzyScore(resolver.apply(item), keyword); - } - static class FuzzySearchGeneralDTO { private final PreferenceSearchItem item; private final float score; diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java index 1cf401892..b52daeb5b 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java @@ -18,7 +18,7 @@ import java.util.Objects; /** * Parses the corresponding preference-file(s). */ -class PreferenceParser { +public class PreferenceParser { private static final String TAG = "PreferenceParser"; private static final String NS_ANDROID = "http://schemas.android.com/apk/res/android"; @@ -28,7 +28,7 @@ class PreferenceParser { private final Map allPreferences; private final PreferenceSearchConfiguration searchConfiguration; - PreferenceParser( + public PreferenceParser( final Context context, final PreferenceSearchConfiguration searchConfiguration ) { diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java index 37b98035a..1c9dc99aa 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java @@ -50,7 +50,7 @@ public class PreferenceSearchConfiguration { return item; } - List getFiles() { + public List getFiles() { return itemsToIndex; } diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java index d9a17da16..1b1d627c1 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java @@ -24,29 +24,15 @@ import java.util.Objects; public class PreferenceSearchFragment extends Fragment { public static final String NAME = PreferenceSearchFragment.class.getSimpleName(); - private final PreferenceSearchConfiguration searchConfiguration; - private final PreferenceSearcher searcher; + private SearchViewHolder viewHolder; private PreferenceSearchAdapter adapter; - public PreferenceSearchFragment(final PreferenceSearchConfiguration searchConfiguration) { - this.searchConfiguration = searchConfiguration; - this.searcher = new PreferenceSearcher(searchConfiguration); - } - - @Override - public void onCreate(@Nullable final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - final PreferenceParser parser = - new PreferenceParser( - getContext(), - searchConfiguration); - - searchConfiguration.getFiles().stream() - .map(parser::parse) - .forEach(searcher::add); + public PreferenceSearchFragment( + final PreferenceSearcher searcher + ) { + this.searcher = searcher; } @Nullable @@ -98,12 +84,6 @@ public class PreferenceSearchFragment extends Fragment { ((PreferenceSearchResultListener) getActivity()).onSearchResultClicked(item); } - @Override - public void onDestroy() { - searcher.close(); - super.onDestroy(); - } - private static class SearchViewHolder { private final RecyclerView recyclerView; private final View emptyStateView; diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearcher.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearcher.java index f9427a1ca..87dd11693 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearcher.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearcher.java @@ -6,16 +6,16 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; -class PreferenceSearcher implements AutoCloseable { +public class PreferenceSearcher { private final List allEntries = new ArrayList<>(); private final PreferenceSearchConfiguration configuration; - PreferenceSearcher(final PreferenceSearchConfiguration configuration) { + public PreferenceSearcher(final PreferenceSearchConfiguration configuration) { this.configuration = configuration; } - void add(final List items) { + public void add(final List items) { allEntries.addAll(items); } @@ -29,8 +29,7 @@ class PreferenceSearcher implements AutoCloseable { .collect(Collectors.toList()); } - @Override - public void close() { + public void clear() { allEntries.clear(); } } From d59314801c035ea1292e5c685437ff0b09982c54 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Mon, 27 Dec 2021 18:57:17 +0100 Subject: [PATCH 072/119] Code rework --- .../preferencesearch/PreferenceParser.java | 4 +-- .../PreferenceSearchItem.java | 33 ++++++++++++------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java index b52daeb5b..afd2c1b4f 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java @@ -5,6 +5,7 @@ import android.text.TextUtils; import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.XmlRes; import androidx.preference.PreferenceManager; import org.xmlpull.v1.XmlPullParser; @@ -111,7 +112,7 @@ public class PreferenceParser { private PreferenceSearchItem parseSearchResult( final XmlPullParser xpp, final String breadcrumbs, - final int searchIndexItemResId + @XmlRes final int searchIndexItemResId ) { final String key = readString(getAttribute(xpp, "key")); final String[] entries = readStringArray(getAttribute(xpp, "entries")); @@ -130,7 +131,6 @@ public class PreferenceParser { entries, entryValues), TextUtils.join(",", entries), - readString(getAttribute(xpp, NS_SEARCH, "keywords")), breadcrumbs, searchIndexItemResId ); diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchItem.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchItem.java index 3030a78bb..52935ef8e 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchItem.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchItem.java @@ -1,6 +1,7 @@ package org.schabi.newpipe.settings.preferencesearch; import androidx.annotation.NonNull; +import androidx.annotation.XmlRes; import java.util.Arrays; import java.util.List; @@ -10,18 +11,35 @@ import java.util.Objects; * Represents a preference-item inside the search. */ public class PreferenceSearchItem { + /** + * Key of the setting/preference. E.g. used inside {@link android.content.SharedPreferences}. + */ @NonNull private final String key; + /** + * Title of the setting, e.g. 'Default resolution' or 'Show higher resolutions'. + */ @NonNull private final String title; + /** + * Summary of the setting, e.g. '480p' or 'Only some devices can play 2k/4k'. + */ @NonNull private final String summary; + /** + * Possible entries of the setting, e.g. 480p,720p,... + */ @NonNull private final String entries; - @NonNull - private final String keywords; + /** + * Breadcrumbs - a hint where the setting is located e.g. 'Video and Audio > Player' + */ @NonNull private final String breadcrumbs; + /** + * The xml-resource where this item was found/built from. + */ + @XmlRes private final int searchIndexItemResId; public PreferenceSearchItem( @@ -29,15 +47,13 @@ public class PreferenceSearchItem { @NonNull final String title, @NonNull final String summary, @NonNull final String entries, - @NonNull final String keywords, @NonNull final String breadcrumbs, - final int searchIndexItemResId + @XmlRes final int searchIndexItemResId ) { this.key = Objects.requireNonNull(key); this.title = Objects.requireNonNull(title); this.summary = Objects.requireNonNull(summary); this.entries = Objects.requireNonNull(entries); - this.keywords = Objects.requireNonNull(keywords); this.breadcrumbs = Objects.requireNonNull(breadcrumbs); this.searchIndexItemResId = searchIndexItemResId; } @@ -62,10 +78,6 @@ public class PreferenceSearchItem { return breadcrumbs; } - public String getKeywords() { - return keywords; - } - public int getSearchIndexItemResId() { return searchIndexItemResId; } @@ -79,8 +91,7 @@ public class PreferenceSearchItem { getTitle(), getSummary(), getEntries(), - getBreadcrumbs(), - getKeywords()); + getBreadcrumbs()); } From 6b23df06592ccbe52534d43448310125685c9eaa Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Wed, 29 Dec 2021 18:12:33 +0100 Subject: [PATCH 073/119] Made debug settings searchable (debug only) * Consolidated main-setttings into a single file * Debug settings are only enabled in the DEBUG build * Moved LeakCanary (debug) specific stuff into a small class that's only shipped with the debug build * Other minor fixes --- .../settings/DebugSettingsFragment.java | 50 ++++++++++++++++--- .../settings/MainSettingsFragment.java | 12 +++-- .../newpipe/settings/SettingsActivity.java | 7 +++ .../settings/SettingsResourceRegistry.java | 5 +- app/src/main/res/values/strings.xml | 1 + .../{debug => main}/res/xml/main_settings.xml | 0 app/src/release/res/xml/main_settings.xml | 49 ------------------ 7 files changed, 61 insertions(+), 63 deletions(-) rename app/src/{debug => main}/java/org/schabi/newpipe/settings/DebugSettingsFragment.java (54%) rename app/src/{debug => main}/res/xml/main_settings.xml (100%) delete mode 100644 app/src/release/res/xml/main_settings.xml diff --git a/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java similarity index 54% rename from app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsFragment.java rename to app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java index f48be553f..710a440e1 100644 --- a/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java @@ -1,5 +1,6 @@ package org.schabi.newpipe.settings; +import android.content.Intent; import android.os.Bundle; import androidx.preference.Preference; @@ -10,13 +11,15 @@ import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.util.PicassoHelper; -import leakcanary.LeakCanary; +import java.util.Optional; public class DebugSettingsFragment extends BasePreferenceFragment { @Override public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) { - addPreferencesFromResource(R.xml.debug_settings); + addPreferencesFromResourceRegistry(); + final Preference allowHeapDumpingPreference + = findPreference(getString(R.string.allow_heap_dumping_key)); final Preference showMemoryLeaksPreference = findPreference(getString(R.string.show_memory_leaks_key)); final Preference showImageIndicatorsPreference @@ -28,16 +31,29 @@ public class DebugSettingsFragment extends BasePreferenceFragment { final Preference createErrorNotificationPreference = findPreference(getString(R.string.create_error_notification_key)); + assert allowHeapDumpingPreference != null; assert showMemoryLeaksPreference != null; assert showImageIndicatorsPreference != null; assert crashTheAppPreference != null; assert showErrorSnackbarPreference != null; assert createErrorNotificationPreference != null; - showMemoryLeaksPreference.setOnPreferenceClickListener(preference -> { - startActivity(LeakCanary.INSTANCE.newLeakDisplayActivityIntent()); - return true; - }); + final Optional optPDLeakCanary = getBVLeakCanary(); + + allowHeapDumpingPreference.setEnabled(optPDLeakCanary.isPresent()); + showMemoryLeaksPreference.setEnabled(optPDLeakCanary.isPresent()); + + if (optPDLeakCanary.isPresent()) { + final DebugSettingsBVLeakCanaryAPI pdLeakCanary = optPDLeakCanary.get(); + + showMemoryLeaksPreference.setOnPreferenceClickListener(preference -> { + startActivity(pdLeakCanary.getNewLeakDisplayActivityIntent()); + return true; + }); + } else { + allowHeapDumpingPreference.setSummary(R.string.leak_canary_not_available); + showMemoryLeaksPreference.setSummary(R.string.leak_canary_not_available); + } showImageIndicatorsPreference.setOnPreferenceChangeListener((preference, newValue) -> { PicassoHelper.setIndicatorsEnabled((Boolean) newValue); @@ -60,4 +76,26 @@ public class DebugSettingsFragment extends BasePreferenceFragment { return true; }); } + + private Optional getBVLeakCanary() { + try { + // Try to find the implementation of the LeakCanary API + return Optional.of((DebugSettingsBVLeakCanaryAPI) + Class.forName(DebugSettingsBVLeakCanaryAPI.IMPL_CLASS).newInstance()); + } catch (final ClassNotFoundException + | IllegalAccessException | java.lang.InstantiationException e) { + return Optional.empty(); + } + } + + /** + * Build variant dependent leak canary API for this fragment. + * Why is LeakCanary not used directly? Because it can't be assured + */ + public interface DebugSettingsBVLeakCanaryAPI { + String IMPL_CLASS = + "org.schabi.newpipe.settings.DebugSettingsBVLeakCanary"; + + Intent getNewLeakDisplayActivityIntent(); + } } diff --git a/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java index 6cd165861..d7fb559d6 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java @@ -6,7 +6,6 @@ import android.view.MenuInflater; import android.view.MenuItem; import androidx.annotation.NonNull; -import androidx.preference.Preference; import org.schabi.newpipe.App; import org.schabi.newpipe.CheckForNewAppVersion; @@ -26,12 +25,17 @@ public class MainSettingsFragment extends BasePreferenceFragment { // Check if the app is updatable if (!CheckForNewAppVersion.isReleaseApk(App.getApp())) { - final Preference update - = findPreference(getString(R.string.update_pref_screen_key)); - getPreferenceScreen().removePreference(update); + getPreferenceScreen().removePreference( + findPreference(getString(R.string.update_pref_screen_key))); defaultPreferences.edit().putBoolean(getString(R.string.update_app_key), false).apply(); } + + // Hide debug preferences in RELEASE build variant + if (!DEBUG) { + getPreferenceScreen().removePreference( + findPreference(getString(R.string.debug_pref_screen_key))); + } } @Override diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java index 92bc21c9d..25d22dc9f 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java @@ -217,6 +217,13 @@ public class SettingsActivity extends AppCompatActivity implements .getEntryByPreferencesResId(R.xml.update_settings) .setSearchable(false); } + + // Hide debug preferences in RELEASE build variant + if (DEBUG) { + SettingsResourceRegistry.getInstance() + .getEntryByPreferencesResId(R.xml.debug_settings) + .setSearchable(true); + } } public void setMenuSearchItem(final MenuItem menuSearchItem) { diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingsResourceRegistry.java b/app/src/main/java/org/schabi/newpipe/settings/SettingsResourceRegistry.java index c4db9f93d..c4751abea 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SettingsResourceRegistry.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SettingsResourceRegistry.java @@ -1,7 +1,6 @@ package org.schabi.newpipe.settings; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.annotation.XmlRes; import androidx.fragment.app.Fragment; @@ -34,6 +33,7 @@ public final class SettingsResourceRegistry { add(AppearanceSettingsFragment.class, R.xml.appearance_settings); add(ContentSettingsFragment.class, R.xml.content_settings); + add(DebugSettingsFragment.class, R.xml.debug_settings).setSearchable(false); add(DownloadSettingsFragment.class, R.xml.download_settings); add(HistorySettingsFragment.class, R.xml.history_settings); add(NotificationSettingsFragment.class, R.xml.notification_settings); @@ -51,7 +51,6 @@ public final class SettingsResourceRegistry { return entry; } - @Nullable public SettingRegistryEntry getEntryByFragmentClass( final Class fragmentClass ) { @@ -62,7 +61,6 @@ public final class SettingsResourceRegistry { .orElse(null); } - @Nullable public SettingRegistryEntry getEntryByPreferencesResId(@XmlRes final int preferencesResId) { return registeredEntries.stream() .filter(e -> Objects.equals(e.getPreferencesResId(), preferencesResId)) @@ -78,7 +76,6 @@ public final class SettingsResourceRegistry { return entry.getPreferencesResId(); } - @Nullable public Class getFragmentClass(@XmlRes final int preferencesResId) { final SettingRegistryEntry entry = getEntryByPreferencesResId(preferencesResId); if (entry == null) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f7ad41ba8..64ed6980b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -441,6 +441,7 @@ Captions Modify player caption text scale and background styles. Requires app restart to take effect + LeakCanary is not available Memory leak monitoring may cause the app to become unresponsive when heap dumping Show memory leaks Report out-of-lifecycle errors diff --git a/app/src/debug/res/xml/main_settings.xml b/app/src/main/res/xml/main_settings.xml similarity index 100% rename from app/src/debug/res/xml/main_settings.xml rename to app/src/main/res/xml/main_settings.xml diff --git a/app/src/release/res/xml/main_settings.xml b/app/src/release/res/xml/main_settings.xml deleted file mode 100644 index 1d5241102..000000000 --- a/app/src/release/res/xml/main_settings.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - From 658168eb8d97e54ac23f1dfdccb7fd8ec2786035 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Wed, 29 Dec 2021 18:29:46 +0100 Subject: [PATCH 074/119] Fixed some sonar warnings --- .../newpipe/settings/DebugSettingsFragment.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java index 710a440e1..915531779 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java @@ -11,9 +11,12 @@ import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.util.PicassoHelper; +import java.lang.reflect.InvocationTargetException; import java.util.Optional; public class DebugSettingsFragment extends BasePreferenceFragment { + private static final String DUMMY = "Dummy"; + @Override public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) { addPreferencesFromResourceRegistry(); @@ -61,18 +64,18 @@ public class DebugSettingsFragment extends BasePreferenceFragment { }); crashTheAppPreference.setOnPreferenceClickListener(preference -> { - throw new RuntimeException(); + throw new RuntimeException(DUMMY); }); showErrorSnackbarPreference.setOnPreferenceClickListener(preference -> { ErrorUtil.showUiErrorSnackbar(DebugSettingsFragment.this, - "Dummy", new RuntimeException("Dummy")); + DUMMY, new RuntimeException(DUMMY)); return true; }); createErrorNotificationPreference.setOnPreferenceClickListener(preference -> { ErrorUtil.createNotification(requireContext(), - new ErrorInfo(new RuntimeException("Dummy"), UserAction.UI_ERROR, "Dummy")); + new ErrorInfo(new RuntimeException(DUMMY), UserAction.UI_ERROR, DUMMY)); return true; }); } @@ -81,9 +84,10 @@ public class DebugSettingsFragment extends BasePreferenceFragment { try { // Try to find the implementation of the LeakCanary API return Optional.of((DebugSettingsBVLeakCanaryAPI) - Class.forName(DebugSettingsBVLeakCanaryAPI.IMPL_CLASS).newInstance()); - } catch (final ClassNotFoundException - | IllegalAccessException | java.lang.InstantiationException e) { + Class.forName(DebugSettingsBVLeakCanaryAPI.IMPL_CLASS) + .getDeclaredConstructor() + .newInstance()); + } catch (final Exception e) { return Optional.empty(); } } From bebd2b449cbf59bfe721a2c4b825eac9243051c0 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Wed, 29 Dec 2021 18:46:45 +0100 Subject: [PATCH 075/119] Removed unused import --- .../java/org/schabi/newpipe/settings/DebugSettingsFragment.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java index 915531779..a42d47313 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java @@ -11,7 +11,6 @@ import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.util.PicassoHelper; -import java.lang.reflect.InvocationTargetException; import java.util.Optional; public class DebugSettingsFragment extends BasePreferenceFragment { From c5a06243a6ed6982bcac663f40543df820803402 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Wed, 29 Dec 2021 18:49:37 +0100 Subject: [PATCH 076/119] Fixed variable name --- .../schabi/newpipe/settings/DebugSettingsFragment.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java index a42d47313..3e28a6065 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java @@ -40,13 +40,13 @@ public class DebugSettingsFragment extends BasePreferenceFragment { assert showErrorSnackbarPreference != null; assert createErrorNotificationPreference != null; - final Optional optPDLeakCanary = getBVLeakCanary(); + final Optional optBVLeakCanary = getBVLeakCanary(); - allowHeapDumpingPreference.setEnabled(optPDLeakCanary.isPresent()); - showMemoryLeaksPreference.setEnabled(optPDLeakCanary.isPresent()); + allowHeapDumpingPreference.setEnabled(optBVLeakCanary.isPresent()); + showMemoryLeaksPreference.setEnabled(optBVLeakCanary.isPresent()); - if (optPDLeakCanary.isPresent()) { - final DebugSettingsBVLeakCanaryAPI pdLeakCanary = optPDLeakCanary.get(); + if (optBVLeakCanary.isPresent()) { + final DebugSettingsBVLeakCanaryAPI pdLeakCanary = optBVLeakCanary.get(); showMemoryLeaksPreference.setOnPreferenceClickListener(preference -> { startActivity(pdLeakCanary.getNewLeakDisplayActivityIntent()); From 8bbc3e531c591539ab89ceac42c94586c130a94a Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Wed, 29 Dec 2021 22:17:30 +0100 Subject: [PATCH 077/119] Fixed gitignore and commited missing file --- .gitignore | 4 ++-- .../settings/DebugSettingsBVLeakCanary.java | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsBVLeakCanary.java diff --git a/.gitignore b/.gitignore index 40e7d2c03..1352b6917 100644 --- a/.gitignore +++ b/.gitignore @@ -8,8 +8,8 @@ captures/ *~ .weblate *.class -**/debug/ -**/release/ +app/debug/ +app/release/ # vscode / eclipse files *.classpath diff --git a/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsBVLeakCanary.java b/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsBVLeakCanary.java new file mode 100644 index 000000000..f8fd7f969 --- /dev/null +++ b/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsBVLeakCanary.java @@ -0,0 +1,15 @@ +package org.schabi.newpipe.settings; + +import android.content.Intent; + +import leakcanary.LeakCanary; + +@SuppressWarnings("unused") // Class is used but loaded via reflection +public class DebugSettingsBVLeakCanary + implements DebugSettingsFragment.DebugSettingsBVLeakCanaryAPI { + + @Override + public Intent getNewLeakDisplayActivityIntent() { + return LeakCanary.INSTANCE.newLeakDisplayActivityIntent(); + } +} From ce4dd33eab241ed79233a44706fb0ce00ba24dd1 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 31 Dec 2021 14:50:27 +0100 Subject: [PATCH 078/119] Fixed problems with Android's lifecycle (restore) --- .../newpipe/settings/SettingsActivity.java | 84 +++++++++++++++---- .../PreferenceSearchFragment.java | 8 +- 2 files changed, 73 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java index 25d22dc9f..4dfbf6c08 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java @@ -3,6 +3,7 @@ package org.schabi.newpipe.settings; import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; import android.os.Bundle; +import android.text.TextUtils; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -40,6 +41,9 @@ import org.schabi.newpipe.views.FocusOverlayView; import java.util.concurrent.TimeUnit; +import icepick.Icepick; +import icepick.State; + /* * Created by Christian Schabesberger on 31.08.15. * @@ -77,20 +81,37 @@ public class SettingsActivity extends AppCompatActivity implements private View searchContainer; private EditText searchEditText; + // State + @State + String searchText; + @State + boolean wasSearchActive; + @Override protected void onCreate(final Bundle savedInstanceBundle) { setTheme(ThemeHelper.getSettingsThemeStyle(this)); assureCorrectAppLanguage(this); + super.onCreate(savedInstanceBundle); + Icepick.restoreInstanceState(this, savedInstanceBundle); + final boolean restored = savedInstanceBundle != null; final SettingsLayoutBinding settingsLayoutBinding = SettingsLayoutBinding.inflate(getLayoutInflater()); setContentView(settingsLayoutBinding.getRoot()); - initSearch(settingsLayoutBinding); + initSearch(settingsLayoutBinding, restored); setSupportActionBar(settingsLayoutBinding.settingsToolbarLayout.toolbar); - if (savedInstanceBundle == null) { + if (restored) { + // Restore state + if (this.wasSearchActive) { + setSearchActive(true); + if (!TextUtils.isEmpty(this.searchText)) { + this.searchEditText.setText(this.searchText); + } + } + } else { getSupportFragmentManager().beginTransaction() .replace(R.id.settings_fragment_holder, new MainSettingsFragment()) .commit(); @@ -101,6 +122,12 @@ public class SettingsActivity extends AppCompatActivity implements } } + @Override + protected void onSaveInstanceState(@NonNull final Bundle outState) { + super.onSaveInstanceState(outState); + Icepick.saveInstanceState(this, outState); + } + @Override public boolean onCreateOptionsMenu(final Menu menu) { final ActionBar actionBar = getSupportActionBar(); @@ -175,7 +202,10 @@ public class SettingsActivity extends AppCompatActivity implements //////////////////////////////////////////////////////////////////////////*/ //region Search - private void initSearch(final SettingsLayoutBinding settingsLayoutBinding) { + private void initSearch( + final SettingsLayoutBinding settingsLayoutBinding, + final boolean restored + ) { searchContainer = settingsLayoutBinding.settingsToolbarLayout.toolbar .findViewById(R.id.toolbar_search_container); @@ -207,7 +237,19 @@ public class SettingsActivity extends AppCompatActivity implements .map(parser::parse) .forEach(searcher::add); - searchFragment = new PreferenceSearchFragment(searcher); + if (restored) { + searchFragment = (PreferenceSearchFragment) getSupportFragmentManager() + .findFragmentByTag(PreferenceSearchFragment.NAME); + if (searchFragment != null) { + // Hide/Remove the search fragment otherwise we get an exception + // when adding it (because it's already present) + hideSearchFragment(); + } + } + if (searchFragment == null) { + searchFragment = new PreferenceSearchFragment(); + } + searchFragment.setSearcher(searcher); } private void prepareSearchConfig() { @@ -228,36 +270,45 @@ public class SettingsActivity extends AppCompatActivity implements public void setMenuSearchItem(final MenuItem menuSearchItem) { this.menuSearchItem = menuSearchItem; + + // Ensure that the item is in the correct state when adding it. This is due to + // Android's lifecycle (the Activity is recreated before the Fragment that registers this) + if (menuSearchItem != null) { + menuSearchItem.setVisible(!isSearchActive()); + } } public void setSearchActive(final boolean active) { + if (DEBUG) { + Log.d(TAG, "setSearchActive called active=" + active); + } + // Ignore if search is already in correct state if (isSearchActive() == active) { return; } - if (DEBUG) { - Log.d(TAG, "setSearchActive called active=" + active); - } + wasSearchActive = active; searchContainer.setVisibility(active ? View.VISIBLE : View.GONE); if (menuSearchItem != null) { menuSearchItem.setVisible(!active); } - final FragmentManager fm = getSupportFragmentManager(); if (active) { - fm.beginTransaction() + getSupportFragmentManager() + .beginTransaction() .add(FRAGMENT_HOLDER_ID, searchFragment, PreferenceSearchFragment.NAME) .addToBackStack(PreferenceSearchFragment.NAME) .commit(); KeyboardUtil.showKeyboard(this, searchEditText); } else if (searchFragment != null) { - fm.beginTransaction().remove(searchFragment).commit(); - fm.popBackStack( - PreferenceSearchFragment.NAME, - FragmentManager.POP_BACK_STACK_INCLUSIVE); + hideSearchFragment(); + getSupportFragmentManager() + .popBackStack( + PreferenceSearchFragment.NAME, + FragmentManager.POP_BACK_STACK_INCLUSIVE); KeyboardUtil.hideKeyboard(this, searchEditText); } @@ -265,6 +316,10 @@ public class SettingsActivity extends AppCompatActivity implements resetSearchText(); } + private void hideSearchFragment() { + getSupportFragmentManager().beginTransaction().remove(searchFragment).commit(); + } + private void resetSearchText() { searchEditText.setText(""); } @@ -279,7 +334,8 @@ public class SettingsActivity extends AppCompatActivity implements } if (searchFragment != null) { - searchFragment.updateSearchResults(this.searchEditText.getText().toString()); + searchText = this.searchEditText.getText().toString(); + searchFragment.updateSearchResults(searchText); } } diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java index 1b1d627c1..38c87ea76 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java @@ -24,14 +24,12 @@ import java.util.Objects; public class PreferenceSearchFragment extends Fragment { public static final String NAME = PreferenceSearchFragment.class.getSimpleName(); - private final PreferenceSearcher searcher; + private PreferenceSearcher searcher; private SearchViewHolder viewHolder; private PreferenceSearchAdapter adapter; - public PreferenceSearchFragment( - final PreferenceSearcher searcher - ) { + public void setSearcher(final PreferenceSearcher searcher) { this.searcher = searcher; } @@ -56,7 +54,7 @@ public class PreferenceSearchFragment extends Fragment { } public void updateSearchResults(final String keyword) { - if (adapter == null) { + if (adapter == null || searcher == null) { return; } From 9b2c86a37be7ce57f5a26dd222f854be0479a771 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 31 Dec 2021 16:14:01 +0100 Subject: [PATCH 079/119] Improved documentation --- .../settings/DebugSettingsBVDLeakCanary.java | 20 +++++++++++++++++++ .../settings/DebugSettingsBVLeakCanary.java | 15 -------------- .../settings/DebugSettingsFragment.java | 20 +++++++++++-------- 3 files changed, 32 insertions(+), 23 deletions(-) create mode 100644 app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsBVDLeakCanary.java delete mode 100644 app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsBVLeakCanary.java diff --git a/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsBVDLeakCanary.java b/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsBVDLeakCanary.java new file mode 100644 index 000000000..a2d65f6f4 --- /dev/null +++ b/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsBVDLeakCanary.java @@ -0,0 +1,20 @@ +package org.schabi.newpipe.settings; + +import android.content.Intent; + +import leakcanary.LeakCanary; + +/** + * Build variant dependent (BVD) leak canary API implementation for the debug settings fragment. + * This class is loaded via reflection by + * {@link DebugSettingsFragment.DebugSettingsBVDLeakCanaryAPI}. + */ +@SuppressWarnings("unused") // Class is used but loaded via reflection +public class DebugSettingsBVDLeakCanary + implements DebugSettingsFragment.DebugSettingsBVDLeakCanaryAPI { + + @Override + public Intent getNewLeakDisplayActivityIntent() { + return LeakCanary.INSTANCE.newLeakDisplayActivityIntent(); + } +} diff --git a/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsBVLeakCanary.java b/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsBVLeakCanary.java deleted file mode 100644 index f8fd7f969..000000000 --- a/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsBVLeakCanary.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.schabi.newpipe.settings; - -import android.content.Intent; - -import leakcanary.LeakCanary; - -@SuppressWarnings("unused") // Class is used but loaded via reflection -public class DebugSettingsBVLeakCanary - implements DebugSettingsFragment.DebugSettingsBVLeakCanaryAPI { - - @Override - public Intent getNewLeakDisplayActivityIntent() { - return LeakCanary.INSTANCE.newLeakDisplayActivityIntent(); - } -} diff --git a/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java index 3e28a6065..395c7c0f0 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java @@ -40,13 +40,13 @@ public class DebugSettingsFragment extends BasePreferenceFragment { assert showErrorSnackbarPreference != null; assert createErrorNotificationPreference != null; - final Optional optBVLeakCanary = getBVLeakCanary(); + final Optional optBVLeakCanary = getBVDLeakCanary(); allowHeapDumpingPreference.setEnabled(optBVLeakCanary.isPresent()); showMemoryLeaksPreference.setEnabled(optBVLeakCanary.isPresent()); if (optBVLeakCanary.isPresent()) { - final DebugSettingsBVLeakCanaryAPI pdLeakCanary = optBVLeakCanary.get(); + final DebugSettingsBVDLeakCanaryAPI pdLeakCanary = optBVLeakCanary.get(); showMemoryLeaksPreference.setOnPreferenceClickListener(preference -> { startActivity(pdLeakCanary.getNewLeakDisplayActivityIntent()); @@ -79,11 +79,15 @@ public class DebugSettingsFragment extends BasePreferenceFragment { }); } - private Optional getBVLeakCanary() { + /** + * Tries to find the {@link DebugSettingsBVDLeakCanaryAPI#IMPL_CLASS} and loads it if available. + * @return An {@link Optional} which is empty if the implementation class couldn't be loaded. + */ + private Optional getBVDLeakCanary() { try { // Try to find the implementation of the LeakCanary API - return Optional.of((DebugSettingsBVLeakCanaryAPI) - Class.forName(DebugSettingsBVLeakCanaryAPI.IMPL_CLASS) + return Optional.of((DebugSettingsBVDLeakCanaryAPI) + Class.forName(DebugSettingsBVDLeakCanaryAPI.IMPL_CLASS) .getDeclaredConstructor() .newInstance()); } catch (final Exception e) { @@ -92,12 +96,12 @@ public class DebugSettingsFragment extends BasePreferenceFragment { } /** - * Build variant dependent leak canary API for this fragment. + * Build variant dependent (BVD) leak canary API for this fragment. * Why is LeakCanary not used directly? Because it can't be assured */ - public interface DebugSettingsBVLeakCanaryAPI { + public interface DebugSettingsBVDLeakCanaryAPI { String IMPL_CLASS = - "org.schabi.newpipe.settings.DebugSettingsBVLeakCanary"; + "org.schabi.newpipe.settings.DebugSettingsBVDLeakCanary"; Intent getNewLeakDisplayActivityIntent(); } From 37cd71328c943e7ccc88baa8ea17ff650d3c922a Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sun, 9 Jan 2022 14:38:36 +0100 Subject: [PATCH 080/119] Moved ``FuzzyScore`` to original Apache package --- .../commons/text}/similarity/FuzzyScore.java | 2 +- .../preferencesearch/PreferenceFuzzySearchFunction.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename app/src/main/java/org/{schabi/newpipe/settings/preferencesearch => apache/commons/text}/similarity/FuzzyScore.java (98%) diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/similarity/FuzzyScore.java b/app/src/main/java/org/apache/commons/text/similarity/FuzzyScore.java similarity index 98% rename from app/src/main/java/org/schabi/newpipe/settings/preferencesearch/similarity/FuzzyScore.java rename to app/src/main/java/org/apache/commons/text/similarity/FuzzyScore.java index 4ab6bf60a..bbab7fd78 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/similarity/FuzzyScore.java +++ b/app/src/main/java/org/apache/commons/text/similarity/FuzzyScore.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.schabi.newpipe.settings.preferencesearch.similarity; +package org.apache.commons.text.similarity; import java.util.Locale; diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceFuzzySearchFunction.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceFuzzySearchFunction.java index 88ef790c8..7c231cafb 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceFuzzySearchFunction.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceFuzzySearchFunction.java @@ -2,7 +2,7 @@ package org.schabi.newpipe.settings.preferencesearch; import android.text.TextUtils; -import org.schabi.newpipe.settings.preferencesearch.similarity.FuzzyScore; +import org.apache.commons.text.similarity.FuzzyScore; import java.util.Comparator; import java.util.Locale; From b16e972710e0bac6ce8cf7c9f56b3ef64a89ed7b Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sun, 9 Jan 2022 14:58:10 +0100 Subject: [PATCH 081/119] Improved doc --- .../preferencesearch/PreferenceSearchResultHighlighter.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultHighlighter.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultHighlighter.java index e48ca28ce..418a3ea46 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultHighlighter.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultHighlighter.java @@ -29,9 +29,11 @@ public final class PreferenceSearchResultHighlighter { /** * Highlight the specified preference. + *
+ * Note: This function is Thread independent (can be called from outside of the main thread). * - * @param item - * @param prefsFragment + * @param item The item to highlight + * @param prefsFragment The fragment where the items is located on */ public static void highlight( final PreferenceSearchItem item, From e2f449f0c8782e19ae2a9cf64936931b9e03a578 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sun, 9 Jan 2022 15:22:05 +0100 Subject: [PATCH 082/119] Code improvements * Renamed methods so that they are more understandable * Removed ``SearchIndexItem`` --- .../newpipe/settings/SettingsActivity.java | 25 +++-- .../preferencesearch/PreferenceParser.java | 13 +-- .../PreferenceSearchConfiguration.java | 99 +------------------ .../preferencesearch/PreferenceSearcher.java | 2 +- 4 files changed, 24 insertions(+), 115 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java index 4dfbf6c08..7d56863eb 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java @@ -171,6 +171,7 @@ public class SettingsActivity extends AppCompatActivity implements @Override public boolean onPreferenceStartFragment(final PreferenceFragmentCompat caller, final Preference preference) { + preference.getExtras() showSettingsFragment(instantiateFragment(preference.getFragment())); return true; } @@ -221,20 +222,24 @@ public class SettingsActivity extends AppCompatActivity implements searchContainer.findViewById(R.id.toolbar_search_clear) .setOnClickListener(ev -> resetSearchText()); - prepareSearchConfig(); + ensureSearchRepresentsApplicationState(); // Build search configuration using SettingsResourceRegistry final PreferenceSearchConfiguration config = new PreferenceSearchConfiguration(); - SettingsResourceRegistry.getInstance().getAllEntries().stream() - .filter(SettingsResourceRegistry.SettingRegistryEntry::isSearchable) - .map(SettingsResourceRegistry.SettingRegistryEntry::getPreferencesResId) - .forEach(config::index); + // Build search items final PreferenceParser parser = new PreferenceParser(getApplicationContext(), config); final PreferenceSearcher searcher = new PreferenceSearcher(config); - config.getFiles().stream() + + // Find all searchable SettingsResourceRegistry fragments + SettingsResourceRegistry.getInstance().getAllEntries().stream() + .filter(SettingsResourceRegistry.SettingRegistryEntry::isSearchable) + // Get the resId + .map(SettingsResourceRegistry.SettingRegistryEntry::getPreferencesResId) + // Parse .map(parser::parse) + // Add it to the searcher .forEach(searcher::add); if (restored) { @@ -252,7 +257,13 @@ public class SettingsActivity extends AppCompatActivity implements searchFragment.setSearcher(searcher); } - private void prepareSearchConfig() { + /** + * Ensures that the search shows the correct/available search results. + *
+ * Some features are e.g. only available for debug builds, these should not + * be found when searching inside a release. + */ + private void ensureSearchRepresentsApplicationState() { // Check if the update settings are available if (!CheckForNewAppVersion.isReleaseApk(App.getApp())) { SettingsResourceRegistry.getInstance() diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java index afd2c1b4f..ccddee97b 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java @@ -39,27 +39,22 @@ public class PreferenceParser { } public List parse( - final PreferenceSearchConfiguration.SearchIndexItem item + @XmlRes final int resId ) { - Objects.requireNonNull(item, "item can't be null"); - final List results = new ArrayList<>(); - final XmlPullParser xpp = context.getResources().getXml(item.getResId()); + final XmlPullParser xpp = context.getResources().getXml(resId); try { xpp.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); xpp.setFeature(XmlPullParser.FEATURE_REPORT_NAMESPACE_ATTRIBUTES, true); final List breadcrumbs = new ArrayList<>(); - if (!TextUtils.isEmpty(item.getBreadcrumb())) { - breadcrumbs.add(item.getBreadcrumb()); - } while (xpp.getEventType() != XmlPullParser.END_DOCUMENT) { if (xpp.getEventType() == XmlPullParser.START_TAG) { final PreferenceSearchItem result = parseSearchResult( xpp, joinBreadcrumbs(breadcrumbs), - item.getResId() + resId ); if (!searchConfiguration.getParserIgnoreElements().contains(xpp.getName()) @@ -79,7 +74,7 @@ public class PreferenceParser { xpp.next(); } } catch (final Exception e) { - Log.w(TAG, "Failed to parse resid=" + item.getResId(), e); + Log.w(TAG, "Failed to parse resid=" + resId, e); } return results; } diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java index 1c9dc99aa..3d49140fb 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java @@ -1,14 +1,10 @@ package org.schabi.newpipe.settings.preferencesearch; -import android.os.Parcel; -import android.os.Parcelable; import android.text.TextUtils; -import androidx.annotation.XmlRes; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceScreen; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -16,8 +12,6 @@ import java.util.function.BinaryOperator; import java.util.stream.Stream; public class PreferenceSearchConfiguration { - private final ArrayList itemsToIndex = new ArrayList<>(); - private BinaryOperator breadcrumbConcat = (s1, s2) -> TextUtils.isEmpty(s1) ? s2 : (s1 + " > " + s2); @@ -38,27 +32,11 @@ public class PreferenceSearchConfiguration { this.searcher = Objects.requireNonNull(searcher); } - /** - * Adds a new file to the index. - * - * @param resId The preference file to index - * @return SearchIndexItem - */ - public SearchIndexItem index(@XmlRes final int resId) { - final SearchIndexItem item = new SearchIndexItem(resId, this); - itemsToIndex.add(item); - return item; - } - - public List getFiles() { - return itemsToIndex; - } - public BinaryOperator getBreadcrumbConcat() { return breadcrumbConcat; } - public PreferenceSearchFunction getSearchMatcher() { + public PreferenceSearchFunction getSearcher() { return searcher; } @@ -70,81 +48,6 @@ public class PreferenceSearchConfiguration { return parserContainerElements; } - /** - * Adds a given R.xml resource to the search index. - */ - public static final class SearchIndexItem implements Parcelable { - private String breadcrumb = ""; - @XmlRes - private final int resId; - private final PreferenceSearchConfiguration searchConfiguration; - - /** - * Includes the given R.xml resource in the index. - * - * @param resId The resource to index - * @param searchConfiguration The configuration for the search - */ - private SearchIndexItem( - @XmlRes final int resId, - final PreferenceSearchConfiguration searchConfiguration - ) { - this.resId = resId; - this.searchConfiguration = searchConfiguration; - } - - /** - * Adds a breadcrumb. - * - * @param breadcrumb The breadcrumb to add - * @return For chaining - */ - @SuppressWarnings("HiddenField") - public SearchIndexItem withBreadcrumb(final String breadcrumb) { - this.breadcrumb = - searchConfiguration.getBreadcrumbConcat().apply(this.breadcrumb, breadcrumb); - return this; - } - - @XmlRes - int getResId() { - return resId; - } - - String getBreadcrumb() { - return breadcrumb; - } - - public static final Creator CREATOR = new Creator<>() { - @Override - public SearchIndexItem createFromParcel(final Parcel in) { - return new SearchIndexItem(in); - } - - @Override - public SearchIndexItem[] newArray(final int size) { - return new SearchIndexItem[size]; - } - }; - - private SearchIndexItem(final Parcel parcel) { - this.breadcrumb = parcel.readString(); - this.resId = parcel.readInt(); - this.searchConfiguration = null; - } - - @Override - public void writeToParcel(final Parcel dest, final int flags) { - dest.writeString(this.breadcrumb); - dest.writeInt(this.resId); - } - - @Override - public int describeContents() { - return 0; - } - } - @FunctionalInterface public interface PreferenceSearchFunction { Stream search( diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearcher.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearcher.java index 87dd11693..176dc5d14 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearcher.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearcher.java @@ -24,7 +24,7 @@ public class PreferenceSearcher { return new ArrayList<>(); } - return configuration.getSearchMatcher() + return configuration.getSearcher() .search(allEntries.stream(), keyword) .collect(Collectors.toList()); } From 03bb2123f24a9ef874d508db94fcd779526c8c88 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sun, 9 Jan 2022 16:49:16 +0100 Subject: [PATCH 083/119] Removed breadcrumbs customization --- .../org/schabi/newpipe/settings/SettingsActivity.java | 1 - .../settings/preferencesearch/PreferenceParser.java | 3 ++- .../PreferenceSearchConfiguration.java | 11 ----------- 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java index 7d56863eb..3872e5172 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java @@ -171,7 +171,6 @@ public class SettingsActivity extends AppCompatActivity implements @Override public boolean onPreferenceStartFragment(final PreferenceFragmentCompat caller, final Preference preference) { - preference.getExtras() showSettingsFragment(instantiateFragment(preference.getFragment())); return true; } diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java index ccddee97b..77136e08d 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java @@ -15,6 +15,7 @@ import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.stream.Collectors; /** * Parses the corresponding preference-file(s). @@ -82,7 +83,7 @@ public class PreferenceParser { private String joinBreadcrumbs(final List breadcrumbs) { return breadcrumbs.stream() .filter(crumb -> !TextUtils.isEmpty(crumb)) - .reduce("", searchConfiguration.getBreadcrumbConcat()); + .collect(Collectors.joining(" > ")); } private String getAttribute( diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java index 3d49140fb..50371b78b 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java @@ -12,9 +12,6 @@ import java.util.function.BinaryOperator; import java.util.stream.Stream; public class PreferenceSearchConfiguration { - private BinaryOperator breadcrumbConcat = - (s1, s2) -> TextUtils.isEmpty(s1) ? s2 : (s1 + " > " + s2); - private PreferenceSearchFunction searcher = new PreferenceFuzzySearchFunction(); private final List parserIgnoreElements = Arrays.asList( @@ -24,18 +21,10 @@ public class PreferenceSearchConfiguration { PreferenceScreen.class.getSimpleName()); - public void setBreadcrumbConcat(final BinaryOperator breadcrumbConcat) { - this.breadcrumbConcat = Objects.requireNonNull(breadcrumbConcat); - } - public void setSearcher(final PreferenceSearchFunction searcher) { this.searcher = Objects.requireNonNull(searcher); } - public BinaryOperator getBreadcrumbConcat() { - return breadcrumbConcat; - } - public PreferenceSearchFunction getSearcher() { return searcher; } From 7067ebdd128f525e039b3bd3942a4bdcf73c1980 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sun, 9 Jan 2022 16:53:36 +0100 Subject: [PATCH 084/119] Fixed imports --- .../newpipe/settings/preferencesearch/PreferenceParser.java | 4 +++- .../preferencesearch/PreferenceSearchConfiguration.java | 3 --- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java index 77136e08d..1f507c7f1 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceParser.java @@ -3,6 +3,7 @@ package org.schabi.newpipe.settings.preferencesearch; import android.content.Context; import android.text.TextUtils; import android.util.Log; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.XmlRes; @@ -14,7 +15,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.stream.Collectors; /** @@ -64,6 +64,8 @@ public class PreferenceParser { results.add(result); } if (searchConfiguration.getParserContainerElements().contains(xpp.getName())) { + // This code adds breadcrumbs for certain containers (e.g. PreferenceScreen) + // Example: Video and Audio > Player breadcrumbs.add(result.getTitle() == null ? "" : result.getTitle()); } } else if (xpp.getEventType() == XmlPullParser.END_TAG diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java index 50371b78b..5835dcab5 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchConfiguration.java @@ -1,14 +1,11 @@ package org.schabi.newpipe.settings.preferencesearch; -import android.text.TextUtils; - import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceScreen; import java.util.Arrays; import java.util.List; import java.util.Objects; -import java.util.function.BinaryOperator; import java.util.stream.Stream; public class PreferenceSearchConfiguration { From f55e8ea3aad21b2897e7bcecb84bb3d077d514b3 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sun, 9 Jan 2022 17:40:16 +0100 Subject: [PATCH 085/119] Use ViewBinding --- .../PreferenceSearchFragment.java | 31 ++++++------------- .../settings_preferencesearch_fragment.xml | 2 +- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java index 38c87ea76..f0944876e 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java @@ -10,13 +10,11 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import org.schabi.newpipe.R; +import org.schabi.newpipe.databinding.SettingsPreferencesearchFragmentBinding; import java.util.ArrayList; import java.util.List; -import java.util.Objects; /** * Displays the search results. @@ -26,7 +24,7 @@ public class PreferenceSearchFragment extends Fragment { private PreferenceSearcher searcher; - private SearchViewHolder viewHolder; + private SettingsPreferencesearchFragmentBinding binding; private PreferenceSearchAdapter adapter; public void setSearcher(final PreferenceSearcher searcher) { @@ -40,17 +38,16 @@ public class PreferenceSearchFragment extends Fragment { @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState ) { - final View rootView = - inflater.inflate(R.layout.settings_preferencesearch_fragment, container, false); + // SettingsPreferenceSearchFragmentBinding. + binding = SettingsPreferencesearchFragmentBinding.inflate(inflater, container, false); - viewHolder = new SearchViewHolder(rootView); - viewHolder.recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + binding.searchResults.setLayoutManager(new LinearLayoutManager(getContext())); adapter = new PreferenceSearchAdapter(); adapter.setOnItemClickListener(this::onItemClicked); - viewHolder.recyclerView.setAdapter(adapter); + binding.searchResults.setAdapter(adapter); - return rootView; + return binding.getRoot(); } public void updateSearchResults(final String keyword) { @@ -69,8 +66,8 @@ public class PreferenceSearchFragment extends Fragment { } private void setEmptyViewShown(final boolean shown) { - viewHolder.emptyStateView.setVisibility(shown ? View.VISIBLE : View.GONE); - viewHolder.recyclerView.setVisibility(shown ? View.GONE : View.VISIBLE); + binding.emptyStateView.setVisibility(shown ? View.VISIBLE : View.GONE); + binding.searchResults.setVisibility(shown ? View.GONE : View.VISIBLE); } public void onItemClicked(final PreferenceSearchItem item) { @@ -81,14 +78,4 @@ public class PreferenceSearchFragment extends Fragment { ((PreferenceSearchResultListener) getActivity()).onSearchResultClicked(item); } - - private static class SearchViewHolder { - private final RecyclerView recyclerView; - private final View emptyStateView; - - SearchViewHolder(final View root) { - recyclerView = Objects.requireNonNull(root.findViewById(R.id.list)); - emptyStateView = Objects.requireNonNull(root.findViewById(R.id.empty_state_view)); - } - } } diff --git a/app/src/main/res/layout/settings_preferencesearch_fragment.xml b/app/src/main/res/layout/settings_preferencesearch_fragment.xml index b8aaa60f6..89a25b217 100644 --- a/app/src/main/res/layout/settings_preferencesearch_fragment.xml +++ b/app/src/main/res/layout/settings_preferencesearch_fragment.xml @@ -41,7 +41,7 @@ Date: Mon, 24 Jan 2022 21:08:06 +0100 Subject: [PATCH 086/119] Use view binding inside ``PreferenceViewHolder`` --- .../PreferenceSearchAdapter.java | 40 +++++++++---------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchAdapter.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchAdapter.java index 527a4a595..02fbf9577 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchAdapter.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchAdapter.java @@ -4,12 +4,11 @@ import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; -import org.schabi.newpipe.R; +import org.schabi.newpipe.databinding.SettingsPreferencesearchListItemResultBinding; import java.util.ArrayList; import java.util.List; @@ -22,37 +21,38 @@ class PreferenceSearchAdapter @NonNull @Override - public PreferenceSearchAdapter.PreferenceViewHolder onCreateViewHolder( + public PreferenceViewHolder onCreateViewHolder( @NonNull final ViewGroup parent, final int viewType ) { return new PreferenceViewHolder( - LayoutInflater - .from(parent.getContext()) - .inflate(R.layout.settings_preferencesearch_list_item_result, parent, false)); + SettingsPreferencesearchListItemResultBinding.inflate( + LayoutInflater.from(parent.getContext()), + parent, + false)); } @Override public void onBindViewHolder( - @NonNull final PreferenceSearchAdapter.PreferenceViewHolder holder, + @NonNull final PreferenceViewHolder holder, final int position ) { final PreferenceSearchItem item = dataset.get(position); - holder.title.setText(item.getTitle()); + holder.binding.title.setText(item.getTitle()); if (TextUtils.isEmpty(item.getSummary())) { - holder.summary.setVisibility(View.GONE); + holder.binding.summary.setVisibility(View.GONE); } else { - holder.summary.setVisibility(View.VISIBLE); - holder.summary.setText(item.getSummary()); + holder.binding.summary.setVisibility(View.VISIBLE); + holder.binding.summary.setText(item.getSummary()); } if (TextUtils.isEmpty(item.getBreadcrumbs())) { - holder.breadcrumbs.setVisibility(View.GONE); + holder.binding.breadcrumbs.setVisibility(View.GONE); } else { - holder.breadcrumbs.setVisibility(View.VISIBLE); - holder.breadcrumbs.setText(item.getBreadcrumbs()); + holder.binding.breadcrumbs.setVisibility(View.VISIBLE); + holder.binding.breadcrumbs.setText(item.getBreadcrumbs()); } holder.itemView.setOnClickListener(v -> { @@ -77,15 +77,11 @@ class PreferenceSearchAdapter } static class PreferenceViewHolder extends RecyclerView.ViewHolder { - final TextView title; - final TextView summary; - final TextView breadcrumbs; + final SettingsPreferencesearchListItemResultBinding binding; - PreferenceViewHolder(final View v) { - super(v); - title = v.findViewById(R.id.title); - summary = v.findViewById(R.id.summary); - breadcrumbs = v.findViewById(R.id.breadcrumbs); + PreferenceViewHolder(final SettingsPreferencesearchListItemResultBinding binding) { + super(binding.getRoot()); + this.binding = binding; } } } From ea07d7751b7aabc2887adca98bc9f3a659747e5d Mon Sep 17 00:00:00 2001 From: TiA4f8R <74829229+TiA4f8R@users.noreply.github.com> Date: Sun, 23 Jan 2022 22:53:17 +0100 Subject: [PATCH 087/119] Fix first item played in playlists when switching player type or resolution The issue was caused by an ExoPlayer change, which when setting a media source, resets the current playback position and the current window index by default. Also set player recovery in more places to fix playback position not propely set in some cases after a player type switch. --- app/src/main/java/org/schabi/newpipe/player/Player.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 81ef25db1..43533b52e 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -2048,7 +2048,7 @@ public final class Player implements if (currentState == STATE_BLOCKED) { changeState(STATE_BUFFERING); } - simpleExoPlayer.setMediaSource(mediaSource); + simpleExoPlayer.setMediaSource(mediaSource, false); simpleExoPlayer.prepare(); } From 1e652b159ea8618acbd101fbc75983d08588efe9 Mon Sep 17 00:00:00 2001 From: ktprograms Date: Mon, 13 Dec 2021 16:42:59 +0800 Subject: [PATCH 088/119] Load uploaderUrl when showing Channel Details from Play Queue This checks if the uploaderUrl is in the database, if not it gets the uploaderUrl and puts it in the database. This is similar to the fetching of uploaderUrl when it doesn't exist done in #6919. Also use createNotification when error occurs in getStreamInfo. --- .../org/schabi/newpipe/QueueItemMenuUtil.java | 13 ++- .../newpipe/util/SaveUploaderUrlHelper.java | 94 +++++++++++++++++++ .../newpipe/util/StreamDialogEntry.java | 28 +----- 3 files changed, 104 insertions(+), 31 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/util/SaveUploaderUrlHelper.java diff --git a/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java b/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java index fcad0b612..fde006a60 100644 --- a/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java +++ b/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java @@ -14,6 +14,7 @@ import org.schabi.newpipe.local.dialog.PlaylistDialog; import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.player.playqueue.PlayQueueItem; import org.schabi.newpipe.util.NavigationHelper; +import org.schabi.newpipe.util.SaveUploaderUrlHelper; import java.util.Collections; @@ -61,11 +62,13 @@ public final class QueueItemMenuUtil { return true; case R.id.menu_item_channel_details: - // An intent must be used here. - // Opening with FragmentManager transactions is not working, - // as PlayQueueActivity doesn't use fragments. - NavigationHelper.openChannelFragmentUsingIntent(context, item.getServiceId(), - item.getUploaderUrl(), item.getUploader()); + SaveUploaderUrlHelper.saveUploaderUrlIfNeeded(context, item, + // An intent must be used here. + // Opening with FragmentManager transactions is not working, + // as PlayQueueActivity doesn't use fragments. + uploaderUrl -> NavigationHelper.openChannelFragmentUsingIntent( + context, item.getServiceId(), uploaderUrl, item.getUploader() + )); return true; case R.id.menu_item_share: shareText(context, item.getTitle(), item.getUrl(), diff --git a/app/src/main/java/org/schabi/newpipe/util/SaveUploaderUrlHelper.java b/app/src/main/java/org/schabi/newpipe/util/SaveUploaderUrlHelper.java new file mode 100644 index 000000000..3c7b1ce91 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/SaveUploaderUrlHelper.java @@ -0,0 +1,94 @@ +package org.schabi.newpipe.util; + +import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; + +import android.content.Context; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import org.schabi.newpipe.NewPipeDatabase; +import org.schabi.newpipe.R; +import org.schabi.newpipe.error.ErrorInfo; +import org.schabi.newpipe.error.ErrorUtil; +import org.schabi.newpipe.error.UserAction; +import org.schabi.newpipe.extractor.stream.StreamInfoItem; +import org.schabi.newpipe.player.playqueue.PlayQueueItem; + +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.schedulers.Schedulers; + +/** + * Utility class for putting the uploader url into the database - when required. + */ +public final class SaveUploaderUrlHelper { + private SaveUploaderUrlHelper() { + } + + // Public functions which call the function that does + // the actual work with the correct parameters + public static void saveUploaderUrlIfNeeded(@NonNull final Fragment fragment, + @NonNull final StreamInfoItem infoItem, + @NonNull final SaveUploaderUrlCallback callback) { + saveUploaderUrlIfNeeded(fragment.requireContext(), + infoItem.getServiceId(), + infoItem.getUrl(), + infoItem.getUploaderUrl(), + callback); + } + public static void saveUploaderUrlIfNeeded(@NonNull final Context context, + @NonNull final PlayQueueItem queueItem, + @NonNull final SaveUploaderUrlCallback callback) { + saveUploaderUrlIfNeeded(context, + queueItem.getServiceId(), + queueItem.getUrl(), + queueItem.getUploaderUrl(), + callback); + } + + /** + * Fetches and saves the uploaderUrl if it is empty (meaning that it does + * not exist in the video item). The callback is called with either the + * fetched uploaderUrl, or the already saved uploaderUrl, but it is always + * called with a valid uploaderUrl that can be used to show channel details. + * + * @param context Context + * @param serviceId The serviceId of the item + * @param url The item url + * @param uploaderUrl The uploaderUrl of the item, if null or empty, it + * will be fetched using the item url. + * @param callback The callback that returns the fetched or existing + * uploaderUrl + */ + private static void saveUploaderUrlIfNeeded(@NonNull final Context context, + final int serviceId, + @NonNull final String url, + // Only used if not null or empty + @Nullable final String uploaderUrl, + @NonNull final SaveUploaderUrlCallback callback) { + if (isNullOrEmpty(uploaderUrl)) { + Toast.makeText(context, R.string.loading_channel_details, + Toast.LENGTH_SHORT).show(); + ExtractorHelper.getStreamInfo(serviceId, url, false) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(result -> { + NewPipeDatabase.getInstance(context).streamDAO() + .setUploaderUrl(serviceId, url, result.getUploaderUrl()) + .subscribeOn(Schedulers.io()).subscribe(); + callback.onCallback(result.getUploaderUrl()); + }, throwable -> ErrorUtil.createNotification(context, + new ErrorInfo(throwable, UserAction.REQUESTED_CHANNEL, + "Could not load channel details") + )); + } else { + callback.onCallback(uploaderUrl); + } + } + + public interface SaveUploaderUrlCallback { + void onCallback(@NonNull String uploaderUrl); + } +} diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java index bb1cbbeae..1b4c8046c 100644 --- a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java +++ b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java @@ -3,12 +3,10 @@ package org.schabi.newpipe.util; import android.content.Context; import android.net.Uri; import android.util.Log; -import android.widget.Toast; import androidx.fragment.app.Fragment; import androidx.preference.PreferenceManager; -import org.schabi.newpipe.NewPipeDatabase; import org.schabi.newpipe.R; import org.schabi.newpipe.database.stream.model.StreamEntity; import org.schabi.newpipe.extractor.stream.StreamInfoItem; @@ -27,36 +25,14 @@ import java.util.function.Consumer; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.schedulers.Schedulers; -import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; - public enum StreamDialogEntry { ////////////////////////////////////// // enum values with DEFAULT actions // ////////////////////////////////////// show_channel_details(R.string.show_channel_details, (fragment, item) -> { - if (isNullOrEmpty(item.getUploaderUrl())) { - final int serviceId = item.getServiceId(); - final String url = item.getUrl(); - Toast.makeText(fragment.getContext(), R.string.loading_channel_details, - Toast.LENGTH_SHORT).show(); - ExtractorHelper.getStreamInfo(serviceId, url, false) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(result -> { - NewPipeDatabase.getInstance(fragment.requireContext()).streamDAO() - .setUploaderUrl(serviceId, url, result.getUploaderUrl()) - .subscribeOn(Schedulers.io()).subscribe(); - openChannelFragment(fragment, item, result.getUploaderUrl()); - }, throwable -> Toast.makeText( - // TODO: Open the Error Activity - fragment.getContext(), - R.string.error_show_channel_details, - Toast.LENGTH_SHORT - ).show()); - } else { - openChannelFragment(fragment, item, item.getUploaderUrl()); - } + SaveUploaderUrlHelper.saveUploaderUrlIfNeeded(fragment, item, + uploaderUrl -> openChannelFragment(fragment, item, uploaderUrl)); }), /** From 5108d75682bf5cbb142ca4be8796daab02b9fb3f Mon Sep 17 00:00:00 2001 From: Stypox Date: Tue, 25 Jan 2022 17:37:15 +0100 Subject: [PATCH 089/119] Fix NPE and add some `@Nullable`s Fix NullPointerException in PlayerHolder.getQueueSize() and add `@Nullable` here and there so that the linter reports risks of NPEs --- .../main/java/org/schabi/newpipe/player/Player.java | 4 +++- .../schabi/newpipe/player/helper/PlayerHolder.java | 12 ++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 81ef25db1..c002ba16d 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -260,7 +260,8 @@ public final class Player implements // Playback //////////////////////////////////////////////////////////////////////////*/ - private PlayQueue playQueue; + // play queue might be null e.g. while player is starting + @Nullable private PlayQueue playQueue; private PlayQueueAdapter playQueueAdapter; private StreamSegmentAdapter segmentAdapter; @@ -4202,6 +4203,7 @@ public final class Player implements } + @Nullable public PlayQueue getPlayQueue() { return playQueue; } diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java index 10e315667..42865564a 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java @@ -38,12 +38,12 @@ public final class PlayerHolder { private static final boolean DEBUG = MainActivity.DEBUG; private static final String TAG = PlayerHolder.class.getSimpleName(); - private PlayerServiceExtendedEventListener listener; + @Nullable private PlayerServiceExtendedEventListener listener; private final PlayerServiceConnection serviceConnection = new PlayerServiceConnection(); private boolean bound; - private MainPlayer playerService; - private Player player; + @Nullable private MainPlayer playerService; + @Nullable private Player player; /** * Returns the current {@link MainPlayer.PlayerType} of the {@link MainPlayer} service, @@ -75,7 +75,11 @@ public final class PlayerHolder { } public int getQueueSize() { - return isPlayerOpen() ? player.getPlayQueue().size() : 0; + if (player == null || player.getPlayQueue() == null) { + // player play queue might be null e.g. while player is starting + return 0; + } + return player.getPlayQueue().size(); } public void setListener(@Nullable final PlayerServiceExtendedEventListener newListener) { From af79479716dc387b5f138757f7015e5caecb2145 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Tue, 25 Jan 2022 20:44:49 +0100 Subject: [PATCH 090/119] Fixed "Changing the seeks duration does not update the displayed seconds" --- app/src/main/java/org/schabi/newpipe/player/Player.java | 3 ++- .../schabi/newpipe/views/player/PlayerFastSeekOverlay.kt | 9 ++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 029b33b7f..b16bd8b0e 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -586,7 +586,8 @@ public final class Player implements */ private void setupPlayerSeekOverlay() { binding.fastSeekOverlay - .seekSeconds((int) (retrieveSeekDurationFromPreferences(this) / 1000.0f)) + .seekSecondsSupplier( + () -> (int) (retrieveSeekDurationFromPreferences(this) / 1000.0f)) .performListener(new PlayerFastSeekOverlay.PerformListener() { @Override diff --git a/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt b/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt index 522977317..649b60494 100644 --- a/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt +++ b/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt @@ -42,11 +42,10 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : performListener = listener } - var seekSeconds: Int = 0 - private set + private var seekSecondsSupplier: () -> Int = { 0 } - fun seekSeconds(seconds: Int) = apply { - seekSeconds = seconds + fun seekSecondsSupplier(supplier: () -> Int) = apply { + seekSecondsSupplier = supplier } // Indicates whether this (double) tap is the first of a series @@ -94,7 +93,7 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : performListener?.onDoubleTap() - secondsView.seconds += seekSeconds + secondsView.seconds += seekSecondsSupplier.invoke() performListener?.seek(forward = shouldForward) } From 8a069b497f88c8f9f4c236e57131da98f49cffad Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Tue, 25 Jan 2022 20:47:53 +0100 Subject: [PATCH 091/119] Code cleanup Co-authored-by: Stypox --- .../settings/preferencesearch/PreferenceSearchFragment.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java index f0944876e..308abbc4e 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchFragment.java @@ -38,7 +38,6 @@ public class PreferenceSearchFragment extends Fragment { @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState ) { - // SettingsPreferenceSearchFragmentBinding. binding = SettingsPreferencesearchFragmentBinding.inflate(inflater, container, false); binding.searchResults.setLayoutManager(new LinearLayoutManager(getContext())); From 466db83375c5f33c686f2b02baa06e4331eefead Mon Sep 17 00:00:00 2001 From: Stypox Date: Thu, 27 Jan 2022 14:43:51 +0100 Subject: [PATCH 092/119] Improve HistoryRecordManager tests (#7700) * Improve HistoryRecordManager tests * Improve shuffle as requested --- .../local/history/HistoryRecordManagerTest.kt | 44 ++++++++++++++----- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/app/src/androidTest/java/org/schabi/newpipe/local/history/HistoryRecordManagerTest.kt b/app/src/androidTest/java/org/schabi/newpipe/local/history/HistoryRecordManagerTest.kt index c32a43b2a..24be0f868 100644 --- a/app/src/androidTest/java/org/schabi/newpipe/local/history/HistoryRecordManagerTest.kt +++ b/app/src/androidTest/java/org/schabi/newpipe/local/history/HistoryRecordManagerTest.kt @@ -97,14 +97,23 @@ class HistoryRecordManagerTest { assertThat(database.searchHistoryDAO().all.blockingFirst()).isEmpty() } - @Test - fun getRelatedSearches_emptyQuery() { + private fun insertShuffledRelatedSearches(relatedSearches: Collection) { + + // shuffle to make sure the order of items returned by queries depends only on + // SearchHistoryEntry.creationDate, not on the actual insertion time, so that we can + // verify that the `ORDER BY` clause does its job + database.searchHistoryDAO().insertAll(relatedSearches.shuffled()) + // make sure all entries were inserted - database.searchHistoryDAO().insertAll(RELATED_SEARCHES_ENTRIES) assertEquals( - RELATED_SEARCHES_ENTRIES.size, + relatedSearches.size, database.searchHistoryDAO().all.blockingFirst().size ) + } + + @Test + fun getRelatedSearches_emptyQuery() { + insertShuffledRelatedSearches(RELATED_SEARCHES_ENTRIES) // make sure correct number of searches is returned and in correct order val searches = manager.getRelatedSearches("", 6, 4).blockingFirst() @@ -117,14 +126,29 @@ class HistoryRecordManagerTest { } @Test - fun getRelatedSearched_nonEmptyQuery() { - // make sure all entries were inserted - database.searchHistoryDAO().insertAll(RELATED_SEARCHES_ENTRIES) - assertEquals( - RELATED_SEARCHES_ENTRIES.size, - database.searchHistoryDAO().all.blockingFirst().size + fun getRelatedSearches_emptyQuery_manyDuplicates() { + insertShuffledRelatedSearches( + listOf( + SearchHistoryEntry(time.minusSeconds(9), 3, "A"), + SearchHistoryEntry(time.minusSeconds(8), 3, "AB"), + SearchHistoryEntry(time.minusSeconds(7), 3, "A"), + SearchHistoryEntry(time.minusSeconds(6), 3, "A"), + SearchHistoryEntry(time.minusSeconds(5), 3, "BA"), + SearchHistoryEntry(time.minusSeconds(4), 3, "A"), + SearchHistoryEntry(time.minusSeconds(3), 3, "A"), + SearchHistoryEntry(time.minusSeconds(2), 0, "A"), + SearchHistoryEntry(time.minusSeconds(1), 2, "AA"), + ) ) + val searches = manager.getRelatedSearches("", 9, 3).blockingFirst() + assertThat(searches).containsExactly("AA", "A", "BA") + } + + @Test + fun getRelatedSearched_nonEmptyQuery() { + insertShuffledRelatedSearches(RELATED_SEARCHES_ENTRIES) + // make sure correct number of searches is returned and in correct order val searches = manager.getRelatedSearches("A", 3, 5).blockingFirst() assertThat(searches).containsExactly( From 71c5aaa11ec020fa9b03a619758943ce01424683 Mon Sep 17 00:00:00 2001 From: Stypox Date: Thu, 27 Jan 2022 17:11:16 +0100 Subject: [PATCH 093/119] Do not show enqueue button if play queue not ready --- .../schabi/newpipe/fragments/list/BaseListFragment.java | 2 +- .../fragments/list/playlist/PlaylistFragment.java | 2 +- .../java/org/schabi/newpipe/local/feed/FeedFragment.kt | 2 +- .../local/history/StatisticsPlaylistFragment.java | 2 +- .../newpipe/local/playlist/LocalPlaylistFragment.java | 2 +- .../org/schabi/newpipe/player/helper/PlayerHolder.java | 9 +++++++++ 6 files changed, 14 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java index 4319d42ee..3c2e65bb7 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java @@ -352,7 +352,7 @@ public abstract class BaseListFragment extends BaseStateFragment } final List entries = new ArrayList<>(); - if (PlayerHolder.getInstance().isPlayerOpen()) { + if (PlayerHolder.getInstance().isPlayQueueReady()) { entries.add(StreamDialogEntry.enqueue); if (PlayerHolder.getInstance().getQueueSize() > 1) { diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java index 85c47ec74..640d08064 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java @@ -149,7 +149,7 @@ public class PlaylistFragment extends BaseListInfoFragment { final ArrayList entries = new ArrayList<>(); - if (PlayerHolder.getInstance().isPlayerOpen()) { + if (PlayerHolder.getInstance().isPlayQueueReady()) { entries.add(StreamDialogEntry.enqueue); if (PlayerHolder.getInstance().getQueueSize() > 1) { diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt index 905290b48..e6da0d545 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt @@ -362,7 +362,7 @@ class FeedFragment : BaseStateFragment() { if (context == null || context.resources == null || activity == null) return val entries = ArrayList() - if (PlayerHolder.getInstance().isPlayerOpen) { + if (PlayerHolder.getInstance().isPlayQueueReady) { entries.add(StreamDialogEntry.enqueue) if (PlayerHolder.getInstance().queueSize > 1) { diff --git a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java index 43a5fcf3c..73682d5d5 100644 --- a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java @@ -338,7 +338,7 @@ public class StatisticsPlaylistFragment final ArrayList entries = new ArrayList<>(); - if (PlayerHolder.getInstance().isPlayerOpen()) { + if (PlayerHolder.getInstance().isPlayQueueReady()) { entries.add(StreamDialogEntry.enqueue); if (PlayerHolder.getInstance().getQueueSize() > 1) { 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 87d913b3b..feb5b2f96 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 @@ -753,7 +753,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment entries = new ArrayList<>(); - if (PlayerHolder.getInstance().isPlayerOpen()) { + if (PlayerHolder.getInstance().isPlayQueueReady()) { entries.add(StreamDialogEntry.enqueue); if (PlayerHolder.getInstance().getQueueSize() > 1) { diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java index 42865564a..06a2e52ab 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java @@ -70,6 +70,15 @@ public final class PlayerHolder { return player != null; } + /** + * Use this method to only allow the user to manipulate the play queue (e.g. by enqueueing via + * the stream long press menu) when there actually is a play queue to manipulate. + * @return true only if the player is open and its play queue is ready (i.e. it is not null) + */ + public boolean isPlayQueueReady() { + return player != null && player.getPlayQueue() != null; + } + public boolean isBound() { return bound; } From 9e5b9ca32693a552ea43c6f2994e1d45b15063d6 Mon Sep 17 00:00:00 2001 From: Radplay <63958709+Radplay@users.noreply.github.com> Date: Sun, 30 Jan 2022 18:10:53 +0100 Subject: [PATCH 094/119] Polish translation of README (#7694) Co-authored-by: Mohammed Anas --- README.es.md | 2 +- README.ja.md | 2 +- README.ko.md | 2 +- README.md | 2 +- README.pl.md | 144 ++++++++++++++++++++++++++++++++++++++++++++++++ README.pt_BR.md | 2 +- README.ro.md | 2 +- README.so.md | 2 +- README.tr.md | 2 +- README.zh_TW.md | 2 +- 10 files changed, 153 insertions(+), 9 deletions(-) create mode 100644 README.pl.md diff --git a/README.es.md b/README.es.md index bb579d6cb..8e741d8dd 100644 --- a/README.es.md +++ b/README.es.md @@ -18,7 +18,7 @@

Sitio WebBlogPreguntas FrecuentesPrensa


-*Lea esto en otros idiomas: [English](README.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* +*Lea esto en otros idiomas: [English](README.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* AVISO: ESTA ES UNA VERSIÓN BETA, POR LO TANTO, PUEDE ENCONTRAR BUGS. SI ENCUENTRA UNO ABRA UN ISSUE A TRAVÉS DE NUESTRO REPOSITORIO DE GITHUB. diff --git a/README.ja.md b/README.ja.md index e40ad4332..733209aea 100644 --- a/README.ja.md +++ b/README.ja.md @@ -17,7 +17,7 @@

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


-*他の言語で読む: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md)。* +*他の言語で読む: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md)。* 注意: これはベータ版のため、バグが発生する可能性があります。もしバグが発生した場合、GitHub のリポジトリで Issue を開いてください。 diff --git a/README.ko.md b/README.ko.md index 4daf526a3..ee4029c2f 100644 --- a/README.ko.md +++ b/README.ko.md @@ -17,7 +17,7 @@

WebsiteBlogFAQPress


-*Read this in other languages: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* +*Read this in other languages: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* 경고: 이 버전은 베타 버전이므로, 버그가 발생할 수도 있습니다. 만약 버그가 발생하였다면, 우리의 GITHUB 저장소에서 ISSUE를 열람하여 주십시오. diff --git a/README.md b/README.md index ac961eaac..18d0c9ea6 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@

WebsiteBlogFAQPress


-*Read this in other languages: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* +*Read this in other languages: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* WARNING: THIS IS A BETA VERSION, THEREFORE YOU MAY ENCOUNTER BUGS. IF YOU DO, OPEN AN ISSUE VIA OUR GITHUB REPOSITORY. diff --git a/README.pl.md b/README.pl.md new file mode 100644 index 000000000..317339e60 --- /dev/null +++ b/README.pl.md @@ -0,0 +1,144 @@ +

+

NewPipe

+

Wolny, lekki streamingowy frontend na Androida.

+ +

Pobierz z F-Droid

+ +

+ + + + + + +

+
+

ScreenshotyOpisFunkcjeInstalacja i aktualizacjeWkładWesprzyjLicencja

+

StronaBlogFAQPress

+
+ +*Przeczytaj w innych językach: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* + +UWAGA: TO JEST WERSJA BETA, WIĘC MOŻESZ NAPOTKAĆ BŁĘDY. JEŚLI TAK SIĘ STANIE, OTWÓRZ NOWY "ISSUE" NA GITHUBIE. + +PUBLIKOWANIE NEWPIPE LUB JAKIEGOKOLWIEK JEGO FORKU W SKLEPIE PLAY NARUSZA ICH WARUNKI UŻYTKOWANIA. + +## Screenshoty + +[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) +[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) +[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png) +[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png) +[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png) +[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png) +[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png) +[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png) +[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png) +[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) +[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) +[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) + +## Opis + +NewPipe nie używa żadnych bibliotek Google ani API YouTube. Strony są jedynie analizowane aby zdobyć wymagane informacje, dzięki czemu ta aplikacja może zostać zainstalowana na urządzeniach bez Usług Google Play. Konto YouTube nie jest wymagane aby używać NewPipe, które jest wolnym oprogramowaniem copyleft. + +### Funkcje + +* Wyszukiwanie filmów +* Brak wymogu konta Google/YouTube +* Wyświetlanie generalnych informacji o filmach +* Oglądanie filmów na YouTube +* Słuchanie filmów na YouTube +* Tryb okienkowy (Pływające okno) +* Wybieranie odtwarzacza przez który możemy oglądać film +* Pobieranie filmów +* Pobieranie audio +* Otwieranie filmów w Kodi +* Pokazanie następnych/podobnych filmów +* Wyszukiwanie w YouTube w konkretnym języku +* Oglądanie/Blokowanie materiałów zablokowanych wiekowo. +* Wyświetlanie generalnych informacji o kanałach +* Wyszukiwanie kanałów +* Oglądanie filmów ze strony kanału +* Wsparcie dla Orbot/Tor (Jeszcze nie bezpośrednio) +* Wsparcie dla 1080p/2K/4K +* Historia oglądania +* Subskrybowanie kanałów +* Historia wyszukiwania +* Wyszukiwanie/Oglądanie playlist +* Oglądanie playlist w kolejce +* Dodawnaie filmów do kolejki +* Lokalne playlisty +* Napisy +* Wsparcie dla livestream'ów +* Wyświetlanie komentarzy + +### Wspierane usługi + +NewPipe wspiera wiele usług. Nasza [dokumentacja](https://teamnewpipe.github.io/documentation/) dostarcza więcej informacji o tym jak nowe usługi mogą zostać dodane do aplikacji i extractora. Proszę skontaktuj się z nami jeśli masz zamiar dodać jakąś nową usługę. Obecnie wspierane usługi to: + +* YouTube +* SoundCloud \[beta\] +* media.ccc.de \[beta\] +* Instancje PeerTube \[beta\] +* Bandcamp \[beta\] + +## Instalacja i aktualizacje +Możesz zainstalować NewPipe za pomocą jednej z tych metod: + 1. Dodaj nasze repozytorium do F-Droid i z tamtąd pobierz NewPipe. Instrukcje znajdują się tutaj: https://newpipe.net/FAQ/tutorials/install-add-fdroid-repo/ + 2. Pobierz APK z [Wydań na GitHubie](https://github.com/TeamNewPipe/NewPipe/releases) i zainstaluj go. + 3. Zaktualizuj poprzez F-Droid. Jest to najwolniejsza metoda aktualizacji, ponieważ F-Droid musi rozpoznać zmiany, zbudować APK, podpisać go i dopiero wypuścić aktualizację do użytkowników. + 4. Zbuduj debug APK samemu. Jest to najszybszy sposób na zdobycie najnowszych funkcji, ale jest to o wiele, wiele bardziej skomplikowane, dlatego rekomendujemy używania jednej z powyższych metod. + +Dla większości użytkowników rekomendujemy metodę 1. Pliki APK zainstalowane za pomocą metod 1 lub 2 są ze sobą kompatybilne, lecz nie są kompatybilne z tymi zainstalowanymi metodą 3. Dzieje się tak ponieważ ten sam (nasz) klucz jest używany do podpisania APK z metod 1 i 2, ale APK z metody 3 podpisany jest innym kluczem (F-Droida). Budowanie debug APK z metody 4 w ogóle nie uwzględnia klucza. Klucze podpisu zapewniają, że użytkownik omylnie nie zainstaluje złośliwej aktualizacji żadnej aplikacji. + +W międzyczasie, jeśli z jakiegoś powodu chcesz zmienić źródło (np. rdzenna funkcjonalność NewPipe psuje się a F-Droid nie ma jeszcze najnowszej aktualizacji), rekomendujemy użyć następującej procedury: +1. Zrób kopię danych wchodząc w Ustawienia > Zawartość > Eksportuj dane, dzięki czemu zachowasz swoją historię, subskrypcje i playlisty +2. Odinstaluj NewPipe +3. Pobierz APK z nowego źródła i zainstaluj go +4. Przywróć dane z kroku 1 wchodząc w Ustawienia > Zawartość > Importuj dane + +## Wkład +Jeśli masz jakieś pomysły, tłumaczenia, zmiany designu, oczyszczony kod, lub wielkie zmiany w kodzie, pomoc jest zawsze mile widziana. +Im więcej jest zrobione, tym lepsza staje się aplikacja! + +Jeśli chcesz pomóc, przeczytaj [Notkę o wkładzie](.github/CONTRIBUTING.md). + + +Translation status + + +## Wesprzyj +Jeśli podoba Ci się NewPipe, bardzo ucieszylibyśmy się z dotacji. Możesz wysłać bitcoin lub przekazać darowiznę przez Bountysource lub Liberapay. Po więcej informacji o darowiznach dla NewPipe, proszę zobacz naszą [stronę](https://newpipe.net/donate). + + + + + + + + + + + + + + + + + +
BitcoinBitcoin QR code16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
LiberapayVisit NewPipe at liberapay.comDonate via Liberapay
BountysourceVisit NewPipe at bountysource.comCheck out how many bounties you can earn.
+ +## Polityka prywatności + +Założeniem projektu NewPipe jest dostarczanie prywatnego, anonimowego dostępu do zasobów i usług internetowych. +Dlatego też, ta aplikacja nie zbiera żadnych informacji bez twojej zgody. Polityka prywatności NewPipe dokładnie wyjaśnia jakie dane są wysyłane i przechowywane, gdy wyślesz raport awarii lub komentarz na naszym blogu. Możesz znaleźć ten dokument [tutaj](https://newpipe.net/legal/privacy/). + +## Licencja +[![GNU GPLv3 Image](https://www.gnu.org/graphics/gplv3-127x51.png)](https://www.gnu.org/licenses/gpl-3.0.en.html) + +NewPipe to wolne oprogramowanie: Możesz używać, uczyć się, udostępniać i ulepszać je do woli. +Możesz udostępniać i/lub modyfikować je na zasadach licencji +[GNU General Public License](https://www.gnu.org/licenses/gpl.html) +publikowaną przez Free Software Foundation, wersję 3 Licencji, lub +(twój wybór) każdną nowszą wersję. diff --git a/README.pt_BR.md b/README.pt_BR.md index 36e44b103..ce2ac38ec 100644 --- a/README.pt_BR.md +++ b/README.pt_BR.md @@ -18,7 +18,7 @@

SiteBlogFAQPress


-*Read this in other languages: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* +*Read this in other languages: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* AVISO: ESTA É UMA VERSÃO BETA, PORTANTO, VOCÊ PODE ENCONTRAR BUGS. ENCONTROU ALGUM, ABRA UM ISSUE ATRAVÉS DO NOSSO REPOSITÓRIO GITHUB. diff --git a/README.ro.md b/README.ro.md index b52339871..71b2ac202 100644 --- a/README.ro.md +++ b/README.ro.md @@ -17,7 +17,7 @@

WebsiteBlogFAQPresă


-*Citiţi în alte limbi: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* +*Citiţi în alte limbi: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* Atenţionare: ACEASTA ESTE O VERSIUNE BETA, AŞA CĂ S-AR PUTE SĂ ÎNTÂLNIŢI ERORI. DACĂ SE ÎNTÂMPLĂ ACEST LUCRU, DESCHIDEŢI UN ISSUE PRIN REPSITORY-UL NOSTRU GITHUB. diff --git a/README.so.md b/README.so.md index 1195b9488..810d8c06d 100644 --- a/README.so.md +++ b/README.so.md @@ -17,7 +17,7 @@

Website-kaMaqaaladaSu'aalaha Aalaa La-iswaydiiyoWarbaahinta


-*Ku akhri luuqad kale: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* +*Ku akhri luuqad kale: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* DIGNIIN: MIDKAN, NOOCA APP-KA EE HADDA WALI TIJAABO AYUU KU JIRAA, SIDAA DARTEED CILLADO AYAAD LA KULMI KARTAA. HADAAD LA KULANTO, KA FUR ARIN SHARAXAYA QAYBTANADA ARRIMAHA EE GITHUB-KA. diff --git a/README.tr.md b/README.tr.md index a0d231cf8..b3391f038 100644 --- a/README.tr.md +++ b/README.tr.md @@ -17,7 +17,7 @@

Web sitesiBlogSSSBasın


-*Bu sayfayı diğer dillerde okuyun: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* +*Bu sayfayı diğer dillerde okuyun: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* UYARI: BU SÜRÜM BETA SÜRÜMÜDÜR, BU NEDENLE HATALARLA KARŞILAŞABİLİRSİNİZ. HATA BULURSANIZ BU GITHUB DEPOSUNDA BUNU BİLDİRİN. diff --git a/README.zh_TW.md b/README.zh_TW.md index e4d9d375d..fdafeb3b9 100644 --- a/README.zh_TW.md +++ b/README.zh_TW.md @@ -17,7 +17,7 @@

網站部落格FAQ媒體


-*其他語言: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md)* +*其他語言: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md)* 警告:這是測試版本,可能會發生錯誤。如果遇到錯誤,請在我們的 GITHUB REPO 開 ISSUE 回報。 From 651b79d3ed6372715fde1b9318e5ec18061541a7 Mon Sep 17 00:00:00 2001 From: TiA4f8R <74829229+TiA4f8R@users.noreply.github.com> Date: Sat, 15 Jan 2022 13:42:48 +0100 Subject: [PATCH 095/119] Catch properly BehindLiveWindowExceptions Instead of trying to reload the play queue manager and then throwing an error, BehindLiveWindowExceptions now make the app seek to the default playback position, like recommended by ExoPlayer. The buffering state is shown in this case. Error handling of other exceptions is not changed. --- .../org/schabi/newpipe/player/Player.java | 71 +++++++++++++------ 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 993357ac4..179486bb1 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -2517,8 +2517,34 @@ public final class Player implements Log.e(TAG, "ExoPlayer - onPlayerError() called with:", error); saveStreamProgressState(); + boolean isBehindLiveWindowException = false; - // create error notification + switch (error.type) { + case ExoPlaybackException.TYPE_SOURCE: + isBehindLiveWindowException = processSourceError(error.getSourceException()); + if (!isBehindLiveWindowException) { + createErrorNotification(error); + } + break; + case ExoPlaybackException.TYPE_UNEXPECTED: + createErrorNotification(error); + setRecovery(); + reloadPlayQueueManager(); + break; + case ExoPlaybackException.TYPE_REMOTE: + case ExoPlaybackException.TYPE_RENDERER: + default: + createErrorNotification(error); + onPlaybackShutdown(); + break; + } + + if (fragmentListener != null && !isBehindLiveWindowException) { + fragmentListener.onPlayerError(error); + } + } + + private void createErrorNotification(@NonNull final ExoPlaybackException error) { final ErrorInfo errorInfo; if (currentMetadata == null) { errorInfo = new ErrorInfo(error, UserAction.PLAY_STREAM, @@ -2530,37 +2556,36 @@ public final class Player implements currentMetadata.getMetadata()); } ErrorUtil.createNotification(context, errorInfo); - - switch (error.type) { - case ExoPlaybackException.TYPE_SOURCE: - processSourceError(error.getSourceException()); - break; - case ExoPlaybackException.TYPE_UNEXPECTED: - setRecovery(); - reloadPlayQueueManager(); - break; - case ExoPlaybackException.TYPE_REMOTE: - case ExoPlaybackException.TYPE_RENDERER: - default: - onPlaybackShutdown(); - break; - } - - if (fragmentListener != null) { - fragmentListener.onPlayerError(error); - } } - private void processSourceError(final IOException error) { + /** + * Process an {@link IOException} returned by {@link ExoPlaybackException#getSourceException()} + * for {@link ExoPlaybackException#TYPE_SOURCE} exceptions. + * + *

+ * This method sets the recovery position and sends an error message to the play queue if the + * exception is not a {@link BehindLiveWindowException}. + *

+ * @param error the source error which was thrown by ExoPlayer + * @return whether the exception thrown is a {@link BehindLiveWindowException} ({@code false} + * is always returned if ExoPlayer or the play queue is null) + */ + private boolean processSourceError(final IOException error) { if (exoPlayerIsNull() || playQueue == null) { - return; + return false; } + setRecovery(); if (error instanceof BehindLiveWindowException) { - reloadPlayQueueManager(); + simpleExoPlayer.seekToDefaultPosition(); + simpleExoPlayer.prepare(); + // Inform the user that we are reloading the stream by switching to the buffering state + onBuffering(); + return true; } else { playQueue.error(); + return false; } } //endregion From 94f774b82d1659ae5ef07b6c0a0789d310d2e779 Mon Sep 17 00:00:00 2001 From: TiA4f8R <74829229+TiA4f8R@users.noreply.github.com> Date: Sat, 15 Jan 2022 13:50:35 +0100 Subject: [PATCH 096/119] Use a custom HlsPlaylistTracker, based on DefaultHlsPlaylistTracker to allow more stucking on HLS livestreams ExoPlayer's default behavior is to use a multiplication of target segment by a coefficient (3,5). This coefficient (and this behavior) cannot be customized without using a custom HlsPlaylistTracker right now. New behavior is to wait 15 seconds before throwing a PlaylistStuckException. This should improve a lot HLS live streaming on (very) low-latency livestreams with buffering issues, especially on YouTube with their HLS manifests. --- .../player/helper/PlayerDataSource.java | 7 +- .../playback/CustomHlsPlaylistTracker.java | 782 ++++++++++++++++++ 2 files changed, 787 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/player/playback/CustomHlsPlaylistTracker.java diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java index 708b72ff2..1fce25e78 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java @@ -16,6 +16,8 @@ import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy; import com.google.android.exoplayer2.upstream.TransferListener; +import org.schabi.newpipe.player.playback.CustomHlsPlaylistTracker; + public class PlayerDataSource { private static final int MANIFEST_MINIMUM_RETRY = 5; private static final int EXTRACTOR_MINIMUM_RETRY = Integer.MAX_VALUE; @@ -44,8 +46,9 @@ public class PlayerDataSource { public HlsMediaSource.Factory getLiveHlsMediaSourceFactory() { return new HlsMediaSource.Factory(cachelessDataSourceFactory) .setAllowChunklessPreparation(true) - .setLoadErrorHandlingPolicy( - new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY)); + .setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy( + MANIFEST_MINIMUM_RETRY)) + .setPlaylistTrackerFactory(CustomHlsPlaylistTracker.FACTORY); } public DashMediaSource.Factory getLiveDashMediaSourceFactory() { diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/CustomHlsPlaylistTracker.java b/app/src/main/java/org/schabi/newpipe/player/playback/CustomHlsPlaylistTracker.java new file mode 100644 index 000000000..28f6b01fe --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/player/playback/CustomHlsPlaylistTracker.java @@ -0,0 +1,782 @@ +/* + * Original source code (DefaultHlsPlaylistTracker): Copyright (C) 2016 The Android Open Source + * Project + * + * Original source code licensed under the Apache License, Version 2.0 (the "License"); + * you may not use the original source code of this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.schabi.newpipe.player.playback; + +import static com.google.android.exoplayer2.util.Assertions.checkNotNull; +import static com.google.android.exoplayer2.util.Util.castNonNull; +import static java.lang.Math.max; + +import android.net.Uri; +import android.os.Handler; +import android.os.SystemClock; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.ParserException; +import com.google.android.exoplayer2.source.LoadEventInfo; +import com.google.android.exoplayer2.source.MediaLoadData; +import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; +import com.google.android.exoplayer2.source.hls.HlsDataSourceFactory; +import com.google.android.exoplayer2.source.hls.playlist.DefaultHlsPlaylistTracker; +import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist; +import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.Variant; +import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist; +import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Part; +import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.RenditionReport; +import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment; +import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylist; +import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParser; +import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParserFactory; +import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker; +import com.google.android.exoplayer2.upstream.DataSource; +import com.google.android.exoplayer2.upstream.HttpDataSource; +import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy; +import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.LoadErrorInfo; +import com.google.android.exoplayer2.upstream.Loader; +import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction; +import com.google.android.exoplayer2.upstream.ParsingLoadable; +import com.google.android.exoplayer2.util.Assertions; +import com.google.android.exoplayer2.util.Util; +import com.google.common.collect.Iterables; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * NewPipe's implementation for {@link HlsPlaylistTracker}, based on + * {@link DefaultHlsPlaylistTracker}. + * + *

+ * It redefines the way of how + * {@link PlaylistStuckException PlaylistStuckExceptions} are thrown: instead of + * using a multiplication between the target duration of segments and + * {@link DefaultHlsPlaylistTracker#DEFAULT_PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT}, it uses a + * constant value (see {@link #MAXIMUM_PLAYLIST_STUCK_DURATION_MS}), in order to reduce the number + * of this exception thrown, especially on (very) low-latency livestreams. + *

+ */ +public final class CustomHlsPlaylistTracker implements HlsPlaylistTracker, + Loader.Callback> { + + /** + * Factory for {@link CustomHlsPlaylistTracker} instances. + */ + public static final Factory FACTORY = CustomHlsPlaylistTracker::new; + + /** + * The maximum duration before a {@link PlaylistStuckException} is thrown, in milliseconds. + */ + private static final double MAXIMUM_PLAYLIST_STUCK_DURATION_MS = 15000; + + private final HlsDataSourceFactory dataSourceFactory; + private final HlsPlaylistParserFactory playlistParserFactory; + private final LoadErrorHandlingPolicy loadErrorHandlingPolicy; + private final HashMap playlistBundles; + private final List listeners; + + @Nullable + private EventDispatcher eventDispatcher; + @Nullable + private Loader initialPlaylistLoader; + @Nullable + private Handler playlistRefreshHandler; + @Nullable + private PrimaryPlaylistListener primaryPlaylistListener; + @Nullable + private HlsMasterPlaylist masterPlaylist; + @Nullable + private Uri primaryMediaPlaylistUrl; + @Nullable + private HlsMediaPlaylist primaryMediaPlaylistSnapshot; + private boolean isLive; + private long initialStartTimeUs; + + /** + * Creates an instance. + * + * @param dataSourceFactory A factory for {@link DataSource} instances. + * @param loadErrorHandlingPolicy The {@link LoadErrorHandlingPolicy}. + * @param playlistParserFactory An {@link HlsPlaylistParserFactory}. + */ + public CustomHlsPlaylistTracker(final HlsDataSourceFactory dataSourceFactory, + final LoadErrorHandlingPolicy loadErrorHandlingPolicy, + final HlsPlaylistParserFactory playlistParserFactory) { + this.dataSourceFactory = dataSourceFactory; + this.playlistParserFactory = playlistParserFactory; + this.loadErrorHandlingPolicy = loadErrorHandlingPolicy; + listeners = new ArrayList<>(); + playlistBundles = new HashMap<>(); + initialStartTimeUs = C.TIME_UNSET; + } + + // HlsPlaylistTracker implementation. + + @Override + public void start(@NonNull final Uri initialPlaylistUri, + @NonNull final EventDispatcher eventDispatcherObject, + @NonNull final PrimaryPlaylistListener primaryPlaylistListenerObject) { + this.playlistRefreshHandler = Util.createHandlerForCurrentLooper(); + this.eventDispatcher = eventDispatcherObject; + this.primaryPlaylistListener = primaryPlaylistListenerObject; + final ParsingLoadable masterPlaylistLoadable = new ParsingLoadable<>( + dataSourceFactory.createDataSource(C.DATA_TYPE_MANIFEST), + initialPlaylistUri, + C.DATA_TYPE_MANIFEST, + playlistParserFactory.createPlaylistParser()); + Assertions.checkState(initialPlaylistLoader == null); + initialPlaylistLoader = new Loader("CustomHlsPlaylistTracker:MasterPlaylist"); + final long elapsedRealtime = initialPlaylistLoader.startLoading(masterPlaylistLoadable, + this, loadErrorHandlingPolicy.getMinimumLoadableRetryCount( + masterPlaylistLoadable.type)); + eventDispatcherObject.loadStarted(new LoadEventInfo(masterPlaylistLoadable.loadTaskId, + masterPlaylistLoadable.dataSpec, elapsedRealtime), + masterPlaylistLoadable.type); + } + + @Override + public void stop() { + primaryMediaPlaylistUrl = null; + primaryMediaPlaylistSnapshot = null; + masterPlaylist = null; + initialStartTimeUs = C.TIME_UNSET; + initialPlaylistLoader.release(); + initialPlaylistLoader = null; + for (final MediaPlaylistBundle bundle : playlistBundles.values()) { + bundle.release(); + } + playlistRefreshHandler.removeCallbacksAndMessages(null); + playlistRefreshHandler = null; + playlistBundles.clear(); + } + + @Override + public void addListener(@NonNull final PlaylistEventListener listener) { + checkNotNull(listener); + listeners.add(listener); + } + + @Override + public void removeListener(@NonNull final PlaylistEventListener listener) { + listeners.remove(listener); + } + + @Override + @Nullable + public HlsMasterPlaylist getMasterPlaylist() { + return masterPlaylist; + } + + @Override + @Nullable + public HlsMediaPlaylist getPlaylistSnapshot(@NonNull final Uri url, + final boolean isForPlayback) { + final HlsMediaPlaylist snapshot = playlistBundles.get(url).getPlaylistSnapshot(); + if (snapshot != null && isForPlayback) { + maybeSetPrimaryUrl(url); + } + return snapshot; + } + + @Override + public long getInitialStartTimeUs() { + return initialStartTimeUs; + } + + @Override + public boolean isSnapshotValid(@NonNull final Uri url) { + return playlistBundles.get(url).isSnapshotValid(); + } + + @Override + public void maybeThrowPrimaryPlaylistRefreshError() throws IOException { + if (initialPlaylistLoader != null) { + initialPlaylistLoader.maybeThrowError(); + } + if (primaryMediaPlaylistUrl != null) { + maybeThrowPlaylistRefreshError(primaryMediaPlaylistUrl); + } + } + + @Override + public void maybeThrowPlaylistRefreshError(@NonNull final Uri url) throws IOException { + playlistBundles.get(url).maybeThrowPlaylistRefreshError(); + } + + @Override + public void refreshPlaylist(@NonNull final Uri url) { + playlistBundles.get(url).loadPlaylist(); + } + + @Override + public boolean isLive() { + return isLive; + } + + // Loader.Callback implementation. + + @Override + public void onLoadCompleted(@NonNull final ParsingLoadable loadable, + final long elapsedRealtimeMs, + final long loadDurationMs) { + final HlsPlaylist result = loadable.getResult(); + final HlsMasterPlaylist newMasterPlaylist; + final boolean isMediaPlaylist = result instanceof HlsMediaPlaylist; + if (isMediaPlaylist) { + newMasterPlaylist = HlsMasterPlaylist.createSingleVariantMasterPlaylist( + result.baseUri); + } else { // result instanceof HlsMasterPlaylist + newMasterPlaylist = (HlsMasterPlaylist) result; + } + this.masterPlaylist = newMasterPlaylist; + primaryMediaPlaylistUrl = newMasterPlaylist.variants.get(0).url; + createBundles(newMasterPlaylist.mediaPlaylistUrls); + final LoadEventInfo loadEventInfo = new LoadEventInfo(loadable.loadTaskId, + loadable.dataSpec, loadable.getUri(), loadable.getResponseHeaders(), + elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); + final MediaPlaylistBundle primaryBundle = playlistBundles.get(primaryMediaPlaylistUrl); + if (isMediaPlaylist) { + // We don't need to load the playlist again. We can use the same result. + primaryBundle.processLoadedPlaylist((HlsMediaPlaylist) result, loadEventInfo); + } else { + primaryBundle.loadPlaylist(); + } + loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId); + eventDispatcher.loadCompleted(loadEventInfo, C.DATA_TYPE_MANIFEST); + } + + @Override + public void onLoadCanceled(@NonNull final ParsingLoadable loadable, + final long elapsedRealtimeMs, + final long loadDurationMs, + final boolean released) { + final LoadEventInfo loadEventInfo = new LoadEventInfo(loadable.loadTaskId, + loadable.dataSpec, loadable.getUri(), loadable.getResponseHeaders(), + elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); + loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId); + eventDispatcher.loadCanceled(loadEventInfo, C.DATA_TYPE_MANIFEST); + } + + @Override + public LoadErrorAction onLoadError(@NonNull final ParsingLoadable loadable, + final long elapsedRealtimeMs, + final long loadDurationMs, + final IOException error, + final int errorCount) { + final LoadEventInfo loadEventInfo = new LoadEventInfo(loadable.loadTaskId, + loadable.dataSpec, loadable.getUri(), loadable.getResponseHeaders(), + elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); + final MediaLoadData mediaLoadData = new MediaLoadData(loadable.type); + final long retryDelayMs = loadErrorHandlingPolicy.getRetryDelayMsFor(new LoadErrorInfo( + loadEventInfo, mediaLoadData, error, errorCount)); + final boolean isFatal = retryDelayMs == C.TIME_UNSET; + eventDispatcher.loadError(loadEventInfo, loadable.type, error, isFatal); + if (isFatal) { + loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId); + } + return isFatal ? Loader.DONT_RETRY_FATAL : Loader.createRetryAction(false, retryDelayMs); + } + + // Internal methods. + + private boolean maybeSelectNewPrimaryUrl() { + final List variants = masterPlaylist.variants; + final int variantsSize = variants.size(); + final long currentTimeMs = SystemClock.elapsedRealtime(); + for (int i = 0; i < variantsSize; i++) { + final MediaPlaylistBundle bundle = checkNotNull(playlistBundles.get( + variants.get(i).url)); + if (currentTimeMs > bundle.excludeUntilMs) { + primaryMediaPlaylistUrl = bundle.playlistUrl; + bundle.loadPlaylistInternal(getRequestUriForPrimaryChange( + primaryMediaPlaylistUrl)); + return true; + } + } + return false; + } + + private void maybeSetPrimaryUrl(@NonNull final Uri url) { + if (url.equals(primaryMediaPlaylistUrl) || !isVariantUrl(url) + || (primaryMediaPlaylistSnapshot != null + && primaryMediaPlaylistSnapshot.hasEndTag)) { + // Ignore if the primary media playlist URL is unchanged, if the media playlist is not + // referenced directly by a variant, or it the last primary snapshot contains an end + // tag. + return; + } + primaryMediaPlaylistUrl = url; + final MediaPlaylistBundle newPrimaryBundle = playlistBundles.get(primaryMediaPlaylistUrl); + final HlsMediaPlaylist newPrimarySnapshot = newPrimaryBundle.playlistSnapshot; + if (newPrimarySnapshot != null && newPrimarySnapshot.hasEndTag) { + primaryMediaPlaylistSnapshot = newPrimarySnapshot; + primaryPlaylistListener.onPrimaryPlaylistRefreshed(newPrimarySnapshot); + } else { + // The snapshot for the new primary media playlist URL may be stale. Defer updating the + // primary snapshot until after we've refreshed it. + newPrimaryBundle.loadPlaylistInternal(getRequestUriForPrimaryChange(url)); + } + } + + private Uri getRequestUriForPrimaryChange(@NonNull final Uri newPrimaryPlaylistUri) { + if (primaryMediaPlaylistSnapshot != null + && primaryMediaPlaylistSnapshot.serverControl.canBlockReload) { + final RenditionReport renditionReport = primaryMediaPlaylistSnapshot.renditionReports + .get(newPrimaryPlaylistUri); + if (renditionReport != null) { + final Uri.Builder uriBuilder = newPrimaryPlaylistUri.buildUpon(); + uriBuilder.appendQueryParameter(MediaPlaylistBundle.BLOCK_MSN_PARAM, + String.valueOf(renditionReport.lastMediaSequence)); + if (renditionReport.lastPartIndex != C.INDEX_UNSET) { + uriBuilder.appendQueryParameter(MediaPlaylistBundle.BLOCK_PART_PARAM, + String.valueOf(renditionReport.lastPartIndex)); + } + return uriBuilder.build(); + } + } + return newPrimaryPlaylistUri; + } + + /** + * @return whether any of the variants in the master playlist have the specified playlist URL. + * @param playlistUrl the playlist URL to test + */ + private boolean isVariantUrl(final Uri playlistUrl) { + final List variants = masterPlaylist.variants; + final int variantsSize = variants.size(); + for (int i = 0; i < variantsSize; i++) { + if (playlistUrl.equals(variants.get(i).url)) { + return true; + } + } + return false; + } + + private void createBundles(@NonNull final List urls) { + final int listSize = urls.size(); + for (int i = 0; i < listSize; i++) { + final Uri url = urls.get(i); + final MediaPlaylistBundle bundle = new MediaPlaylistBundle(url); + playlistBundles.put(url, bundle); + } + } + + /** + * Called by the bundles when a snapshot changes. + * + * @param url The url of the playlist. + * @param newSnapshot The new snapshot. + */ + private void onPlaylistUpdated(@NonNull final Uri url, final HlsMediaPlaylist newSnapshot) { + if (url.equals(primaryMediaPlaylistUrl)) { + if (primaryMediaPlaylistSnapshot == null) { + // This is the first primary URL snapshot. + isLive = !newSnapshot.hasEndTag; + initialStartTimeUs = newSnapshot.startTimeUs; + } + primaryMediaPlaylistSnapshot = newSnapshot; + primaryPlaylistListener.onPrimaryPlaylistRefreshed(newSnapshot); + } + final int listenersSize = listeners.size(); + for (int i = 0; i < listenersSize; i++) { + listeners.get(i).onPlaylistChanged(); + } + } + + private boolean notifyPlaylistError(final Uri playlistUrl, final long exclusionDurationMs) { + final int listenersSize = listeners.size(); + boolean anyExclusionFailed = false; + for (int i = 0; i < listenersSize; i++) { + anyExclusionFailed |= !listeners.get(i).onPlaylistError(playlistUrl, + exclusionDurationMs); + } + return anyExclusionFailed; + } + + private HlsMediaPlaylist getLatestPlaylistSnapshot( + @Nullable final HlsMediaPlaylist oldPlaylist, + @NonNull final HlsMediaPlaylist loadedPlaylist) { + if (!loadedPlaylist.isNewerThan(oldPlaylist)) { + if (loadedPlaylist.hasEndTag) { + // If the loaded playlist has an end tag but is not newer than the old playlist + // then we have an inconsistent state. This is typically caused by the server + // incorrectly resetting the media sequence when appending the end tag. We resolve + // this case as best we can by returning the old playlist with the end tag + // appended. + return oldPlaylist.copyWithEndTag(); + } else { + return oldPlaylist; + } + } + final long startTimeUs = getLoadedPlaylistStartTimeUs(oldPlaylist, loadedPlaylist); + final int discontinuitySequence = getLoadedPlaylistDiscontinuitySequence(oldPlaylist, + loadedPlaylist); + return loadedPlaylist.copyWith(startTimeUs, discontinuitySequence); + } + + private long getLoadedPlaylistStartTimeUs(@Nullable final HlsMediaPlaylist oldPlaylist, + @NonNull final HlsMediaPlaylist loadedPlaylist) { + if (loadedPlaylist.hasProgramDateTime) { + return loadedPlaylist.startTimeUs; + } + final long primarySnapshotStartTimeUs = primaryMediaPlaylistSnapshot != null + ? primaryMediaPlaylistSnapshot.startTimeUs : 0; + if (oldPlaylist == null) { + return primarySnapshotStartTimeUs; + } + final Segment firstOldOverlappingSegment = getFirstOldOverlappingSegment(oldPlaylist, + loadedPlaylist); + if (firstOldOverlappingSegment != null) { + return oldPlaylist.startTimeUs + firstOldOverlappingSegment.relativeStartTimeUs; + } else if (oldPlaylist.segments.size() == loadedPlaylist.mediaSequence + - oldPlaylist.mediaSequence) { + return oldPlaylist.getEndTimeUs(); + } else { + // No segments overlap, we assume the new playlist start coincides with the primary + // playlist. + return primarySnapshotStartTimeUs; + } + } + + private int getLoadedPlaylistDiscontinuitySequence( + @Nullable final HlsMediaPlaylist oldPlaylist, + @NonNull final HlsMediaPlaylist loadedPlaylist) { + if (loadedPlaylist.hasDiscontinuitySequence) { + return loadedPlaylist.discontinuitySequence; + } + // TODO: Improve cross-playlist discontinuity adjustment. + final int primaryUrlDiscontinuitySequence = primaryMediaPlaylistSnapshot != null + ? primaryMediaPlaylistSnapshot.discontinuitySequence : 0; + if (oldPlaylist == null) { + return primaryUrlDiscontinuitySequence; + } + final Segment firstOldOverlappingSegment = getFirstOldOverlappingSegment(oldPlaylist, + loadedPlaylist); + if (firstOldOverlappingSegment != null) { + return oldPlaylist.discontinuitySequence + + firstOldOverlappingSegment.relativeDiscontinuitySequence + - loadedPlaylist.segments.get(0).relativeDiscontinuitySequence; + } + return primaryUrlDiscontinuitySequence; + } + + @Nullable + private static Segment getFirstOldOverlappingSegment( + @NonNull final HlsMediaPlaylist oldPlaylist, + @NonNull final HlsMediaPlaylist loadedPlaylist) { + final int mediaSequenceOffset = (int) (loadedPlaylist.mediaSequence + - oldPlaylist.mediaSequence); + final List oldSegments = oldPlaylist.segments; + return mediaSequenceOffset < oldSegments.size() ? oldSegments.get(mediaSequenceOffset) + : null; + } + + /** + * Hold all information related to a specific Media Playlist. + */ + private final class MediaPlaylistBundle + implements Loader.Callback> { + + private static final String BLOCK_MSN_PARAM = "_HLS_msn"; + private static final String BLOCK_PART_PARAM = "_HLS_part"; + private static final String SKIP_PARAM = "_HLS_skip"; + + private final Uri playlistUrl; + private final Loader mediaPlaylistLoader; + private final DataSource mediaPlaylistDataSource; + + @Nullable + private HlsMediaPlaylist playlistSnapshot; + private long lastSnapshotLoadMs; + private long lastSnapshotChangeMs; + private long earliestNextLoadTimeMs; + private long excludeUntilMs; + private boolean loadPending; + @Nullable + private IOException playlistError; + + MediaPlaylistBundle(final Uri playlistUrl) { + this.playlistUrl = playlistUrl; + mediaPlaylistLoader = new Loader("CustomHlsPlaylistTracker:MediaPlaylist"); + mediaPlaylistDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_MANIFEST); + } + + @Nullable + public HlsMediaPlaylist getPlaylistSnapshot() { + return playlistSnapshot; + } + + public boolean isSnapshotValid() { + if (playlistSnapshot == null) { + return false; + } + final long currentTimeMs = SystemClock.elapsedRealtime(); + final long snapshotValidityDurationMs = max(30000, C.usToMs( + playlistSnapshot.durationUs)); + return playlistSnapshot.hasEndTag + || playlistSnapshot.playlistType == HlsMediaPlaylist.PLAYLIST_TYPE_EVENT + || playlistSnapshot.playlistType == HlsMediaPlaylist.PLAYLIST_TYPE_VOD + || lastSnapshotLoadMs + snapshotValidityDurationMs > currentTimeMs; + } + + public void loadPlaylist() { + loadPlaylistInternal(playlistUrl); + } + + public void maybeThrowPlaylistRefreshError() throws IOException { + mediaPlaylistLoader.maybeThrowError(); + if (playlistError != null) { + throw playlistError; + } + } + + public void release() { + mediaPlaylistLoader.release(); + } + + // Loader.Callback implementation. + + @Override + public void onLoadCompleted(@NonNull final ParsingLoadable loadable, + final long elapsedRealtimeMs, + final long loadDurationMs) { + final HlsPlaylist result = loadable.getResult(); + final LoadEventInfo loadEventInfo = new LoadEventInfo(loadable.loadTaskId, + loadable.dataSpec, loadable.getUri(), loadable.getResponseHeaders(), + elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); + if (result instanceof HlsMediaPlaylist) { + processLoadedPlaylist((HlsMediaPlaylist) result, loadEventInfo); + eventDispatcher.loadCompleted(loadEventInfo, C.DATA_TYPE_MANIFEST); + } else { + playlistError = new ParserException("Loaded playlist has unexpected type."); + eventDispatcher.loadError( + loadEventInfo, C.DATA_TYPE_MANIFEST, playlistError, true); + } + loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId); + } + + @Override + public void onLoadCanceled(@NonNull final ParsingLoadable loadable, + final long elapsedRealtimeMs, + final long loadDurationMs, + final boolean released) { + final LoadEventInfo loadEventInfo = new LoadEventInfo(loadable.loadTaskId, + loadable.dataSpec, loadable.getUri(), loadable.getResponseHeaders(), + elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); + loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId); + eventDispatcher.loadCanceled(loadEventInfo, C.DATA_TYPE_MANIFEST); + } + + @Override + public LoadErrorAction onLoadError(@NonNull final ParsingLoadable loadable, + final long elapsedRealtimeMs, + final long loadDurationMs, + final IOException error, + final int errorCount) { + final LoadEventInfo loadEventInfo = new LoadEventInfo(loadable.loadTaskId, + loadable.dataSpec, loadable.getUri(), loadable.getResponseHeaders(), + elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); + final boolean isBlockingRequest = loadable.getUri().getQueryParameter(BLOCK_MSN_PARAM) + != null; + final boolean deltaUpdateFailed = error instanceof HlsPlaylistParser + .DeltaUpdateException; + if (isBlockingRequest || deltaUpdateFailed) { + int responseCode = Integer.MAX_VALUE; + if (error instanceof HttpDataSource.InvalidResponseCodeException) { + responseCode = ((HttpDataSource.InvalidResponseCodeException) error) + .responseCode; + } + if (deltaUpdateFailed || responseCode == 400 || responseCode == 503) { + // Intercept failed delta updates and blocking requests producing a Bad Request + // (400) and Service Unavailable (503). In such cases, force a full, + // non-blocking request (see RFC 8216, section 6.2.5.2 and 6.3.7). + earliestNextLoadTimeMs = SystemClock.elapsedRealtime(); + loadPlaylist(); + castNonNull(eventDispatcher).loadError(loadEventInfo, loadable.type, error, + true); + return Loader.DONT_RETRY; + } + } + final MediaLoadData mediaLoadData = new MediaLoadData(loadable.type); + final LoadErrorInfo loadErrorInfo = new LoadErrorInfo(loadEventInfo, mediaLoadData, + error, errorCount); + final LoadErrorAction loadErrorAction; + final long exclusionDurationMs = loadErrorHandlingPolicy.getBlacklistDurationMsFor( + loadErrorInfo); + final boolean shouldExclude = exclusionDurationMs != C.TIME_UNSET; + + boolean exclusionFailed = notifyPlaylistError(playlistUrl, exclusionDurationMs) + || !shouldExclude; + if (shouldExclude) { + exclusionFailed |= excludePlaylist(exclusionDurationMs); + } + + if (exclusionFailed) { + final long retryDelay = loadErrorHandlingPolicy.getRetryDelayMsFor(loadErrorInfo); + loadErrorAction = retryDelay != C.TIME_UNSET + ? Loader.createRetryAction(false, retryDelay) + : Loader.DONT_RETRY_FATAL; + } else { + loadErrorAction = Loader.DONT_RETRY; + } + + final boolean wasCanceled = !loadErrorAction.isRetry(); + eventDispatcher.loadError(loadEventInfo, loadable.type, error, wasCanceled); + if (wasCanceled) { + loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId); + } + return loadErrorAction; + } + + // Internal methods. + + private void loadPlaylistInternal(@NonNull final Uri playlistRequestUri) { + excludeUntilMs = 0; + if (loadPending || mediaPlaylistLoader.isLoading() + || mediaPlaylistLoader.hasFatalError()) { + // Load already pending, in progress, or a fatal error has been encountered. Do + // nothing. + return; + } + final long currentTimeMs = SystemClock.elapsedRealtime(); + if (currentTimeMs < earliestNextLoadTimeMs) { + loadPending = true; + playlistRefreshHandler.postDelayed( + () -> { + loadPending = false; + loadPlaylistImmediately(playlistRequestUri); + }, + earliestNextLoadTimeMs - currentTimeMs); + } else { + loadPlaylistImmediately(playlistRequestUri); + } + } + + private void loadPlaylistImmediately(@NonNull final Uri playlistRequestUri) { + final ParsingLoadable.Parser mediaPlaylistParser = playlistParserFactory + .createPlaylistParser(masterPlaylist, playlistSnapshot); + final ParsingLoadable mediaPlaylistLoadable = new ParsingLoadable<>( + mediaPlaylistDataSource, playlistRequestUri, C.DATA_TYPE_MANIFEST, + mediaPlaylistParser); + final long elapsedRealtime = mediaPlaylistLoader.startLoading(mediaPlaylistLoadable, + this, loadErrorHandlingPolicy.getMinimumLoadableRetryCount( + mediaPlaylistLoadable.type)); + eventDispatcher.loadStarted(new LoadEventInfo(mediaPlaylistLoadable.loadTaskId, + mediaPlaylistLoadable.dataSpec, elapsedRealtime), + mediaPlaylistLoadable.type); + } + + private void processLoadedPlaylist(final HlsMediaPlaylist loadedPlaylist, + final LoadEventInfo loadEventInfo) { + final HlsMediaPlaylist oldPlaylist = playlistSnapshot; + final long currentTimeMs = SystemClock.elapsedRealtime(); + lastSnapshotLoadMs = currentTimeMs; + playlistSnapshot = getLatestPlaylistSnapshot(oldPlaylist, loadedPlaylist); + if (playlistSnapshot != oldPlaylist) { + playlistError = null; + lastSnapshotChangeMs = currentTimeMs; + onPlaylistUpdated(playlistUrl, playlistSnapshot); + } else if (!playlistSnapshot.hasEndTag) { + if (loadedPlaylist.mediaSequence + loadedPlaylist.segments.size() + < playlistSnapshot.mediaSequence) { + // TODO: Allow customization of playlist resets handling. + // The media sequence jumped backwards. The server has probably reset. We do + // not try excluding in this case. + playlistError = new PlaylistResetException(playlistUrl); + notifyPlaylistError(playlistUrl, C.TIME_UNSET); + } else if (currentTimeMs - lastSnapshotChangeMs + > MAXIMUM_PLAYLIST_STUCK_DURATION_MS) { + // TODO: Allow customization of stuck playlists handling. + playlistError = new PlaylistStuckException(playlistUrl); + final LoadErrorInfo loadErrorInfo = new LoadErrorInfo(loadEventInfo, + new MediaLoadData(C.DATA_TYPE_MANIFEST), + playlistError, 1); + final long exclusionDurationMs = loadErrorHandlingPolicy + .getBlacklistDurationMsFor(loadErrorInfo); + notifyPlaylistError(playlistUrl, exclusionDurationMs); + if (exclusionDurationMs != C.TIME_UNSET) { + excludePlaylist(exclusionDurationMs); + } + } + } + long durationUntilNextLoadUs = 0L; + if (!playlistSnapshot.serverControl.canBlockReload) { + // If blocking requests are not supported, do not allow the playlist to load again + // within the target duration if we obtained a new snapshot, or half the target + // duration otherwise. + durationUntilNextLoadUs = playlistSnapshot != oldPlaylist + ? playlistSnapshot.targetDurationUs + : (playlistSnapshot.targetDurationUs / 2); + } + earliestNextLoadTimeMs = currentTimeMs + C.usToMs(durationUntilNextLoadUs); + // Schedule a load if this is the primary playlist or a playlist of a low-latency + // stream and it doesn't have an end tag. Else the next load will be scheduled when + // refreshPlaylist is called, or when this playlist becomes the primary. + final boolean scheduleLoad = playlistSnapshot.partTargetDurationUs != C.TIME_UNSET + || playlistUrl.equals(primaryMediaPlaylistUrl); + if (scheduleLoad && !playlistSnapshot.hasEndTag) { + loadPlaylistInternal(getMediaPlaylistUriForReload()); + } + } + + private Uri getMediaPlaylistUriForReload() { + if (playlistSnapshot == null + || (playlistSnapshot.serverControl.skipUntilUs == C.TIME_UNSET + && !playlistSnapshot.serverControl.canBlockReload)) { + return playlistUrl; + } + final Uri.Builder uriBuilder = playlistUrl.buildUpon(); + if (playlistSnapshot.serverControl.canBlockReload) { + final long targetMediaSequence = playlistSnapshot.mediaSequence + + playlistSnapshot.segments.size(); + uriBuilder.appendQueryParameter(BLOCK_MSN_PARAM, String.valueOf( + targetMediaSequence)); + if (playlistSnapshot.partTargetDurationUs != C.TIME_UNSET) { + final List trailingParts = playlistSnapshot.trailingParts; + int targetPartIndex = trailingParts.size(); + if (!trailingParts.isEmpty() && Iterables.getLast(trailingParts).isPreload) { + // Ignore the preload part. + targetPartIndex--; + } + uriBuilder.appendQueryParameter(BLOCK_PART_PARAM, String.valueOf( + targetPartIndex)); + } + } + if (playlistSnapshot.serverControl.skipUntilUs != C.TIME_UNSET) { + uriBuilder.appendQueryParameter(SKIP_PARAM, + playlistSnapshot.serverControl.canSkipDateRanges ? "v2" : "YES"); + } + return uriBuilder.build(); + } + + /** + * Exclude the playlist. + * + * @param exclusionDurationMs The number of milliseconds for which the playlist should be + * excluded. + * @return Whether the playlist is the primary, despite being excluded. + */ + private boolean excludePlaylist(final long exclusionDurationMs) { + excludeUntilMs = SystemClock.elapsedRealtime() + exclusionDurationMs; + return playlistUrl.equals(primaryMediaPlaylistUrl) && !maybeSelectNewPrimaryUrl(); + } + } +} From d0637a883236349f087ab11a1001729a123b1ca3 Mon Sep 17 00:00:00 2001 From: TiA4f8R <74829229+TiA4f8R@users.noreply.github.com> Date: Sat, 15 Jan 2022 21:03:37 +0100 Subject: [PATCH 097/119] Suppress SonarLint NullPointerException warnings in CustomHlsPlaylistTracker They seem to be wrong, by looking at the class work and at the return of CustomHlsPlaylistTracker's methods. --- .../newpipe/player/playback/CustomHlsPlaylistTracker.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/CustomHlsPlaylistTracker.java b/app/src/main/java/org/schabi/newpipe/player/playback/CustomHlsPlaylistTracker.java index 28f6b01fe..99d6bfa07 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playback/CustomHlsPlaylistTracker.java +++ b/app/src/main/java/org/schabi/newpipe/player/playback/CustomHlsPlaylistTracker.java @@ -411,6 +411,7 @@ public final class CustomHlsPlaylistTracker implements HlsPlaylistTracker, return anyExclusionFailed; } + @SuppressWarnings("squid:S2259") private HlsMediaPlaylist getLatestPlaylistSnapshot( @Nullable final HlsMediaPlaylist oldPlaylist, @NonNull final HlsMediaPlaylist loadedPlaylist) { @@ -684,6 +685,7 @@ public final class CustomHlsPlaylistTracker implements HlsPlaylistTracker, mediaPlaylistLoadable.type); } + @SuppressWarnings("squid:S2259") private void processLoadedPlaylist(final HlsMediaPlaylist loadedPlaylist, final LoadEventInfo loadEventInfo) { final HlsMediaPlaylist oldPlaylist = playlistSnapshot; From e103e4817c16e12141a548aed5dfa7dda5ac6157 Mon Sep 17 00:00:00 2001 From: TiA4f8R <74829229+TiA4f8R@users.noreply.github.com> Date: Thu, 20 Jan 2022 17:07:06 +0100 Subject: [PATCH 098/119] Apply suggested changes and remove the CustomHlsPlaylistTracker class --- .../org/schabi/newpipe/player/Player.java | 23 +- .../player/helper/PlayerDataSource.java | 14 +- .../playback/CustomHlsPlaylistTracker.java | 784 ------------------ 3 files changed, 22 insertions(+), 799 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/player/playback/CustomHlsPlaylistTracker.java diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 179486bb1..5bf239a86 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -2517,29 +2517,30 @@ public final class Player implements Log.e(TAG, "ExoPlayer - onPlayerError() called with:", error); saveStreamProgressState(); - boolean isBehindLiveWindowException = false; + boolean isCatchableException = false; switch (error.type) { case ExoPlaybackException.TYPE_SOURCE: - isBehindLiveWindowException = processSourceError(error.getSourceException()); - if (!isBehindLiveWindowException) { - createErrorNotification(error); - } + isCatchableException = processSourceError(error.getSourceException()); break; case ExoPlaybackException.TYPE_UNEXPECTED: - createErrorNotification(error); setRecovery(); reloadPlayQueueManager(); break; case ExoPlaybackException.TYPE_REMOTE: case ExoPlaybackException.TYPE_RENDERER: default: - createErrorNotification(error); onPlaybackShutdown(); break; } - if (fragmentListener != null && !isBehindLiveWindowException) { + if (isCatchableException) { + return; + } + + createErrorNotification(error); + + if (fragmentListener != null) { fragmentListener.onPlayerError(error); } } @@ -2583,10 +2584,10 @@ public final class Player implements // Inform the user that we are reloading the stream by switching to the buffering state onBuffering(); return true; - } else { - playQueue.error(); - return false; } + + playQueue.error(); + return false; } //endregion diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java index 1fce25e78..c898c6ff5 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java @@ -9,6 +9,7 @@ import com.google.android.exoplayer2.source.SingleSampleMediaSource; import com.google.android.exoplayer2.source.dash.DashMediaSource; import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource; import com.google.android.exoplayer2.source.hls.HlsMediaSource; +import com.google.android.exoplayer2.source.hls.playlist.DefaultHlsPlaylistTracker; import com.google.android.exoplayer2.source.smoothstreaming.DefaultSsChunkSource; import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource; import com.google.android.exoplayer2.upstream.DataSource; @@ -16,12 +17,13 @@ import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy; import com.google.android.exoplayer2.upstream.TransferListener; -import org.schabi.newpipe.player.playback.CustomHlsPlaylistTracker; - public class PlayerDataSource { + + public static final int LIVE_STREAM_EDGE_GAP_MILLIS = 10000; + + private static final double PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT = 15; private static final int MANIFEST_MINIMUM_RETRY = 5; private static final int EXTRACTOR_MINIMUM_RETRY = Integer.MAX_VALUE; - public static final int LIVE_STREAM_EDGE_GAP_MILLIS = 10000; private final DataSource.Factory cacheDataSourceFactory; private final DataSource.Factory cachelessDataSourceFactory; @@ -48,7 +50,11 @@ public class PlayerDataSource { .setAllowChunklessPreparation(true) .setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy( MANIFEST_MINIMUM_RETRY)) - .setPlaylistTrackerFactory(CustomHlsPlaylistTracker.FACTORY); + .setPlaylistTrackerFactory((dataSourceFactory, loadErrorHandlingPolicy, + playlistParserFactory) -> + new DefaultHlsPlaylistTracker(dataSourceFactory, loadErrorHandlingPolicy, + playlistParserFactory, PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT) + ); } public DashMediaSource.Factory getLiveDashMediaSourceFactory() { diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/CustomHlsPlaylistTracker.java b/app/src/main/java/org/schabi/newpipe/player/playback/CustomHlsPlaylistTracker.java deleted file mode 100644 index 99d6bfa07..000000000 --- a/app/src/main/java/org/schabi/newpipe/player/playback/CustomHlsPlaylistTracker.java +++ /dev/null @@ -1,784 +0,0 @@ -/* - * Original source code (DefaultHlsPlaylistTracker): Copyright (C) 2016 The Android Open Source - * Project - * - * Original source code licensed under the Apache License, Version 2.0 (the "License"); - * you may not use the original source code of this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.schabi.newpipe.player.playback; - -import static com.google.android.exoplayer2.util.Assertions.checkNotNull; -import static com.google.android.exoplayer2.util.Util.castNonNull; -import static java.lang.Math.max; - -import android.net.Uri; -import android.os.Handler; -import android.os.SystemClock; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.ParserException; -import com.google.android.exoplayer2.source.LoadEventInfo; -import com.google.android.exoplayer2.source.MediaLoadData; -import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; -import com.google.android.exoplayer2.source.hls.HlsDataSourceFactory; -import com.google.android.exoplayer2.source.hls.playlist.DefaultHlsPlaylistTracker; -import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist; -import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.Variant; -import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist; -import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Part; -import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.RenditionReport; -import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment; -import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylist; -import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParser; -import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParserFactory; -import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker; -import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.HttpDataSource; -import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy; -import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.LoadErrorInfo; -import com.google.android.exoplayer2.upstream.Loader; -import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction; -import com.google.android.exoplayer2.upstream.ParsingLoadable; -import com.google.android.exoplayer2.util.Assertions; -import com.google.android.exoplayer2.util.Util; -import com.google.common.collect.Iterables; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -/** - * NewPipe's implementation for {@link HlsPlaylistTracker}, based on - * {@link DefaultHlsPlaylistTracker}. - * - *

- * It redefines the way of how - * {@link PlaylistStuckException PlaylistStuckExceptions} are thrown: instead of - * using a multiplication between the target duration of segments and - * {@link DefaultHlsPlaylistTracker#DEFAULT_PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT}, it uses a - * constant value (see {@link #MAXIMUM_PLAYLIST_STUCK_DURATION_MS}), in order to reduce the number - * of this exception thrown, especially on (very) low-latency livestreams. - *

- */ -public final class CustomHlsPlaylistTracker implements HlsPlaylistTracker, - Loader.Callback> { - - /** - * Factory for {@link CustomHlsPlaylistTracker} instances. - */ - public static final Factory FACTORY = CustomHlsPlaylistTracker::new; - - /** - * The maximum duration before a {@link PlaylistStuckException} is thrown, in milliseconds. - */ - private static final double MAXIMUM_PLAYLIST_STUCK_DURATION_MS = 15000; - - private final HlsDataSourceFactory dataSourceFactory; - private final HlsPlaylistParserFactory playlistParserFactory; - private final LoadErrorHandlingPolicy loadErrorHandlingPolicy; - private final HashMap playlistBundles; - private final List listeners; - - @Nullable - private EventDispatcher eventDispatcher; - @Nullable - private Loader initialPlaylistLoader; - @Nullable - private Handler playlistRefreshHandler; - @Nullable - private PrimaryPlaylistListener primaryPlaylistListener; - @Nullable - private HlsMasterPlaylist masterPlaylist; - @Nullable - private Uri primaryMediaPlaylistUrl; - @Nullable - private HlsMediaPlaylist primaryMediaPlaylistSnapshot; - private boolean isLive; - private long initialStartTimeUs; - - /** - * Creates an instance. - * - * @param dataSourceFactory A factory for {@link DataSource} instances. - * @param loadErrorHandlingPolicy The {@link LoadErrorHandlingPolicy}. - * @param playlistParserFactory An {@link HlsPlaylistParserFactory}. - */ - public CustomHlsPlaylistTracker(final HlsDataSourceFactory dataSourceFactory, - final LoadErrorHandlingPolicy loadErrorHandlingPolicy, - final HlsPlaylistParserFactory playlistParserFactory) { - this.dataSourceFactory = dataSourceFactory; - this.playlistParserFactory = playlistParserFactory; - this.loadErrorHandlingPolicy = loadErrorHandlingPolicy; - listeners = new ArrayList<>(); - playlistBundles = new HashMap<>(); - initialStartTimeUs = C.TIME_UNSET; - } - - // HlsPlaylistTracker implementation. - - @Override - public void start(@NonNull final Uri initialPlaylistUri, - @NonNull final EventDispatcher eventDispatcherObject, - @NonNull final PrimaryPlaylistListener primaryPlaylistListenerObject) { - this.playlistRefreshHandler = Util.createHandlerForCurrentLooper(); - this.eventDispatcher = eventDispatcherObject; - this.primaryPlaylistListener = primaryPlaylistListenerObject; - final ParsingLoadable masterPlaylistLoadable = new ParsingLoadable<>( - dataSourceFactory.createDataSource(C.DATA_TYPE_MANIFEST), - initialPlaylistUri, - C.DATA_TYPE_MANIFEST, - playlistParserFactory.createPlaylistParser()); - Assertions.checkState(initialPlaylistLoader == null); - initialPlaylistLoader = new Loader("CustomHlsPlaylistTracker:MasterPlaylist"); - final long elapsedRealtime = initialPlaylistLoader.startLoading(masterPlaylistLoadable, - this, loadErrorHandlingPolicy.getMinimumLoadableRetryCount( - masterPlaylistLoadable.type)); - eventDispatcherObject.loadStarted(new LoadEventInfo(masterPlaylistLoadable.loadTaskId, - masterPlaylistLoadable.dataSpec, elapsedRealtime), - masterPlaylistLoadable.type); - } - - @Override - public void stop() { - primaryMediaPlaylistUrl = null; - primaryMediaPlaylistSnapshot = null; - masterPlaylist = null; - initialStartTimeUs = C.TIME_UNSET; - initialPlaylistLoader.release(); - initialPlaylistLoader = null; - for (final MediaPlaylistBundle bundle : playlistBundles.values()) { - bundle.release(); - } - playlistRefreshHandler.removeCallbacksAndMessages(null); - playlistRefreshHandler = null; - playlistBundles.clear(); - } - - @Override - public void addListener(@NonNull final PlaylistEventListener listener) { - checkNotNull(listener); - listeners.add(listener); - } - - @Override - public void removeListener(@NonNull final PlaylistEventListener listener) { - listeners.remove(listener); - } - - @Override - @Nullable - public HlsMasterPlaylist getMasterPlaylist() { - return masterPlaylist; - } - - @Override - @Nullable - public HlsMediaPlaylist getPlaylistSnapshot(@NonNull final Uri url, - final boolean isForPlayback) { - final HlsMediaPlaylist snapshot = playlistBundles.get(url).getPlaylistSnapshot(); - if (snapshot != null && isForPlayback) { - maybeSetPrimaryUrl(url); - } - return snapshot; - } - - @Override - public long getInitialStartTimeUs() { - return initialStartTimeUs; - } - - @Override - public boolean isSnapshotValid(@NonNull final Uri url) { - return playlistBundles.get(url).isSnapshotValid(); - } - - @Override - public void maybeThrowPrimaryPlaylistRefreshError() throws IOException { - if (initialPlaylistLoader != null) { - initialPlaylistLoader.maybeThrowError(); - } - if (primaryMediaPlaylistUrl != null) { - maybeThrowPlaylistRefreshError(primaryMediaPlaylistUrl); - } - } - - @Override - public void maybeThrowPlaylistRefreshError(@NonNull final Uri url) throws IOException { - playlistBundles.get(url).maybeThrowPlaylistRefreshError(); - } - - @Override - public void refreshPlaylist(@NonNull final Uri url) { - playlistBundles.get(url).loadPlaylist(); - } - - @Override - public boolean isLive() { - return isLive; - } - - // Loader.Callback implementation. - - @Override - public void onLoadCompleted(@NonNull final ParsingLoadable loadable, - final long elapsedRealtimeMs, - final long loadDurationMs) { - final HlsPlaylist result = loadable.getResult(); - final HlsMasterPlaylist newMasterPlaylist; - final boolean isMediaPlaylist = result instanceof HlsMediaPlaylist; - if (isMediaPlaylist) { - newMasterPlaylist = HlsMasterPlaylist.createSingleVariantMasterPlaylist( - result.baseUri); - } else { // result instanceof HlsMasterPlaylist - newMasterPlaylist = (HlsMasterPlaylist) result; - } - this.masterPlaylist = newMasterPlaylist; - primaryMediaPlaylistUrl = newMasterPlaylist.variants.get(0).url; - createBundles(newMasterPlaylist.mediaPlaylistUrls); - final LoadEventInfo loadEventInfo = new LoadEventInfo(loadable.loadTaskId, - loadable.dataSpec, loadable.getUri(), loadable.getResponseHeaders(), - elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); - final MediaPlaylistBundle primaryBundle = playlistBundles.get(primaryMediaPlaylistUrl); - if (isMediaPlaylist) { - // We don't need to load the playlist again. We can use the same result. - primaryBundle.processLoadedPlaylist((HlsMediaPlaylist) result, loadEventInfo); - } else { - primaryBundle.loadPlaylist(); - } - loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId); - eventDispatcher.loadCompleted(loadEventInfo, C.DATA_TYPE_MANIFEST); - } - - @Override - public void onLoadCanceled(@NonNull final ParsingLoadable loadable, - final long elapsedRealtimeMs, - final long loadDurationMs, - final boolean released) { - final LoadEventInfo loadEventInfo = new LoadEventInfo(loadable.loadTaskId, - loadable.dataSpec, loadable.getUri(), loadable.getResponseHeaders(), - elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); - loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId); - eventDispatcher.loadCanceled(loadEventInfo, C.DATA_TYPE_MANIFEST); - } - - @Override - public LoadErrorAction onLoadError(@NonNull final ParsingLoadable loadable, - final long elapsedRealtimeMs, - final long loadDurationMs, - final IOException error, - final int errorCount) { - final LoadEventInfo loadEventInfo = new LoadEventInfo(loadable.loadTaskId, - loadable.dataSpec, loadable.getUri(), loadable.getResponseHeaders(), - elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); - final MediaLoadData mediaLoadData = new MediaLoadData(loadable.type); - final long retryDelayMs = loadErrorHandlingPolicy.getRetryDelayMsFor(new LoadErrorInfo( - loadEventInfo, mediaLoadData, error, errorCount)); - final boolean isFatal = retryDelayMs == C.TIME_UNSET; - eventDispatcher.loadError(loadEventInfo, loadable.type, error, isFatal); - if (isFatal) { - loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId); - } - return isFatal ? Loader.DONT_RETRY_FATAL : Loader.createRetryAction(false, retryDelayMs); - } - - // Internal methods. - - private boolean maybeSelectNewPrimaryUrl() { - final List variants = masterPlaylist.variants; - final int variantsSize = variants.size(); - final long currentTimeMs = SystemClock.elapsedRealtime(); - for (int i = 0; i < variantsSize; i++) { - final MediaPlaylistBundle bundle = checkNotNull(playlistBundles.get( - variants.get(i).url)); - if (currentTimeMs > bundle.excludeUntilMs) { - primaryMediaPlaylistUrl = bundle.playlistUrl; - bundle.loadPlaylistInternal(getRequestUriForPrimaryChange( - primaryMediaPlaylistUrl)); - return true; - } - } - return false; - } - - private void maybeSetPrimaryUrl(@NonNull final Uri url) { - if (url.equals(primaryMediaPlaylistUrl) || !isVariantUrl(url) - || (primaryMediaPlaylistSnapshot != null - && primaryMediaPlaylistSnapshot.hasEndTag)) { - // Ignore if the primary media playlist URL is unchanged, if the media playlist is not - // referenced directly by a variant, or it the last primary snapshot contains an end - // tag. - return; - } - primaryMediaPlaylistUrl = url; - final MediaPlaylistBundle newPrimaryBundle = playlistBundles.get(primaryMediaPlaylistUrl); - final HlsMediaPlaylist newPrimarySnapshot = newPrimaryBundle.playlistSnapshot; - if (newPrimarySnapshot != null && newPrimarySnapshot.hasEndTag) { - primaryMediaPlaylistSnapshot = newPrimarySnapshot; - primaryPlaylistListener.onPrimaryPlaylistRefreshed(newPrimarySnapshot); - } else { - // The snapshot for the new primary media playlist URL may be stale. Defer updating the - // primary snapshot until after we've refreshed it. - newPrimaryBundle.loadPlaylistInternal(getRequestUriForPrimaryChange(url)); - } - } - - private Uri getRequestUriForPrimaryChange(@NonNull final Uri newPrimaryPlaylistUri) { - if (primaryMediaPlaylistSnapshot != null - && primaryMediaPlaylistSnapshot.serverControl.canBlockReload) { - final RenditionReport renditionReport = primaryMediaPlaylistSnapshot.renditionReports - .get(newPrimaryPlaylistUri); - if (renditionReport != null) { - final Uri.Builder uriBuilder = newPrimaryPlaylistUri.buildUpon(); - uriBuilder.appendQueryParameter(MediaPlaylistBundle.BLOCK_MSN_PARAM, - String.valueOf(renditionReport.lastMediaSequence)); - if (renditionReport.lastPartIndex != C.INDEX_UNSET) { - uriBuilder.appendQueryParameter(MediaPlaylistBundle.BLOCK_PART_PARAM, - String.valueOf(renditionReport.lastPartIndex)); - } - return uriBuilder.build(); - } - } - return newPrimaryPlaylistUri; - } - - /** - * @return whether any of the variants in the master playlist have the specified playlist URL. - * @param playlistUrl the playlist URL to test - */ - private boolean isVariantUrl(final Uri playlistUrl) { - final List variants = masterPlaylist.variants; - final int variantsSize = variants.size(); - for (int i = 0; i < variantsSize; i++) { - if (playlistUrl.equals(variants.get(i).url)) { - return true; - } - } - return false; - } - - private void createBundles(@NonNull final List urls) { - final int listSize = urls.size(); - for (int i = 0; i < listSize; i++) { - final Uri url = urls.get(i); - final MediaPlaylistBundle bundle = new MediaPlaylistBundle(url); - playlistBundles.put(url, bundle); - } - } - - /** - * Called by the bundles when a snapshot changes. - * - * @param url The url of the playlist. - * @param newSnapshot The new snapshot. - */ - private void onPlaylistUpdated(@NonNull final Uri url, final HlsMediaPlaylist newSnapshot) { - if (url.equals(primaryMediaPlaylistUrl)) { - if (primaryMediaPlaylistSnapshot == null) { - // This is the first primary URL snapshot. - isLive = !newSnapshot.hasEndTag; - initialStartTimeUs = newSnapshot.startTimeUs; - } - primaryMediaPlaylistSnapshot = newSnapshot; - primaryPlaylistListener.onPrimaryPlaylistRefreshed(newSnapshot); - } - final int listenersSize = listeners.size(); - for (int i = 0; i < listenersSize; i++) { - listeners.get(i).onPlaylistChanged(); - } - } - - private boolean notifyPlaylistError(final Uri playlistUrl, final long exclusionDurationMs) { - final int listenersSize = listeners.size(); - boolean anyExclusionFailed = false; - for (int i = 0; i < listenersSize; i++) { - anyExclusionFailed |= !listeners.get(i).onPlaylistError(playlistUrl, - exclusionDurationMs); - } - return anyExclusionFailed; - } - - @SuppressWarnings("squid:S2259") - private HlsMediaPlaylist getLatestPlaylistSnapshot( - @Nullable final HlsMediaPlaylist oldPlaylist, - @NonNull final HlsMediaPlaylist loadedPlaylist) { - if (!loadedPlaylist.isNewerThan(oldPlaylist)) { - if (loadedPlaylist.hasEndTag) { - // If the loaded playlist has an end tag but is not newer than the old playlist - // then we have an inconsistent state. This is typically caused by the server - // incorrectly resetting the media sequence when appending the end tag. We resolve - // this case as best we can by returning the old playlist with the end tag - // appended. - return oldPlaylist.copyWithEndTag(); - } else { - return oldPlaylist; - } - } - final long startTimeUs = getLoadedPlaylistStartTimeUs(oldPlaylist, loadedPlaylist); - final int discontinuitySequence = getLoadedPlaylistDiscontinuitySequence(oldPlaylist, - loadedPlaylist); - return loadedPlaylist.copyWith(startTimeUs, discontinuitySequence); - } - - private long getLoadedPlaylistStartTimeUs(@Nullable final HlsMediaPlaylist oldPlaylist, - @NonNull final HlsMediaPlaylist loadedPlaylist) { - if (loadedPlaylist.hasProgramDateTime) { - return loadedPlaylist.startTimeUs; - } - final long primarySnapshotStartTimeUs = primaryMediaPlaylistSnapshot != null - ? primaryMediaPlaylistSnapshot.startTimeUs : 0; - if (oldPlaylist == null) { - return primarySnapshotStartTimeUs; - } - final Segment firstOldOverlappingSegment = getFirstOldOverlappingSegment(oldPlaylist, - loadedPlaylist); - if (firstOldOverlappingSegment != null) { - return oldPlaylist.startTimeUs + firstOldOverlappingSegment.relativeStartTimeUs; - } else if (oldPlaylist.segments.size() == loadedPlaylist.mediaSequence - - oldPlaylist.mediaSequence) { - return oldPlaylist.getEndTimeUs(); - } else { - // No segments overlap, we assume the new playlist start coincides with the primary - // playlist. - return primarySnapshotStartTimeUs; - } - } - - private int getLoadedPlaylistDiscontinuitySequence( - @Nullable final HlsMediaPlaylist oldPlaylist, - @NonNull final HlsMediaPlaylist loadedPlaylist) { - if (loadedPlaylist.hasDiscontinuitySequence) { - return loadedPlaylist.discontinuitySequence; - } - // TODO: Improve cross-playlist discontinuity adjustment. - final int primaryUrlDiscontinuitySequence = primaryMediaPlaylistSnapshot != null - ? primaryMediaPlaylistSnapshot.discontinuitySequence : 0; - if (oldPlaylist == null) { - return primaryUrlDiscontinuitySequence; - } - final Segment firstOldOverlappingSegment = getFirstOldOverlappingSegment(oldPlaylist, - loadedPlaylist); - if (firstOldOverlappingSegment != null) { - return oldPlaylist.discontinuitySequence - + firstOldOverlappingSegment.relativeDiscontinuitySequence - - loadedPlaylist.segments.get(0).relativeDiscontinuitySequence; - } - return primaryUrlDiscontinuitySequence; - } - - @Nullable - private static Segment getFirstOldOverlappingSegment( - @NonNull final HlsMediaPlaylist oldPlaylist, - @NonNull final HlsMediaPlaylist loadedPlaylist) { - final int mediaSequenceOffset = (int) (loadedPlaylist.mediaSequence - - oldPlaylist.mediaSequence); - final List oldSegments = oldPlaylist.segments; - return mediaSequenceOffset < oldSegments.size() ? oldSegments.get(mediaSequenceOffset) - : null; - } - - /** - * Hold all information related to a specific Media Playlist. - */ - private final class MediaPlaylistBundle - implements Loader.Callback> { - - private static final String BLOCK_MSN_PARAM = "_HLS_msn"; - private static final String BLOCK_PART_PARAM = "_HLS_part"; - private static final String SKIP_PARAM = "_HLS_skip"; - - private final Uri playlistUrl; - private final Loader mediaPlaylistLoader; - private final DataSource mediaPlaylistDataSource; - - @Nullable - private HlsMediaPlaylist playlistSnapshot; - private long lastSnapshotLoadMs; - private long lastSnapshotChangeMs; - private long earliestNextLoadTimeMs; - private long excludeUntilMs; - private boolean loadPending; - @Nullable - private IOException playlistError; - - MediaPlaylistBundle(final Uri playlistUrl) { - this.playlistUrl = playlistUrl; - mediaPlaylistLoader = new Loader("CustomHlsPlaylistTracker:MediaPlaylist"); - mediaPlaylistDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_MANIFEST); - } - - @Nullable - public HlsMediaPlaylist getPlaylistSnapshot() { - return playlistSnapshot; - } - - public boolean isSnapshotValid() { - if (playlistSnapshot == null) { - return false; - } - final long currentTimeMs = SystemClock.elapsedRealtime(); - final long snapshotValidityDurationMs = max(30000, C.usToMs( - playlistSnapshot.durationUs)); - return playlistSnapshot.hasEndTag - || playlistSnapshot.playlistType == HlsMediaPlaylist.PLAYLIST_TYPE_EVENT - || playlistSnapshot.playlistType == HlsMediaPlaylist.PLAYLIST_TYPE_VOD - || lastSnapshotLoadMs + snapshotValidityDurationMs > currentTimeMs; - } - - public void loadPlaylist() { - loadPlaylistInternal(playlistUrl); - } - - public void maybeThrowPlaylistRefreshError() throws IOException { - mediaPlaylistLoader.maybeThrowError(); - if (playlistError != null) { - throw playlistError; - } - } - - public void release() { - mediaPlaylistLoader.release(); - } - - // Loader.Callback implementation. - - @Override - public void onLoadCompleted(@NonNull final ParsingLoadable loadable, - final long elapsedRealtimeMs, - final long loadDurationMs) { - final HlsPlaylist result = loadable.getResult(); - final LoadEventInfo loadEventInfo = new LoadEventInfo(loadable.loadTaskId, - loadable.dataSpec, loadable.getUri(), loadable.getResponseHeaders(), - elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); - if (result instanceof HlsMediaPlaylist) { - processLoadedPlaylist((HlsMediaPlaylist) result, loadEventInfo); - eventDispatcher.loadCompleted(loadEventInfo, C.DATA_TYPE_MANIFEST); - } else { - playlistError = new ParserException("Loaded playlist has unexpected type."); - eventDispatcher.loadError( - loadEventInfo, C.DATA_TYPE_MANIFEST, playlistError, true); - } - loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId); - } - - @Override - public void onLoadCanceled(@NonNull final ParsingLoadable loadable, - final long elapsedRealtimeMs, - final long loadDurationMs, - final boolean released) { - final LoadEventInfo loadEventInfo = new LoadEventInfo(loadable.loadTaskId, - loadable.dataSpec, loadable.getUri(), loadable.getResponseHeaders(), - elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); - loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId); - eventDispatcher.loadCanceled(loadEventInfo, C.DATA_TYPE_MANIFEST); - } - - @Override - public LoadErrorAction onLoadError(@NonNull final ParsingLoadable loadable, - final long elapsedRealtimeMs, - final long loadDurationMs, - final IOException error, - final int errorCount) { - final LoadEventInfo loadEventInfo = new LoadEventInfo(loadable.loadTaskId, - loadable.dataSpec, loadable.getUri(), loadable.getResponseHeaders(), - elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); - final boolean isBlockingRequest = loadable.getUri().getQueryParameter(BLOCK_MSN_PARAM) - != null; - final boolean deltaUpdateFailed = error instanceof HlsPlaylistParser - .DeltaUpdateException; - if (isBlockingRequest || deltaUpdateFailed) { - int responseCode = Integer.MAX_VALUE; - if (error instanceof HttpDataSource.InvalidResponseCodeException) { - responseCode = ((HttpDataSource.InvalidResponseCodeException) error) - .responseCode; - } - if (deltaUpdateFailed || responseCode == 400 || responseCode == 503) { - // Intercept failed delta updates and blocking requests producing a Bad Request - // (400) and Service Unavailable (503). In such cases, force a full, - // non-blocking request (see RFC 8216, section 6.2.5.2 and 6.3.7). - earliestNextLoadTimeMs = SystemClock.elapsedRealtime(); - loadPlaylist(); - castNonNull(eventDispatcher).loadError(loadEventInfo, loadable.type, error, - true); - return Loader.DONT_RETRY; - } - } - final MediaLoadData mediaLoadData = new MediaLoadData(loadable.type); - final LoadErrorInfo loadErrorInfo = new LoadErrorInfo(loadEventInfo, mediaLoadData, - error, errorCount); - final LoadErrorAction loadErrorAction; - final long exclusionDurationMs = loadErrorHandlingPolicy.getBlacklistDurationMsFor( - loadErrorInfo); - final boolean shouldExclude = exclusionDurationMs != C.TIME_UNSET; - - boolean exclusionFailed = notifyPlaylistError(playlistUrl, exclusionDurationMs) - || !shouldExclude; - if (shouldExclude) { - exclusionFailed |= excludePlaylist(exclusionDurationMs); - } - - if (exclusionFailed) { - final long retryDelay = loadErrorHandlingPolicy.getRetryDelayMsFor(loadErrorInfo); - loadErrorAction = retryDelay != C.TIME_UNSET - ? Loader.createRetryAction(false, retryDelay) - : Loader.DONT_RETRY_FATAL; - } else { - loadErrorAction = Loader.DONT_RETRY; - } - - final boolean wasCanceled = !loadErrorAction.isRetry(); - eventDispatcher.loadError(loadEventInfo, loadable.type, error, wasCanceled); - if (wasCanceled) { - loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId); - } - return loadErrorAction; - } - - // Internal methods. - - private void loadPlaylistInternal(@NonNull final Uri playlistRequestUri) { - excludeUntilMs = 0; - if (loadPending || mediaPlaylistLoader.isLoading() - || mediaPlaylistLoader.hasFatalError()) { - // Load already pending, in progress, or a fatal error has been encountered. Do - // nothing. - return; - } - final long currentTimeMs = SystemClock.elapsedRealtime(); - if (currentTimeMs < earliestNextLoadTimeMs) { - loadPending = true; - playlistRefreshHandler.postDelayed( - () -> { - loadPending = false; - loadPlaylistImmediately(playlistRequestUri); - }, - earliestNextLoadTimeMs - currentTimeMs); - } else { - loadPlaylistImmediately(playlistRequestUri); - } - } - - private void loadPlaylistImmediately(@NonNull final Uri playlistRequestUri) { - final ParsingLoadable.Parser mediaPlaylistParser = playlistParserFactory - .createPlaylistParser(masterPlaylist, playlistSnapshot); - final ParsingLoadable mediaPlaylistLoadable = new ParsingLoadable<>( - mediaPlaylistDataSource, playlistRequestUri, C.DATA_TYPE_MANIFEST, - mediaPlaylistParser); - final long elapsedRealtime = mediaPlaylistLoader.startLoading(mediaPlaylistLoadable, - this, loadErrorHandlingPolicy.getMinimumLoadableRetryCount( - mediaPlaylistLoadable.type)); - eventDispatcher.loadStarted(new LoadEventInfo(mediaPlaylistLoadable.loadTaskId, - mediaPlaylistLoadable.dataSpec, elapsedRealtime), - mediaPlaylistLoadable.type); - } - - @SuppressWarnings("squid:S2259") - private void processLoadedPlaylist(final HlsMediaPlaylist loadedPlaylist, - final LoadEventInfo loadEventInfo) { - final HlsMediaPlaylist oldPlaylist = playlistSnapshot; - final long currentTimeMs = SystemClock.elapsedRealtime(); - lastSnapshotLoadMs = currentTimeMs; - playlistSnapshot = getLatestPlaylistSnapshot(oldPlaylist, loadedPlaylist); - if (playlistSnapshot != oldPlaylist) { - playlistError = null; - lastSnapshotChangeMs = currentTimeMs; - onPlaylistUpdated(playlistUrl, playlistSnapshot); - } else if (!playlistSnapshot.hasEndTag) { - if (loadedPlaylist.mediaSequence + loadedPlaylist.segments.size() - < playlistSnapshot.mediaSequence) { - // TODO: Allow customization of playlist resets handling. - // The media sequence jumped backwards. The server has probably reset. We do - // not try excluding in this case. - playlistError = new PlaylistResetException(playlistUrl); - notifyPlaylistError(playlistUrl, C.TIME_UNSET); - } else if (currentTimeMs - lastSnapshotChangeMs - > MAXIMUM_PLAYLIST_STUCK_DURATION_MS) { - // TODO: Allow customization of stuck playlists handling. - playlistError = new PlaylistStuckException(playlistUrl); - final LoadErrorInfo loadErrorInfo = new LoadErrorInfo(loadEventInfo, - new MediaLoadData(C.DATA_TYPE_MANIFEST), - playlistError, 1); - final long exclusionDurationMs = loadErrorHandlingPolicy - .getBlacklistDurationMsFor(loadErrorInfo); - notifyPlaylistError(playlistUrl, exclusionDurationMs); - if (exclusionDurationMs != C.TIME_UNSET) { - excludePlaylist(exclusionDurationMs); - } - } - } - long durationUntilNextLoadUs = 0L; - if (!playlistSnapshot.serverControl.canBlockReload) { - // If blocking requests are not supported, do not allow the playlist to load again - // within the target duration if we obtained a new snapshot, or half the target - // duration otherwise. - durationUntilNextLoadUs = playlistSnapshot != oldPlaylist - ? playlistSnapshot.targetDurationUs - : (playlistSnapshot.targetDurationUs / 2); - } - earliestNextLoadTimeMs = currentTimeMs + C.usToMs(durationUntilNextLoadUs); - // Schedule a load if this is the primary playlist or a playlist of a low-latency - // stream and it doesn't have an end tag. Else the next load will be scheduled when - // refreshPlaylist is called, or when this playlist becomes the primary. - final boolean scheduleLoad = playlistSnapshot.partTargetDurationUs != C.TIME_UNSET - || playlistUrl.equals(primaryMediaPlaylistUrl); - if (scheduleLoad && !playlistSnapshot.hasEndTag) { - loadPlaylistInternal(getMediaPlaylistUriForReload()); - } - } - - private Uri getMediaPlaylistUriForReload() { - if (playlistSnapshot == null - || (playlistSnapshot.serverControl.skipUntilUs == C.TIME_UNSET - && !playlistSnapshot.serverControl.canBlockReload)) { - return playlistUrl; - } - final Uri.Builder uriBuilder = playlistUrl.buildUpon(); - if (playlistSnapshot.serverControl.canBlockReload) { - final long targetMediaSequence = playlistSnapshot.mediaSequence - + playlistSnapshot.segments.size(); - uriBuilder.appendQueryParameter(BLOCK_MSN_PARAM, String.valueOf( - targetMediaSequence)); - if (playlistSnapshot.partTargetDurationUs != C.TIME_UNSET) { - final List trailingParts = playlistSnapshot.trailingParts; - int targetPartIndex = trailingParts.size(); - if (!trailingParts.isEmpty() && Iterables.getLast(trailingParts).isPreload) { - // Ignore the preload part. - targetPartIndex--; - } - uriBuilder.appendQueryParameter(BLOCK_PART_PARAM, String.valueOf( - targetPartIndex)); - } - } - if (playlistSnapshot.serverControl.skipUntilUs != C.TIME_UNSET) { - uriBuilder.appendQueryParameter(SKIP_PARAM, - playlistSnapshot.serverControl.canSkipDateRanges ? "v2" : "YES"); - } - return uriBuilder.build(); - } - - /** - * Exclude the playlist. - * - * @param exclusionDurationMs The number of milliseconds for which the playlist should be - * excluded. - * @return Whether the playlist is the primary, despite being excluded. - */ - private boolean excludePlaylist(final long exclusionDurationMs) { - excludeUntilMs = SystemClock.elapsedRealtime() + exclusionDurationMs; - return playlistUrl.equals(primaryMediaPlaylistUrl) && !maybeSelectNewPrimaryUrl(); - } - } -} From 52cc4a0a05e58177e83362ff38db6b728a33ff06 Mon Sep 17 00:00:00 2001 From: TiA4f8R <74829229+TiA4f8R@users.noreply.github.com> Date: Sun, 30 Jan 2022 20:41:08 +0100 Subject: [PATCH 099/119] Add JavaDoc for PlayerDataSource.PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT --- .../org/schabi/newpipe/player/helper/PlayerDataSource.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java index c898c6ff5..a2f0d7149 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java @@ -21,6 +21,12 @@ public class PlayerDataSource { public static final int LIVE_STREAM_EDGE_GAP_MILLIS = 10000; + /** + * An approximately 4.3 times greater value than the + * {@link DefaultHlsPlaylistTracker#DEFAULT_PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT default} + * to ensure that (very) low latency livestreams which got stuck for a moment don't crash too + * early. + */ private static final double PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT = 15; private static final int MANIFEST_MINIMUM_RETRY = 5; private static final int EXTRACTOR_MINIMUM_RETRY = Integer.MAX_VALUE; From 72a2644f258ea54d37e735e606d5069e9bc767e7 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Tue, 1 Feb 2022 13:41:12 +0100 Subject: [PATCH 100/119] Update NewPipe Extractor to 0.21.13 --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 0f7c28a43..4fb0d12be 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -189,7 +189,7 @@ dependencies { // name and the commit hash with the commit hash of the (pushed) commit you want to test // This works thanks to JitPack: https://jitpack.io/ implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751' - implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.21.12' + implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.21.13' /** Checkstyle **/ checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}" From 144a10f7a60f5bb5847949c429c6865361fa03a1 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Tue, 1 Feb 2022 13:44:19 +0100 Subject: [PATCH 101/119] Release 0.21.16 (982) --- app/build.gradle | 4 ++-- fastlane/metadata/android/en-US/changelogs/982.txt | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/982.txt diff --git a/app/build.gradle b/app/build.gradle index 4fb0d12be..a5c838c08 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,8 +17,8 @@ android { resValue "string", "app_name", "NewPipe" minSdkVersion 19 targetSdkVersion 29 - versionCode 981 - versionName "0.21.15" + versionCode 982 + versionName "0.21.16" multiDexEnabled true diff --git a/fastlane/metadata/android/en-US/changelogs/982.txt b/fastlane/metadata/android/en-US/changelogs/982.txt new file mode 100644 index 000000000..954c6a818 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/982.txt @@ -0,0 +1 @@ +Fixed YouTube not playing any stream. \ No newline at end of file From 79060f0bfe56009f5c7c059feeeaf8435e0faba4 Mon Sep 17 00:00:00 2001 From: TacoTheDank Date: Wed, 2 Feb 2022 13:12:29 -0500 Subject: [PATCH 102/119] Update ACRA library --- app/build.gradle | 2 +- app/src/main/java/org/schabi/newpipe/App.java | 18 +++--------------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 4cebcb7f5..7d6123d6f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -260,7 +260,7 @@ dependencies { implementation "com.nononsenseapps:filepicker:4.2.1" // Crash reporting - implementation "ch.acra:acra-core:5.7.0" + implementation "ch.acra:acra-core:5.8.4" // Properly restarting implementation 'com.jakewharton:process-phoenix:2.1.2' diff --git a/app/src/main/java/org/schabi/newpipe/App.java b/app/src/main/java/org/schabi/newpipe/App.java index 6c02b6f57..54e0af8c6 100644 --- a/app/src/main/java/org/schabi/newpipe/App.java +++ b/app/src/main/java/org/schabi/newpipe/App.java @@ -13,13 +13,8 @@ import androidx.preference.PreferenceManager; import com.jakewharton.processphoenix.ProcessPhoenix; import org.acra.ACRA; -import org.acra.config.ACRAConfigurationException; -import org.acra.config.CoreConfiguration; import org.acra.config.CoreConfigurationBuilder; -import org.schabi.newpipe.error.ErrorInfo; -import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.ReCaptchaActivity; -import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.ktx.ExceptionUtils; @@ -210,16 +205,9 @@ public class App extends MultiDexApplication { return; } - try { - final CoreConfiguration acraConfig = new CoreConfigurationBuilder(this) - .setBuildConfigClass(BuildConfig.class) - .build(); - ACRA.init(this, acraConfig); - } catch (final ACRAConfigurationException exception) { - exception.printStackTrace(); - ErrorUtil.openActivity(this, new ErrorInfo(exception, - UserAction.SOMETHING_ELSE, "Could not initialize ACRA crash report")); - } + final CoreConfigurationBuilder acraConfig = new CoreConfigurationBuilder(this) + .withBuildConfigClass(BuildConfig.class); + ACRA.init(this, acraConfig); } private void initNotificationChannels() { From b0e4f947eae5d07d7e046d9ea9d3e268a4852a4d Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Thu, 3 Feb 2022 21:06:25 +0100 Subject: [PATCH 103/119] Fixed merge conflict Co-authored-by: Mohammed Anas --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d2132ecb1..ead430fd1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,8 +14,8 @@ android { defaultConfig { applicationId "org.schabi.newpipe" resValue "string", "app_name", "NewPipe" - minSdkVersion 19 - targetSdkVersion 29 + minSdk 19 + targetSdk 29 versionCode 982 versionName "0.21.16" From 8b3aec5edba7c26a7473a7c791c1ec3415826764 Mon Sep 17 00:00:00 2001 From: Alberto Mosconi Date: Thu, 3 Feb 2022 21:33:27 +0100 Subject: [PATCH 104/119] Move translated READMEs to subfolder (#7784) --- README.md | 2 +- README.es.md => doc/README.es.md | 38 ++-- README.ja.md => doc/README.ja.md | 298 ++++++++++++------------- README.ko.md => doc/README.ko.md | 38 ++-- README.pl.md => doc/README.pl.md | 288 ++++++++++++------------ README.pt_BR.md => doc/README.pt_BR.md | 38 ++-- README.ro.md => doc/README.ro.md | 38 ++-- README.so.md => doc/README.so.md | 38 ++-- README.tr.md => doc/README.tr.md | 38 ++-- README.zh_TW.md => doc/README.zh_TW.md | 38 ++-- 10 files changed, 427 insertions(+), 427 deletions(-) rename README.es.md => doc/README.es.md (75%) rename README.ja.md => doc/README.ja.md (76%) rename README.ko.md => doc/README.ko.md (75%) rename README.pl.md => doc/README.pl.md (72%) rename README.pt_BR.md => doc/README.pt_BR.md (74%) rename README.ro.md => doc/README.ro.md (75%) rename README.so.md => doc/README.so.md (75%) rename README.tr.md => doc/README.tr.md (74%) rename README.zh_TW.md => doc/README.zh_TW.md (70%) diff --git a/README.md b/README.md index 18d0c9ea6..186b613f7 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@

WebsiteBlogFAQPress


-*Read this in other languages: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* +*Read this in other languages: [English](README.md), [Español](doc/README.es.md), [한국어](doc/README.ko.md), [Soomaali](doc/README.so.md), [Português Brasil](doc/README.pt_BR.md), [Polski](doc/README.pl.md), [日本語](doc/README.ja.md), [Română](doc/README.ro.md), [Türkçe](doc/README.tr.md), [正體中文](doc/README.zh_TW.md).* WARNING: THIS IS A BETA VERSION, THEREFORE YOU MAY ENCOUNTER BUGS. IF YOU DO, OPEN AN ISSUE VIA OUR GITHUB REPOSITORY. diff --git a/README.es.md b/doc/README.es.md similarity index 75% rename from README.es.md rename to doc/README.es.md index 8e741d8dd..58e9742bf 100644 --- a/README.es.md +++ b/doc/README.es.md @@ -1,4 +1,4 @@ -

+

NewPipe

Una interfaz de streaming ligera y libre para Android.

@@ -18,7 +18,7 @@

Sitio WebBlogPreguntas FrecuentesPrensa


-*Lea esto en otros idiomas: [English](README.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* +*Lea esto en otros idiomas: [English](../README.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* AVISO: ESTA ES UNA VERSIÓN BETA, POR LO TANTO, PUEDE ENCONTRAR BUGS. SI ENCUENTRA UNO ABRA UN ISSUE A TRAVÉS DE NUESTRO REPOSITORIO DE GITHUB. @@ -26,18 +26,18 @@ ## Capturas de Pantalla -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) -[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) -[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) +[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) +[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) ## Descripción @@ -105,7 +105,7 @@ Además, si quiere cambiar el método de instalación por alguna razón (por eje Si tiene ideas, traducciones, cambios de diseño, limpieza de código o cambios grandes de código, su ayuda es siempre bienvenida. ¡Cuanto más hagamos, NewPipe será mucho mejor! -Si quiere involucrarse, fíjese en nuestras [notas de contribución](.github/CONTRIBUTING.md). +Si quiere involucrarse, fíjese en nuestras [notas de contribución](../.github/CONTRIBUTING.md). Estado de la Traducción @@ -117,17 +117,17 @@ Si te gusta NewPipe, estaremos felices con una donación. Puede enviar bitcoin o - + - - + + - +
BitcoinCódigo QR del BitcoinCódigo QR del Bitcoin 16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
LiberapayVisita NewPipe en liberapay.comDona vía LiberapayVisita NewPipe en liberapay.comDona vía Liberapay
BountysourceVisita NewPipe en bountysource.comVisita NewPipe en bountysource.com Revisa cuántas recompensas puedes obtener.
diff --git a/README.ja.md b/doc/README.ja.md similarity index 76% rename from README.ja.md rename to doc/README.ja.md index 733209aea..37a7add44 100644 --- a/README.ja.md +++ b/doc/README.ja.md @@ -1,149 +1,149 @@ -

-

NewPipe

-

自由で軽量な Android 向けストリーミングフロントエンド

- -

Get it on F-Droid

- -

- - - - - - -

-
-

スクリーンショット説明機能インストールと更新貢献寄付ライセンス

-

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

-
- -*他の言語で読む: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md)。* - -注意: これはベータ版のため、バグが発生する可能性があります。もしバグが発生した場合、GitHub のリポジトリで Issue を開いてください。 - -NewPipe 及びいずれのフォークを Google Play ストアに公開すると、Google の取引条件の違反になります。 - - -## スクリーンショット - -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) -[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) -[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) - - -## 説明 - -自由なコピーレフトソフトウェアの NewPipe は一切の Google フレームワークライブラリ及び、YouTube API を使用しません。ウェブサイトは必要な情報のためだけに読み込まれるため、このアプリは Google のサービスがインストールされていない端末で使用ができます。また、NewPipe の使用に YouTube アカウントは必要となりません。 - - -### 機能 - -* 動画の検索 -* 動画の基本情報の表示 -* YouTube の動画の視聴 -* YouTube の動画のバックグラウンド再生 -* ポップアップモード (フローティングプレイヤー) -* 動画を視聴するストリーミングプレイヤーの選択 -* 動画のダウンロード -* 音声のみのダウンロード -* Kodi での動画再生 -* 次の動画/関連動画の表示 -* 特定の言語の YouTube の検索 -* 年齢制限のあるコンテンツの視聴/ブロック -* チャンネルの基本情報の表示 -* チャンネルの検索 -* チャンネルからの動画の視聴 -* Orbot/Tor 対応 (直接的なものは未実装) -* 1080p/2K/4K 対応 -* 履歴の表示 -* チャンネルの登録 -* 履歴の検索 -* 再生リストの検索/視聴 -* 再生リストをキューに追加して再生 -* 動画のキューへの追加 -* 端末内の再生リスト -* 字幕 -* ライブ配信の対応 -* コメントの表示 - -### 対応しているサービス - -NewPipe は複数のサービスに対応しています。[ドキュメント](https://teamnewpipe.github.io/documentation/)は、どのようにしてアプリと NewPipe Extractor にサービスを追加できるかについて詳細な情報を提供しています。もし、新しいサービスを追加するならば、是非私たちに連絡をお願いします。現在対応しているサービスは: - -* YouTube -* SoundCloud \[ベータ\] -* media.ccc.de \[ベータ\] -* PeerTube インスタンス \[ベータ\] -* Bandcamp \[ベータ\] - - - - - -## インストールと更新 -以下の方法のいずれかに従うことによって NewPipe をインストールできます。 -1. カスタムリポジトリを F-Droid に追加してリリースが公開され次第インストールする。この方法の説明はこちら: https://newpipe.net/FAQ/tutorials/install-add-fdroid-repo/ -2. リリースが公開され次第[GitHub のリリース](https://github.com/TeamNewPipe/NewPipe/releases)から APK をダウンロードしてインストールする。 -3. F-Droid から更新する。これは更新を手にする上で最も遅い方法です。F-Droid が変更を検知して、APK をビルドし、署名、そしてユーザーに更新を届ける必要があるためです。 -4. 自分でデバッグ APK をビルドする。これは新しい機能を使用する上で最も早い方法ですが、他と比べてとても複雑なので、他の方法の使用を推奨します。 - -私たちはほとんどのユーザーに方法1を推奨します。方法1と2でインストールされた APK は互換性がありますが、方法3でインストールされたものにはありません。これは方法1と2では、同じ署名鍵 (私たちが使用するもの)が使用されますが、方法3では異なった署名鍵 (F-Droidが使用するもの)が使用されるためです。方法4を使ったデバッグ APK のビルドは根本的に署名鍵の問題を除きます。署名鍵はユーザーが騙されて悪意のある更新がアプリにインストールされないことを助けるためにあります。 - -もし、何かしらの理由によりソースを切り替えたい場合 (例: NewPipe のコア機能が壊れてしまったが F-Droid はまだ更新をしていない) は、この手順を推奨します。 -1. 履歴や登録チャンネル、再生リストを保つために 設定 > コンテンツ > データベースをエクスポート からデータをバックアップ -2. NewPipe をアンインストール -3. 新しいソースから APK をダウンロードしてインストール -4. 設定 > コンテンツ > データベースをインポート からステップ1で作ったデータベースをインポート - - -## 貢献 -翻訳、デザインの変更、コードの整理、大規模なコードの変更などの助けはいつでも歓迎します。 -より良いものを一緒に作り上げましょう! - -もし貢献をしたい場合、[貢献ノート](.github/CONTRIBUTING.md)をご確認ください。 - - -翻訳状態 - - - -## 寄付 -もし、NewPipe を気に入っていただけたら、寄付をしていただけると嬉しいです。Bitcoin または Bountysource, Liberapay から寄付をすることができます。NewPipe への寄付については、[ウェブサイト](https://newpipe.net/donate)からお願いします。 - - - - - - - - - - - - - - - - - -
BitcoinBitcoin QR コード16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
Liberapayliberapay.com で NewPipe を訪れるLiberapay で寄付
Bountysourcebountysource.com で NewPipe を訪れるあなたがどれほどの寄付を得られるのか確認しましょう。
- -## プライバシーポリシー -NewPipe プロジェクトはメディアウェブサービスを使用する上でのプライベートで匿名の体験を提供することを目的としています。 -そのため、アプリはあなたの同意なしで一切のデータを収集しません。NewPipe のプライバシーポリシーはあなたがクラッシュレポートまたは、私たちのブログでコメントを送信した場合にどのようなデータが送信され、保存されるのかを詳細に説明しています。そのドキュメントは[こちら](https://newpipe.net/legal/privacy/)から見つけることができます。 - - -## ライセンス -[![GNU GPLv3 のロゴ](https://www.gnu.org/graphics/gplv3-127x51.png)](https://www.gnu.org/licenses/gpl-3.0.en.html) - -NewPipe はフリーソフトウェアなので、あなたはあなたの望むように使用、習得、共有、改善を行えます。 -具体的には、フリーソフトウェア財団により公開された [GNU General Public License](https://www.gnu.org/licenses/gpl.html) のバージョン3のライセンスもしくは、(あなたの選択で) いずれかの後継バージョンの規約の元で配布または改変を行うことができます。 +

+

NewPipe

+

自由で軽量な Android 向けストリーミングフロントエンド

+ +

Get it on F-Droid

+ +

+ + + + + + +

+
+

スクリーンショット説明機能インストールと更新貢献寄付ライセンス

+

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

+
+ +*他の言語で読む: [English](../README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md)。* + +注意: これはベータ版のため、バグが発生する可能性があります。もしバグが発生した場合、GitHub のリポジトリで Issue を開いてください。 + +NewPipe 及びいずれのフォークを Google Play ストアに公開すると、Google の取引条件の違反になります。 + + +## スクリーンショット + +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) +[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) +[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) + + +## 説明 + +自由なコピーレフトソフトウェアの NewPipe は一切の Google フレームワークライブラリ及び、YouTube API を使用しません。ウェブサイトは必要な情報のためだけに読み込まれるため、このアプリは Google のサービスがインストールされていない端末で使用ができます。また、NewPipe の使用に YouTube アカウントは必要となりません。 + + +### 機能 + +* 動画の検索 +* 動画の基本情報の表示 +* YouTube の動画の視聴 +* YouTube の動画のバックグラウンド再生 +* ポップアップモード (フローティングプレイヤー) +* 動画を視聴するストリーミングプレイヤーの選択 +* 動画のダウンロード +* 音声のみのダウンロード +* Kodi での動画再生 +* 次の動画/関連動画の表示 +* 特定の言語の YouTube の検索 +* 年齢制限のあるコンテンツの視聴/ブロック +* チャンネルの基本情報の表示 +* チャンネルの検索 +* チャンネルからの動画の視聴 +* Orbot/Tor 対応 (直接的なものは未実装) +* 1080p/2K/4K 対応 +* 履歴の表示 +* チャンネルの登録 +* 履歴の検索 +* 再生リストの検索/視聴 +* 再生リストをキューに追加して再生 +* 動画のキューへの追加 +* 端末内の再生リスト +* 字幕 +* ライブ配信の対応 +* コメントの表示 + +### 対応しているサービス + +NewPipe は複数のサービスに対応しています。[ドキュメント](https://teamnewpipe.github.io/documentation/)は、どのようにしてアプリと NewPipe Extractor にサービスを追加できるかについて詳細な情報を提供しています。もし、新しいサービスを追加するならば、是非私たちに連絡をお願いします。現在対応しているサービスは: + +* YouTube +* SoundCloud \[ベータ\] +* media.ccc.de \[ベータ\] +* PeerTube インスタンス \[ベータ\] +* Bandcamp \[ベータ\] + + + + + +## インストールと更新 +以下の方法のいずれかに従うことによって NewPipe をインストールできます。 +1. カスタムリポジトリを F-Droid に追加してリリースが公開され次第インストールする。この方法の説明はこちら: https://newpipe.net/FAQ/tutorials/install-add-fdroid-repo/ +2. リリースが公開され次第[GitHub のリリース](https://github.com/TeamNewPipe/NewPipe/releases)から APK をダウンロードしてインストールする。 +3. F-Droid から更新する。これは更新を手にする上で最も遅い方法です。F-Droid が変更を検知して、APK をビルドし、署名、そしてユーザーに更新を届ける必要があるためです。 +4. 自分でデバッグ APK をビルドする。これは新しい機能を使用する上で最も早い方法ですが、他と比べてとても複雑なので、他の方法の使用を推奨します。 + +私たちはほとんどのユーザーに方法1を推奨します。方法1と2でインストールされた APK は互換性がありますが、方法3でインストールされたものにはありません。これは方法1と2では、同じ署名鍵 (私たちが使用するもの)が使用されますが、方法3では異なった署名鍵 (F-Droidが使用するもの)が使用されるためです。方法4を使ったデバッグ APK のビルドは根本的に署名鍵の問題を除きます。署名鍵はユーザーが騙されて悪意のある更新がアプリにインストールされないことを助けるためにあります。 + +もし、何かしらの理由によりソースを切り替えたい場合 (例: NewPipe のコア機能が壊れてしまったが F-Droid はまだ更新をしていない) は、この手順を推奨します。 +1. 履歴や登録チャンネル、再生リストを保つために 設定 > コンテンツ > データベースをエクスポート からデータをバックアップ +2. NewPipe をアンインストール +3. 新しいソースから APK をダウンロードしてインストール +4. 設定 > コンテンツ > データベースをインポート からステップ1で作ったデータベースをインポート + + +## 貢献 +翻訳、デザインの変更、コードの整理、大規模なコードの変更などの助けはいつでも歓迎します。 +より良いものを一緒に作り上げましょう! + +もし貢献をしたい場合、[貢献ノート](../.github/CONTRIBUTING.md)をご確認ください。 + + +翻訳状態 + + + +## 寄付 +もし、NewPipe を気に入っていただけたら、寄付をしていただけると嬉しいです。Bitcoin または Bountysource, Liberapay から寄付をすることができます。NewPipe への寄付については、[ウェブサイト](https://newpipe.net/donate)からお願いします。 + + + + + + + + + + + + + + + + + +
BitcoinBitcoin QR コード16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
Liberapayliberapay.com で NewPipe を訪れるLiberapay で寄付
Bountysourcebountysource.com で NewPipe を訪れるあなたがどれほどの寄付を得られるのか確認しましょう。
+ +## プライバシーポリシー +NewPipe プロジェクトはメディアウェブサービスを使用する上でのプライベートで匿名の体験を提供することを目的としています。 +そのため、アプリはあなたの同意なしで一切のデータを収集しません。NewPipe のプライバシーポリシーはあなたがクラッシュレポートまたは、私たちのブログでコメントを送信した場合にどのようなデータが送信され、保存されるのかを詳細に説明しています。そのドキュメントは[こちら](https://newpipe.net/legal/privacy/)から見つけることができます。 + + +## ライセンス +[![GNU GPLv3 のロゴ](https://www.gnu.org/graphics/gplv3-127x51.png)](https://www.gnu.org/licenses/gpl-3.0.en.html) + +NewPipe はフリーソフトウェアなので、あなたはあなたの望むように使用、習得、共有、改善を行えます。 +具体的には、フリーソフトウェア財団により公開された [GNU General Public License](https://www.gnu.org/licenses/gpl.html) のバージョン3のライセンスもしくは、(あなたの選択で) いずれかの後継バージョンの規約の元で配布または改変を行うことができます。 diff --git a/README.ko.md b/doc/README.ko.md similarity index 75% rename from README.ko.md rename to doc/README.ko.md index ee4029c2f..08e340388 100644 --- a/README.ko.md +++ b/doc/README.ko.md @@ -1,4 +1,4 @@ -

+

NewPipe

A libre lightweight streaming frontend for Android.

@@ -17,7 +17,7 @@

WebsiteBlogFAQPress


-*Read this in other languages: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* +*Read this in other languages: [English](../README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* 경고: 이 버전은 베타 버전이므로, 버그가 발생할 수도 있습니다. 만약 버그가 발생하였다면, 우리의 GITHUB 저장소에서 ISSUE를 열람하여 주십시오. @@ -25,18 +25,18 @@ ## Screenshots -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) -[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) -[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) +[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) +[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) ## Description @@ -106,7 +106,7 @@ NewPipe 코드의 변경이 있을 때(기능 추가 또는 버그 수정으로 당신이 아이디어, 번역, 디자인 변경, 코드 정리, 또는 정말 큰 코드 수정에 대한 의견이 있다면, 도움은 항상 환영합니다. 더 많이 수행될수록 더 많이 발전할 수 있습니다! -만약 참여하고 싶다면, 우리의 [컨트리뷰션 공지](.github/CONTRIBUTING.md)를 참고하십시오. +만약 참여하고 싶다면, 우리의 [컨트리뷰션 공지](../.github/CONTRIBUTING.md)를 참고하십시오. Translation status @@ -118,17 +118,17 @@ NewPipe 코드의 변경이 있을 때(기능 추가 또는 버그 수정으로 - + - - + + - +
BitcoinBitcoin QR codeBitcoin QR code 16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
LiberapayVisit NewPipe at liberapay.comDonate via LiberapayVisit NewPipe at liberapay.comDonate via Liberapay
BountysourceVisit NewPipe at bountysource.comVisit NewPipe at bountysource.com Check out how many bounties you can earn.
diff --git a/README.pl.md b/doc/README.pl.md similarity index 72% rename from README.pl.md rename to doc/README.pl.md index 317339e60..91c06fbd6 100644 --- a/README.pl.md +++ b/doc/README.pl.md @@ -1,144 +1,144 @@ -

-

NewPipe

-

Wolny, lekki streamingowy frontend na Androida.

- -

Pobierz z F-Droid

- -

- - - - - - -

-
-

ScreenshotyOpisFunkcjeInstalacja i aktualizacjeWkładWesprzyjLicencja

-

StronaBlogFAQPress

-
- -*Przeczytaj w innych językach: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* - -UWAGA: TO JEST WERSJA BETA, WIĘC MOŻESZ NAPOTKAĆ BŁĘDY. JEŚLI TAK SIĘ STANIE, OTWÓRZ NOWY "ISSUE" NA GITHUBIE. - -PUBLIKOWANIE NEWPIPE LUB JAKIEGOKOLWIEK JEGO FORKU W SKLEPIE PLAY NARUSZA ICH WARUNKI UŻYTKOWANIA. - -## Screenshoty - -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) -[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) -[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) - -## Opis - -NewPipe nie używa żadnych bibliotek Google ani API YouTube. Strony są jedynie analizowane aby zdobyć wymagane informacje, dzięki czemu ta aplikacja może zostać zainstalowana na urządzeniach bez Usług Google Play. Konto YouTube nie jest wymagane aby używać NewPipe, które jest wolnym oprogramowaniem copyleft. - -### Funkcje - -* Wyszukiwanie filmów -* Brak wymogu konta Google/YouTube -* Wyświetlanie generalnych informacji o filmach -* Oglądanie filmów na YouTube -* Słuchanie filmów na YouTube -* Tryb okienkowy (Pływające okno) -* Wybieranie odtwarzacza przez który możemy oglądać film -* Pobieranie filmów -* Pobieranie audio -* Otwieranie filmów w Kodi -* Pokazanie następnych/podobnych filmów -* Wyszukiwanie w YouTube w konkretnym języku -* Oglądanie/Blokowanie materiałów zablokowanych wiekowo. -* Wyświetlanie generalnych informacji o kanałach -* Wyszukiwanie kanałów -* Oglądanie filmów ze strony kanału -* Wsparcie dla Orbot/Tor (Jeszcze nie bezpośrednio) -* Wsparcie dla 1080p/2K/4K -* Historia oglądania -* Subskrybowanie kanałów -* Historia wyszukiwania -* Wyszukiwanie/Oglądanie playlist -* Oglądanie playlist w kolejce -* Dodawnaie filmów do kolejki -* Lokalne playlisty -* Napisy -* Wsparcie dla livestream'ów -* Wyświetlanie komentarzy - -### Wspierane usługi - -NewPipe wspiera wiele usług. Nasza [dokumentacja](https://teamnewpipe.github.io/documentation/) dostarcza więcej informacji o tym jak nowe usługi mogą zostać dodane do aplikacji i extractora. Proszę skontaktuj się z nami jeśli masz zamiar dodać jakąś nową usługę. Obecnie wspierane usługi to: - -* YouTube -* SoundCloud \[beta\] -* media.ccc.de \[beta\] -* Instancje PeerTube \[beta\] -* Bandcamp \[beta\] - -## Instalacja i aktualizacje -Możesz zainstalować NewPipe za pomocą jednej z tych metod: - 1. Dodaj nasze repozytorium do F-Droid i z tamtąd pobierz NewPipe. Instrukcje znajdują się tutaj: https://newpipe.net/FAQ/tutorials/install-add-fdroid-repo/ - 2. Pobierz APK z [Wydań na GitHubie](https://github.com/TeamNewPipe/NewPipe/releases) i zainstaluj go. - 3. Zaktualizuj poprzez F-Droid. Jest to najwolniejsza metoda aktualizacji, ponieważ F-Droid musi rozpoznać zmiany, zbudować APK, podpisać go i dopiero wypuścić aktualizację do użytkowników. - 4. Zbuduj debug APK samemu. Jest to najszybszy sposób na zdobycie najnowszych funkcji, ale jest to o wiele, wiele bardziej skomplikowane, dlatego rekomendujemy używania jednej z powyższych metod. - -Dla większości użytkowników rekomendujemy metodę 1. Pliki APK zainstalowane za pomocą metod 1 lub 2 są ze sobą kompatybilne, lecz nie są kompatybilne z tymi zainstalowanymi metodą 3. Dzieje się tak ponieważ ten sam (nasz) klucz jest używany do podpisania APK z metod 1 i 2, ale APK z metody 3 podpisany jest innym kluczem (F-Droida). Budowanie debug APK z metody 4 w ogóle nie uwzględnia klucza. Klucze podpisu zapewniają, że użytkownik omylnie nie zainstaluje złośliwej aktualizacji żadnej aplikacji. - -W międzyczasie, jeśli z jakiegoś powodu chcesz zmienić źródło (np. rdzenna funkcjonalność NewPipe psuje się a F-Droid nie ma jeszcze najnowszej aktualizacji), rekomendujemy użyć następującej procedury: -1. Zrób kopię danych wchodząc w Ustawienia > Zawartość > Eksportuj dane, dzięki czemu zachowasz swoją historię, subskrypcje i playlisty -2. Odinstaluj NewPipe -3. Pobierz APK z nowego źródła i zainstaluj go -4. Przywróć dane z kroku 1 wchodząc w Ustawienia > Zawartość > Importuj dane - -## Wkład -Jeśli masz jakieś pomysły, tłumaczenia, zmiany designu, oczyszczony kod, lub wielkie zmiany w kodzie, pomoc jest zawsze mile widziana. -Im więcej jest zrobione, tym lepsza staje się aplikacja! - -Jeśli chcesz pomóc, przeczytaj [Notkę o wkładzie](.github/CONTRIBUTING.md). - - -Translation status - - -## Wesprzyj -Jeśli podoba Ci się NewPipe, bardzo ucieszylibyśmy się z dotacji. Możesz wysłać bitcoin lub przekazać darowiznę przez Bountysource lub Liberapay. Po więcej informacji o darowiznach dla NewPipe, proszę zobacz naszą [stronę](https://newpipe.net/donate). - - - - - - - - - - - - - - - - - -
BitcoinBitcoin QR code16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
LiberapayVisit NewPipe at liberapay.comDonate via Liberapay
BountysourceVisit NewPipe at bountysource.comCheck out how many bounties you can earn.
- -## Polityka prywatności - -Założeniem projektu NewPipe jest dostarczanie prywatnego, anonimowego dostępu do zasobów i usług internetowych. -Dlatego też, ta aplikacja nie zbiera żadnych informacji bez twojej zgody. Polityka prywatności NewPipe dokładnie wyjaśnia jakie dane są wysyłane i przechowywane, gdy wyślesz raport awarii lub komentarz na naszym blogu. Możesz znaleźć ten dokument [tutaj](https://newpipe.net/legal/privacy/). - -## Licencja -[![GNU GPLv3 Image](https://www.gnu.org/graphics/gplv3-127x51.png)](https://www.gnu.org/licenses/gpl-3.0.en.html) - -NewPipe to wolne oprogramowanie: Możesz używać, uczyć się, udostępniać i ulepszać je do woli. -Możesz udostępniać i/lub modyfikować je na zasadach licencji -[GNU General Public License](https://www.gnu.org/licenses/gpl.html) -publikowaną przez Free Software Foundation, wersję 3 Licencji, lub -(twój wybór) każdną nowszą wersję. +

+

NewPipe

+

Wolny, lekki streamingowy frontend na Androida.

+ +

Pobierz z F-Droid

+ +

+ + + + + + +

+
+

ScreenshotyOpisFunkcjeInstalacja i aktualizacjeWkładWesprzyjLicencja

+

StronaBlogFAQPress

+
+ +*Przeczytaj w innych językach: [English](../README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* + +UWAGA: TO JEST WERSJA BETA, WIĘC MOŻESZ NAPOTKAĆ BŁĘDY. JEŚLI TAK SIĘ STANIE, OTWÓRZ NOWY "ISSUE" NA GITHUBIE. + +PUBLIKOWANIE NEWPIPE LUB JAKIEGOKOLWIEK JEGO FORKU W SKLEPIE PLAY NARUSZA ICH WARUNKI UŻYTKOWANIA. + +## Screenshoty + +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) +[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) +[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) + +## Opis + +NewPipe nie używa żadnych bibliotek Google ani API YouTube. Strony są jedynie analizowane aby zdobyć wymagane informacje, dzięki czemu ta aplikacja może zostać zainstalowana na urządzeniach bez Usług Google Play. Konto YouTube nie jest wymagane aby używać NewPipe, które jest wolnym oprogramowaniem copyleft. + +### Funkcje + +* Wyszukiwanie filmów +* Brak wymogu konta Google/YouTube +* Wyświetlanie generalnych informacji o filmach +* Oglądanie filmów na YouTube +* Słuchanie filmów na YouTube +* Tryb okienkowy (Pływające okno) +* Wybieranie odtwarzacza przez który możemy oglądać film +* Pobieranie filmów +* Pobieranie audio +* Otwieranie filmów w Kodi +* Pokazanie następnych/podobnych filmów +* Wyszukiwanie w YouTube w konkretnym języku +* Oglądanie/Blokowanie materiałów zablokowanych wiekowo. +* Wyświetlanie generalnych informacji o kanałach +* Wyszukiwanie kanałów +* Oglądanie filmów ze strony kanału +* Wsparcie dla Orbot/Tor (Jeszcze nie bezpośrednio) +* Wsparcie dla 1080p/2K/4K +* Historia oglądania +* Subskrybowanie kanałów +* Historia wyszukiwania +* Wyszukiwanie/Oglądanie playlist +* Oglądanie playlist w kolejce +* Dodawnaie filmów do kolejki +* Lokalne playlisty +* Napisy +* Wsparcie dla livestream'ów +* Wyświetlanie komentarzy + +### Wspierane usługi + +NewPipe wspiera wiele usług. Nasza [dokumentacja](https://teamnewpipe.github.io/documentation/) dostarcza więcej informacji o tym jak nowe usługi mogą zostać dodane do aplikacji i extractora. Proszę skontaktuj się z nami jeśli masz zamiar dodać jakąś nową usługę. Obecnie wspierane usługi to: + +* YouTube +* SoundCloud \[beta\] +* media.ccc.de \[beta\] +* Instancje PeerTube \[beta\] +* Bandcamp \[beta\] + +## Instalacja i aktualizacje +Możesz zainstalować NewPipe za pomocą jednej z tych metod: + 1. Dodaj nasze repozytorium do F-Droid i z tamtąd pobierz NewPipe. Instrukcje znajdują się tutaj: https://newpipe.net/FAQ/tutorials/install-add-fdroid-repo/ + 2. Pobierz APK z [Wydań na GitHubie](https://github.com/TeamNewPipe/NewPipe/releases) i zainstaluj go. + 3. Zaktualizuj poprzez F-Droid. Jest to najwolniejsza metoda aktualizacji, ponieważ F-Droid musi rozpoznać zmiany, zbudować APK, podpisać go i dopiero wypuścić aktualizację do użytkowników. + 4. Zbuduj debug APK samemu. Jest to najszybszy sposób na zdobycie najnowszych funkcji, ale jest to o wiele, wiele bardziej skomplikowane, dlatego rekomendujemy używania jednej z powyższych metod. + +Dla większości użytkowników rekomendujemy metodę 1. Pliki APK zainstalowane za pomocą metod 1 lub 2 są ze sobą kompatybilne, lecz nie są kompatybilne z tymi zainstalowanymi metodą 3. Dzieje się tak ponieważ ten sam (nasz) klucz jest używany do podpisania APK z metod 1 i 2, ale APK z metody 3 podpisany jest innym kluczem (F-Droida). Budowanie debug APK z metody 4 w ogóle nie uwzględnia klucza. Klucze podpisu zapewniają, że użytkownik omylnie nie zainstaluje złośliwej aktualizacji żadnej aplikacji. + +W międzyczasie, jeśli z jakiegoś powodu chcesz zmienić źródło (np. rdzenna funkcjonalność NewPipe psuje się a F-Droid nie ma jeszcze najnowszej aktualizacji), rekomendujemy użyć następującej procedury: +1. Zrób kopię danych wchodząc w Ustawienia > Zawartość > Eksportuj dane, dzięki czemu zachowasz swoją historię, subskrypcje i playlisty +2. Odinstaluj NewPipe +3. Pobierz APK z nowego źródła i zainstaluj go +4. Przywróć dane z kroku 1 wchodząc w Ustawienia > Zawartość > Importuj dane + +## Wkład +Jeśli masz jakieś pomysły, tłumaczenia, zmiany designu, oczyszczony kod, lub wielkie zmiany w kodzie, pomoc jest zawsze mile widziana. +Im więcej jest zrobione, tym lepsza staje się aplikacja! + +Jeśli chcesz pomóc, przeczytaj [Notkę o wkładzie](../.github/CONTRIBUTING.md). + + +Translation status + + +## Wesprzyj +Jeśli podoba Ci się NewPipe, bardzo ucieszylibyśmy się z dotacji. Możesz wysłać bitcoin lub przekazać darowiznę przez Bountysource lub Liberapay. Po więcej informacji o darowiznach dla NewPipe, proszę zobacz naszą [stronę](https://newpipe.net/donate). + + + + + + + + + + + + + + + + + +
BitcoinBitcoin QR code16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
LiberapayVisit NewPipe at liberapay.comDonate via Liberapay
BountysourceVisit NewPipe at bountysource.comCheck out how many bounties you can earn.
+ +## Polityka prywatności + +Założeniem projektu NewPipe jest dostarczanie prywatnego, anonimowego dostępu do zasobów i usług internetowych. +Dlatego też, ta aplikacja nie zbiera żadnych informacji bez twojej zgody. Polityka prywatności NewPipe dokładnie wyjaśnia jakie dane są wysyłane i przechowywane, gdy wyślesz raport awarii lub komentarz na naszym blogu. Możesz znaleźć ten dokument [tutaj](https://newpipe.net/legal/privacy/). + +## Licencja +[![GNU GPLv3 Image](https://www.gnu.org/graphics/gplv3-127x51.png)](https://www.gnu.org/licenses/gpl-3.0.en.html) + +NewPipe to wolne oprogramowanie: Możesz używać, uczyć się, udostępniać i ulepszać je do woli. +Możesz udostępniać i/lub modyfikować je na zasadach licencji +[GNU General Public License](https://www.gnu.org/licenses/gpl.html) +publikowaną przez Free Software Foundation, wersję 3 Licencji, lub +(twój wybór) każdną nowszą wersję. diff --git a/README.pt_BR.md b/doc/README.pt_BR.md similarity index 74% rename from README.pt_BR.md rename to doc/README.pt_BR.md index ce2ac38ec..4afe51996 100644 --- a/README.pt_BR.md +++ b/doc/README.pt_BR.md @@ -1,4 +1,4 @@ -

+

NewPipe

Uma interface de streaming leve e gratuita para Android.

@@ -18,7 +18,7 @@

SiteBlogFAQPress


-*Read this in other languages: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* +*Read this in other languages: [English](../README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* AVISO: ESTA É UMA VERSÃO BETA, PORTANTO, VOCÊ PODE ENCONTRAR BUGS. ENCONTROU ALGUM, ABRA UM ISSUE ATRAVÉS DO NOSSO REPOSITÓRIO GITHUB. @@ -26,18 +26,18 @@ ## Screenshots -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) -[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) -[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) +[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) +[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) ## Descrição @@ -102,7 +102,7 @@ Enquanto isso, se você quiser trocar de fontes por algum motivo (por exemplo, a Se você tem ideias, traduções, alterações de design, limpeza de códigos ou mudanças reais de código, a ajuda é sempre bem-vinda. Quanto mais for feito, melhor fica! -Se você quiser se envolver, verifique nossa [notas de contribuição](.github/CONTRIBUTING.md). +Se você quiser se envolver, verifique nossa [notas de contribuição](../.github/CONTRIBUTING.md). Translation status @@ -114,17 +114,17 @@ Se você gosta de NewPipe, ficaríamos felizes com uma doação. Você pode envi - + - - + + - +
BitcoinBitcoin QR codeBitcoin QR code 16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
LiberapayVisit NewPipe at liberapay.comDonate via LiberapayVisit NewPipe at liberapay.comDonate via Liberapay
BountysourceVisit NewPipe at bountysource.comVisit NewPipe at bountysource.com Check out how many bounties you can earn.
diff --git a/README.ro.md b/doc/README.ro.md similarity index 75% rename from README.ro.md rename to doc/README.ro.md index 71b2ac202..32ab8126e 100644 --- a/README.ro.md +++ b/doc/README.ro.md @@ -1,4 +1,4 @@ -

+

NewPipe

Un front-end de streaming „uşor” liber, pentru Android.

@@ -17,7 +17,7 @@

WebsiteBlogFAQPresă


-*Citiţi în alte limbi: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* +*Citiţi în alte limbi: [English](../README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* Atenţionare: ACEASTA ESTE O VERSIUNE BETA, AŞA CĂ S-AR PUTE SĂ ÎNTÂLNIŢI ERORI. DACĂ SE ÎNTÂMPLĂ ACEST LUCRU, DESCHIDEŢI UN ISSUE PRIN REPSITORY-UL NOSTRU GITHUB. @@ -25,18 +25,18 @@ ## Capturi de ecran -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) -[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) -[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) +[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) +[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) ## Descriere @@ -105,7 +105,7 @@ Recomandăm metoda 1 pentru majoritatea utilizatorilor. APK-urile din metodele 1 Dacă aveţi idei, traduceri, schimbări de design, curaţarea codului, sau schimbări majore ale codului, ajutorul este întotdeauna binevenit. Cu cât se face mai mult cu atât mai bună devine aplicaţia! -Dacă doriţi să vă implicaţi, accesaţi [notele noastre de contribuţie](.github/CONTRIBUTING.md). +Dacă doriţi să vă implicaţi, accesaţi [notele noastre de contribuţie](../.github/CONTRIBUTING.md). Translation status @@ -117,17 +117,17 @@ Dacă vă place NewPipe, am fi bucuroşi să primim o donaţie. Puteţi să ne t - + - - + + - +
BitcoinBitcoin QR codeBitcoin QR code 16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
LiberapayVisit NewPipe at liberapay.comDonate via LiberapayVisit NewPipe at liberapay.comDonate via Liberapay
BountysourceVisit NewPipe at bountysource.comVisit NewPipe at bountysource.com Check out how many bounties you can earn.
diff --git a/README.so.md b/doc/README.so.md similarity index 75% rename from README.so.md rename to doc/README.so.md index 810d8c06d..2b8ab020a 100644 --- a/README.so.md +++ b/doc/README.so.md @@ -1,4 +1,4 @@ -

+

NewPipe

App bilaash ah oo fudud looguna talagalay in Android-ka wax loogu daawado.

@@ -17,7 +17,7 @@

Website-kaMaqaaladaSu'aalaha Aalaa La-iswaydiiyoWarbaahinta


-*Ku akhri luuqad kale: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* +*Ku akhri luuqad kale: [English](../README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* DIGNIIN: MIDKAN, NOOCA APP-KA EE HADDA WALI TIJAABO AYUU KU JIRAA, SIDAA DARTEED CILLADO AYAAD LA KULMI KARTAA. HADAAD LA KULANTO, KA FUR ARIN SHARAXAYA QAYBTANADA ARRIMAHA EE GITHUB-KA. @@ -25,18 +25,18 @@ ## Sawir-shaashadeed -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) -[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) -[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) +[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) +[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) ## Faahfaahin @@ -100,7 +100,7 @@ Waxaa kale, hadaad rabto inaad tixraacayada kala badasho sabab jirta awgeed (tus ## Kusoo Kordhin Hadaad hayso fikrado; rogid, qaab badal, nadiifin koodh, ama koodhka ood si wayn wax oga badashaa—caawinta marwalba waa lasoo dhawaynayaa. Waxbadan hadii la qabto waxbadan ayaa fiicnaan! -Hadaad jeceshahay inaad qayb ka noqoto, fiiri [ogaysiisyada kusoo kordhinta](.github/CONTRIBUTING.md). +Hadaad jeceshahay inaad qayb ka noqoto, fiiri [ogaysiisyada kusoo kordhinta](../.github/CONTRIBUTING.md). Heerka turjimaada @@ -112,17 +112,17 @@ Hadaad jeceshahay NewPipe waan ku faraxsanaan lahayn deeq. Waxaad soo diri karta - + - - + + - +
BitcoinBitcoin QR codeBitcoin QR code 16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
LiberapayVisit NewPipe at liberapay.comDonate via LiberapayVisit NewPipe at liberapay.comDonate via Liberapay
BountysourceVisit NewPipe at bountysource.comVisit NewPipe at bountysource.com Check out how many bounties you can earn.
diff --git a/README.tr.md b/doc/README.tr.md similarity index 74% rename from README.tr.md rename to doc/README.tr.md index b3391f038..6b3169bdb 100644 --- a/README.tr.md +++ b/doc/README.tr.md @@ -1,4 +1,4 @@ -

+

NewPipe

Android için hafif ve özgür bir akış arayüzü.

@@ -17,7 +17,7 @@

Web sitesiBlogSSSBasın


-*Bu sayfayı diğer dillerde okuyun: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* +*Bu sayfayı diğer dillerde okuyun: [English](../README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md).* UYARI: BU SÜRÜM BETA SÜRÜMÜDÜR, BU NEDENLE HATALARLA KARŞILAŞABİLİRSİNİZ. HATA BULURSANIZ BU GITHUB DEPOSUNDA BUNU BİLDİRİN. @@ -25,18 +25,18 @@ ## Ekran görüntüleri -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) -[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) -[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) +[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) +[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) ## Açıklama @@ -104,7 +104,7 @@ Bu arada, herhangi bir nedenle kaynakları değiştirmek istiyorsanız (örneği Fikirleriniz, çevirileriniz, tasarım değişiklikleriniz, kod temizlemeniz veya ağır kod değişiklikleriniz olsun, yardımınıza her zaman açığız. Yapılan her değişiklikle NewPipe daha da iyi bir konuma geliyor! -Eğer yer almak istiyorsanız, [katkı sağlayanlar için hazırladığımız notları](.github/CONTRIBUTING.md) kontrol edin. +Eğer yer almak istiyorsanız, [katkı sağlayanlar için hazırladığımız notları](../.github/CONTRIBUTING.md) kontrol edin. Çeviri istatistikleri @@ -116,17 +116,17 @@ NewPipe'ı beğendiyseniz, yapacağınız bağışlar bizi motive eder. Bitcoin - + - - + + - +
BitcoinBitcoin QR koduBitcoin QR kodu 16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
Liberapayliberapay.com üzerinde NewPipe'ı ziyaret edinLiberapay aracılığıyla bağış yapınliberapay.com üzerinde NewPipe'ı ziyaret edinLiberapay aracılığıyla bağış yapın
Bountysourcebountysource.com üzerinde NewPipe'ı ziyaret edinbountysource.com üzerinde NewPipe'ı ziyaret edin Ne kadar ödül kazanabileceğinizi kontrol edin.
diff --git a/README.zh_TW.md b/doc/README.zh_TW.md similarity index 70% rename from README.zh_TW.md rename to doc/README.zh_TW.md index fdafeb3b9..6be8d0fc4 100644 --- a/README.zh_TW.md +++ b/doc/README.zh_TW.md @@ -1,4 +1,4 @@ -

+

NewPipe

輕巧的 Android 串流前端

@@ -17,7 +17,7 @@

網站部落格FAQ媒體


-*其他語言: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md)* +*其他語言: [English](../README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md)* 警告:這是測試版本,可能會發生錯誤。如果遇到錯誤,請在我們的 GITHUB REPO 開 ISSUE 回報。 @@ -26,18 +26,18 @@ ## 截圖 -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png) -[](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) -[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) -[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png) +[](../fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) +[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) +[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) ## 說明 @@ -109,7 +109,7 @@ NewPipe 支援多種服務。我們的[使用文件](https://teamnewpipe.github. ## 貢獻 若你有任何想法、翻譯、設計、整理原始碼或大範圍的原始碼改動,我們歡迎任何幫助。 -若你想參與,請閱讀[貢獻須知(英文)](.github/CONTRIBUTING.md)。 +若你想參與,請閱讀[貢獻須知(英文)](../.github/CONTRIBUTING.md)。 Translation status @@ -122,17 +122,17 @@ NewPipe 支援多種服務。我們的[使用文件](https://teamnewpipe.github. - + - - + + - +
BitcoinBitcoin QR codeBitcoin QR code 16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
LiberapayVisit NewPipe at liberapay.comDonate via LiberapayVisit NewPipe at liberapay.comDonate via Liberapay
BountysourceVisit NewPipe at bountysource.comVisit NewPipe at bountysource.com Check out how many bounties you can earn.
From 9274e6417ae2b75d2a4023b3aeba45d2dbb2ec2f Mon Sep 17 00:00:00 2001 From: Mohammed Anas Date: Fri, 4 Feb 2022 10:13:10 +0000 Subject: [PATCH 105/119] Add files in `doc` to `paths-ignore` --- .github/workflows/ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 49e78e997..a4c4beb42 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,8 @@ on: - dev - master paths-ignore: - - 'README*.md' + - 'README.md' + - 'doc/**' - 'fastlane/**' - 'assets/**' - '.github/**/*.md' @@ -16,7 +17,8 @@ on: - dev - master paths-ignore: - - 'README*.md' + - 'README.md' + - 'doc/**' - 'fastlane/**' - 'assets/**' - '.github/**/*.md' From 3b1b23ba2a102a626453722fe83995f9920ee9f7 Mon Sep 17 00:00:00 2001 From: Mohammed Anas Date: Fri, 4 Feb 2022 10:32:33 +0000 Subject: [PATCH 106/119] Add `FUNDING.yml` to `paths-ignore` --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a4c4beb42..eedd37c6e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,7 @@ on: - 'fastlane/**' - 'assets/**' - '.github/**/*.md' + - '.github/FUNDING.yml' push: branches: - dev @@ -22,6 +23,7 @@ on: - 'fastlane/**' - 'assets/**' - '.github/**/*.md' + - '.github/FUNDING.yml' jobs: build-and-test-jvm: From 5bf439ad9e3d8fd45e3b82601df875acb255b9bd Mon Sep 17 00:00:00 2001 From: Poussinou Date: Fri, 4 Feb 2022 11:36:00 +0100 Subject: [PATCH 107/119] Update FUNDING.yml (#7682) Co-authored-by: Mohammed Anas --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 2c79d62cd..4137c7635 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1,2 @@ liberapay: TeamNewPipe +custom: 'https://newpipe.net/donate/' From 377914f1d858e95f5d721c30362b4dd4d82b0a93 Mon Sep 17 00:00:00 2001 From: Mohammed Anas Date: Fri, 4 Feb 2022 21:26:37 +0300 Subject: [PATCH 108/119] Small changes to license section of README (#7710) Co-authored-by: opusforlife2 <53176348+opusforlife2@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 186b613f7..28be82192 100644 --- a/README.md +++ b/README.md @@ -140,7 +140,7 @@ Therefore, the app does not collect any data without your consent. NewPipe's pri ## License [![GNU GPLv3 Image](https://www.gnu.org/graphics/gplv3-127x51.png)](https://www.gnu.org/licenses/gpl-3.0.en.html) -NewPipe is Free Software: You can use, study share and improve it at your +NewPipe is Free Software: You can use, study, share, and improve it at will. Specifically you can redistribute and/or modify it under the terms of the [GNU General Public License](https://www.gnu.org/licenses/gpl.html) as published by the Free Software Foundation, either version 3 of the License, or From 2e538b89599cfb6225221d22f1aca3e8eaa758ba Mon Sep 17 00:00:00 2001 From: Tobi Date: Fri, 11 Feb 2022 15:25:25 +0100 Subject: [PATCH 109/119] Add changelog for NewPipe 0.22.0 (983) (#7810) * Add changelog for NewPipe 0.22.0 (983) Co-authored-by: opusforlife2 <53176348+opusforlife2@users.noreply.github.com> Co-authored-by: Mohammed Anas --- fastlane/metadata/android/en-US/changelogs/983.txt | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/983.txt diff --git a/fastlane/metadata/android/en-US/changelogs/983.txt b/fastlane/metadata/android/en-US/changelogs/983.txt new file mode 100644 index 000000000..efbd0557c --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/983.txt @@ -0,0 +1,9 @@ +Add new double-tap-to-seek UI and behaviour +Make settings searchable +Highlight pinned comments as such +Add open-with-app support for FSFE's PeerTube instance +Add error notifications +Fix replay of first queue item on player change +Wait longer when buffering during livestreams before failing +Fix order of local search results +Fix empty item fields in play queue From 608e73e2f2577fa929f2620ab23e2b1ccede0517 Mon Sep 17 00:00:00 2001 From: TiA4f8R <74829229+TiA4f8R@users.noreply.github.com> Date: Thu, 10 Feb 2022 19:48:04 +0100 Subject: [PATCH 110/119] Set workaround for playback position reset when switching to main player with content thumbnail The workaround set before was not applied when switching to main player with content thumbnail from popup or background player. This commit fixes this by applying the workaround when switching to main player with content thumbnail from popup or background player. --- .../schabi/newpipe/fragments/detail/VideoDetailFragment.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index 05630ef79..2d9abc6dc 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 @@ -500,6 +500,10 @@ public final class VideoDetailFragment break; case R.id.detail_thumbnail_root_layout: autoPlayEnabled = true; // forcefully start playing + // FIXME Workaround #7427 + if (isPlayerAvailable()) { + player.setRecovery(); + } openVideoPlayerAutoFullscreen(); break; case R.id.detail_title_root_layout: From f388a1af6770da1aa2517f7edefc9ee7db3563a6 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 11 Feb 2022 20:54:12 +0100 Subject: [PATCH 111/119] Added image-minimizer (#7772) Co-authored-by: Mohammed Anas --- .github/workflows/image-minimizer.js | 107 ++++++++++++++++++++++++++ .github/workflows/image-minimizer.yml | 29 +++++++ 2 files changed, 136 insertions(+) create mode 100644 .github/workflows/image-minimizer.js create mode 100644 .github/workflows/image-minimizer.yml diff --git a/.github/workflows/image-minimizer.js b/.github/workflows/image-minimizer.js new file mode 100644 index 000000000..8d10a1e77 --- /dev/null +++ b/.github/workflows/image-minimizer.js @@ -0,0 +1,107 @@ +/* + * Script for minimizing big images (jpg,gif,png) when they are uploaded to GitHub and not edited otherwise + */ +module.exports = async ({github, context}) => { + const IGNORE_KEY = ''; + const IGNORE_ALT_NAME_END = 'ignoreImageMinify'; + const IMG_MAX_HEIGHT_PX = 600; + + // Get the body of the image + let initialBody = null; + if (context.eventName == 'issue_comment') { + initialBody = context.payload.comment.body; + } else if (context.eventName == 'issues') { + initialBody = context.payload.issue.body; + } else { + console.log('Aborting: No body found'); + return; + } + console.log(`Found body: \n${initialBody}\n`); + + // Check if we should ignore the currently processing element + if (initialBody.includes(IGNORE_KEY)) { + console.log('Ignoring: Body contains IGNORE_KEY'); + return; + } + + // Regex for finding images (simple variant) ![ALT_TEXT](https://*.githubusercontent.com//.) + const REGEX_IMAGE_LOOKUP = /\!\[(.*)\]\((https:\/\/[-a-z0-9]+\.githubusercontent\.com\/\d+\/[-0-9a-f]{32,512}\.(jpg|gif|png))\)/gm; + + // Check if we found something + let foundSimpleImages = REGEX_IMAGE_LOOKUP.test(initialBody); + if (!foundSimpleImages) { + console.log('Found no simple images to process'); + return; + } + + console.log('Found at least one simple image to process'); + + // Require the probe lib for getting the image dimensions + const probe = require('probe-image-size'); + + // Try to find and replace the images with minimized ones + let newBody = await replaceAsync(initialBody, REGEX_IMAGE_LOOKUP, async (match, g1, g2) => { + console.log(`Found match '${match}'`); + + if (g1.endsWith(IGNORE_ALT_NAME_END)) { + console.log(`Ignoring match '${match}': IGNORE_ALT_NAME_END`); + return match; + } + + let shouldModifiy = false; + try { + console.log(`Probing ${g2}`); + let probeResult = await probe(g2); + if (probeResult == null) { + throw 'No probeResult'; + } + if (probeResult.hUnits != 'px') { + throw `Unexpected probeResult.hUnits (expected px but got ${probeResult.hUnits})`; + } + + shouldModifiy = probeResult.height > IMG_MAX_HEIGHT_PX; + } catch(e) { + console.log('Probing failed:', e); + // Immediately abort + return match; + } + + if (shouldModifiy) { + console.log(`Modifying match '${match}'`); + return `${g1}`; + } + + console.log(`Match '${match}' is ok/will not be modified`); + return match; + }); + + // Update the corresponding element + if (context.eventName == 'issue_comment') { + console.log('Updating comment with id', context.payload.comment.id); + await github.rest.issues.updateComment({ + comment_id: context.payload.comment.id, + owner: context.repo.owner, + repo: context.repo.repo, + body: newBody + }) + } else if (context.eventName == 'issues') { + console.log('Updating issue', context.payload.issue.number); + await github.rest.issues.update({ + issue_number: context.payload.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: newBody + }); + } + + // Asnyc replace function from https://stackoverflow.com/a/48032528 + async function replaceAsync(str, regex, asyncFn) { + const promises = []; + str.replace(regex, (match, ...args) => { + const promise = asyncFn(match, ...args); + promises.push(promise); + }); + const data = await Promise.all(promises); + return str.replace(regex, () => data.shift()); + } +} diff --git a/.github/workflows/image-minimizer.yml b/.github/workflows/image-minimizer.yml new file mode 100644 index 000000000..77b1faecf --- /dev/null +++ b/.github/workflows/image-minimizer.yml @@ -0,0 +1,29 @@ +name: Image Minimizer + +on: + issue_comment: + types: [created, edited] + issues: + types: [opened, edited] + +jobs: + try-minimize: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v2 + with: + node-version: 16 + + - name: Install probe-image-size + run: npm i probe-image-size@7.2.3 --ignore-scripts + + - name: Minimize simple images + uses: actions/github-script@v5 + timeout-minutes: 3 + with: + script: | + const script = require('.github/workflows/image-minimizer.js'); + await script({github, context}); From 3223ec04e38b2359ea6c9bd39a6b91dd2feab4ff Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Fri, 11 Feb 2022 20:56:59 +0100 Subject: [PATCH 112/119] Use the correct app language when searching in the settings --- .../java/org/schabi/newpipe/settings/SettingsActivity.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java index 3872e5172..7510bb3bc 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java @@ -2,6 +2,7 @@ package org.schabi.newpipe.settings; import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; +import android.content.Context; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; @@ -228,7 +229,9 @@ public class SettingsActivity extends AppCompatActivity implements // Build search items - final PreferenceParser parser = new PreferenceParser(getApplicationContext(), config); + final Context searchContext = getApplicationContext(); + assureCorrectAppLanguage(searchContext); + final PreferenceParser parser = new PreferenceParser(searchContext, config); final PreferenceSearcher searcher = new PreferenceSearcher(config); // Find all searchable SettingsResourceRegistry fragments From e2a7b9ac56bd2e14b85a407ac4f0bfbba601f9f0 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sat, 12 Feb 2022 20:34:08 +0100 Subject: [PATCH 113/119] Switch to GitHub issue forms (#7773) * Switched to GitHub issue forms See also * https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#creating-issue-forms * https://github.blog/changelog/2021-06-23-issues-forms-beta-for-public-repositories/ * Switched expected and actual behavior * Improved/Reworked issue template Credits to @TheAssassin * CI: Ignore changes to issue-templates * Improved/Reworked issue template Credits to @opusforlife2 and @mhmdanas * Further improved the issue templates * Next round of review Co-authored-by: opusforlife2 <53176348+opusforlife2@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/bug_report.md | 65 ------------ .github/ISSUE_TEMPLATE/bug_report.yml | 113 +++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 24 ----- .github/ISSUE_TEMPLATE/feature_request.yml | 51 ++++++++++ .github/ISSUE_TEMPLATE/question.md | 24 ----- .github/ISSUE_TEMPLATE/question.yml | 35 +++++++ .github/workflows/ci.yml | 2 + 7 files changed, 201 insertions(+), 113 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml delete mode 100644 .github/ISSUE_TEMPLATE/question.md create mode 100644 .github/ISSUE_TEMPLATE/question.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index de16c5cf0..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -name: Bug report -about: Create a bug report to help us improve -labels: bug -assignees: '' - ---- - - - - - - - -### Checklist - - -- [x] I am using the latest version - x.xx.x -- [ ] I checked, but didn't find any duplicates (open OR closed) of this issue in the repo. -- [ ] I have read the contribution guidelines given at https://github.com/TeamNewPipe/NewPipe/blob/HEAD/.github/CONTRIBUTING.md. -- [ ] This issue contains only one bug. I will open one issue for every bug report I want to file. - -### Steps to reproduce the bug - - - - - - -### Actual behavior - - - - -### Expected behavior - - - - -### Screenshots/Screen recordings - - - - - - -### Logs - - - - - - - - -### Device info - - - Android version/Custom ROM version: - - Device model: diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 000000000..a0a9f9ef5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,113 @@ +name: Bug report +description: Create a bug report to help us improve +labels: [bug] +body: + - type: markdown + attributes: + value: | + Thank you for helping to make NewPipe better by reporting a bug. :hugs: + + Please fill in as much information as possible about your bug so that we don't have to play "information ping-pong" and can help you immediately. + + - type: checkboxes + id: checklist + attributes: + label: "Checklist" + options: + - label: "I am able to reproduce the bug with the [latest version](https://github.com/TeamNewPipe/NewPipe/releases/latest)." + required: true + - label: "I made sure that there are *no existing issues* - [open](https://github.com/TeamNewPipe/NewPipe/issues) or [closed](https://github.com/TeamNewPipe/NewPipe/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." + required: true + - label: "I have taken the time to fill in all the required details. I understand that the bug report will be dismissed otherwise." + required: true + - label: "This issue contains only one bug." + required: true + - label: "I have read and understood the [contribution guidelines](https://github.com/TeamNewPipe/NewPipe/blob/dev/.github/CONTRIBUTING.md)." + required: true + + - type: input + id: app-version + attributes: + label: Affected version + description: "In which NewPipe version did you encounter the bug?" + placeholder: "x.xx.x - Can be seen in the app from the 'About' section in the sidebar" + validations: + required: true + + - type: textarea + id: steps-to-reproduce + attributes: + label: Steps to reproduce the bug + description: | + What did you do for the bug to show up? + + If you can't cause the bug to show up again reliably (and hence don't have a proper set of steps to give us), please still try to give as many details as possible on how you think you encountered the bug. + placeholder: | + 1. Go to '...' + 2. Press on '....' + 3. Swipe down to '....' + validations: + required: true + + - type: textarea + id: expected-behavior + attributes: + label: Expected behavior + description: | + Tell us what you expect to happen. + + - type: textarea + id: actual-behavior + attributes: + label: Actual behavior + description: | + Tell us what happens with the steps given above. + + - type: textarea + id: screen-media + attributes: + label: Screenshots/Screen recordings + description: | + A picture or video is worth a thousand words. + + If applicable, add screenshots or a screen recording to help explain your problem. + GitHub supports uploading them directly in the text box. + If your file is too big for Github to accept, try to compress it (ZIP-file) or feel free to paste a link to an image/video hoster here instead. + + :heavy_exclamation_mark: DON'T POST SCREENSHOTS OF THE ERROR PAGE. + Instead, follow the instructions in the "Logs" section below. + + - type: textarea + id: logs + attributes: + label: Logs + description: | + If your bug includes a crash (where you're shown the Error Report page with a bunch of info), tap on "Copy formatted report" at the bottom and paste it here. + + - type: input + id: device-os-info + attributes: + label: Affected Android/Custom ROM version + description: | + With what operating system (+ version) did you encounter the bug? + placeholder: "Example: Android 12 / LineageOS 18.1" + + - type: input + id: device-model-info + attributes: + label: Affected device model + description: | + On what device did you encounter the bug? + placeholder: "Example: Huawei P20 lite (ANE-LX1) / Samsung Galaxy S20" + + - type: textarea + id: additional-information + attributes: + label: Additional information + description: | + Any other information you'd like to include, for instance that + * the affected device is foldable or a TV + * you have disabled all animations on your device + * your cat disabled your network connection + * ... + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 6664ed276..000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -labels: enhancement -assignees: '' - ---- - - - - -### Checklist - - -- [x] I checked, but didn't find any duplicates (open OR closed) of this issue in the repo. -- [ ] I have read the contribution guidelines given at https://github.com/TeamNewPipe/NewPipe/blob/HEAD/.github/CONTRIBUTING.md. -- [ ] This issue contains only one feature request. I will open one issue for every feature I want to request. - -#### What feature do you want? - - - -#### Why do you want this feature? - diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 000000000..83d6f0299 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,51 @@ +name: Feature request +description: Suggest an idea for this project +labels: [enhancement] +body: + - type: markdown + attributes: + value: | + Thank you for helping to make NewPipe better by suggesting a feature. :hugs: + + Your ideas are highly welcome! The app is made for you, the users, after all. + + - type: checkboxes + id: checklist + attributes: + label: "Checklist" + options: + - label: "I made sure that there are *no existing issues* - [open](https://github.com/TeamNewPipe/NewPipe/issues) or [closed](https://github.com/TeamNewPipe/NewPipe/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." + required: true + - label: "I'm aware that this is a request for NewPipe itself and that requests for adding a new service need to be made at [NewPipeExtractor](https://github.com/TeamNewPipe/NewPipeExtractor/issues)." + required: true + - label: "I have taken the time to fill in all the required details. I understand that the feature request will be dismissed otherwise." + required: true + - label: "This issue contains only one feature request." + required: true + - label: "I have read and understood the [contribution guidelines](https://github.com/TeamNewPipe/NewPipe/blob/dev/.github/CONTRIBUTING.md)." + required: true + + + - type: textarea + id: feature-description + attributes: + label: Feature description + description: | + Explain how you want the app's look or behavior to change to suit your needs. + validations: + required: true + + - type: textarea + id: why-is-the-feature-requested + attributes: + label: Why do you want this feature? + description: | + Describe any problem or limitation you come across while using the app which would be solved by this feature. + validations: + required: true + + - type: textarea + id: additional-information + attributes: + label: Additional information + description: Any other information you'd like to include, for instance sketches, mockups, pictures of cats, etc. diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md deleted file mode 100644 index 5582fd407..000000000 --- a/.github/ISSUE_TEMPLATE/question.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -name: Question -about: Ask about anything NewPipe-related -labels: question -assignees: '' - ---- - - - - - -### Checklist - - -- [x] I checked, but didn't find any duplicates (open OR closed) of this issue in the repo. -- [ ] I have read the contribution guidelines given at https://github.com/TeamNewPipe/NewPipe/blob/HEAD/.github/CONTRIBUTING.md. - -#### What's your question(s)? - - -#### Additional context - diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml new file mode 100644 index 000000000..4c42ab26a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.yml @@ -0,0 +1,35 @@ +name: Question +description: Ask about anything NewPipe-related +labels: [question] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this issue! :hugs: + + Note that you can also ask questions on our [IRC channel](https://web.libera.chat/#newpipe). + + - type: checkboxes + id: checklist + attributes: + label: "Checklist" + options: + - label: "I made sure that there are *no existing issues* - [open](https://github.com/TeamNewPipe/NewPipe/issues) or [closed](https://github.com/TeamNewPipe/NewPipe/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." + required: true + - label: "I have taken the time to fill in all the required details. I understand that the question will be dismissed otherwise." + required: true + - label: "I have read and understood the [contribution guidelines](https://github.com/TeamNewPipe/NewPipe/blob/dev/.github/CONTRIBUTING.md)." + required: true + + - type: textarea + id: what-is-the-question + attributes: + label: What is/are your question(s)? + validations: + required: true + + - type: textarea + id: additional-information + attributes: + label: Additional information + description: Any other information you'd like to include, for instance sketches, mockups, pictures of cats, etc. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eedd37c6e..7dbfadc0b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,7 @@ on: - 'assets/**' - '.github/**/*.md' - '.github/FUNDING.yml' + - '.github/ISSUE_TEMPLATE/**' push: branches: - dev @@ -24,6 +25,7 @@ on: - 'assets/**' - '.github/**/*.md' - '.github/FUNDING.yml' + - '.github/ISSUE_TEMPLATE/**' jobs: build-and-test-jvm: From c08a4e851bc927347c26e4be8a3093fce26cd8b5 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Tue, 15 Feb 2022 20:09:21 +0100 Subject: [PATCH 114/119] Improved image-minimizer * Don't minimize images that are too wide -> they will get stretched otherwise * Don't try to modify the issue/comment when nothing changed * Fixed typo --- .github/workflows/image-minimizer.js | 29 +++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/.github/workflows/image-minimizer.js b/.github/workflows/image-minimizer.js index 8d10a1e77..273c6d328 100644 --- a/.github/workflows/image-minimizer.js +++ b/.github/workflows/image-minimizer.js @@ -4,7 +4,12 @@ module.exports = async ({github, context}) => { const IGNORE_KEY = ''; const IGNORE_ALT_NAME_END = 'ignoreImageMinify'; + // Targeted maximum height const IMG_MAX_HEIGHT_PX = 600; + // maximum width of GitHub issues/comments + const IMG_MAX_WIDTH_PX = 800; + // all images that have a lower aspect ration (-> have a smaller width) than this will be minimized + const MIN_ASPECT_RATION = IMG_MAX_WIDTH_PX / IMG_MAX_HEIGHT_PX // Get the body of the image let initialBody = null; @@ -38,6 +43,8 @@ module.exports = async ({github, context}) => { // Require the probe lib for getting the image dimensions const probe = require('probe-image-size'); + + var wasMatchModified = false; // Try to find and replace the images with minimized ones let newBody = await replaceAsync(initialBody, REGEX_IMAGE_LOOKUP, async (match, g1, g2) => { @@ -48,7 +55,7 @@ module.exports = async ({github, context}) => { return match; } - let shouldModifiy = false; + let shouldModify = false; try { console.log(`Probing ${g2}`); let probeResult = await probe(g2); @@ -58,15 +65,26 @@ module.exports = async ({github, context}) => { if (probeResult.hUnits != 'px') { throw `Unexpected probeResult.hUnits (expected px but got ${probeResult.hUnits})`; } + if (probeResult.height <= 0) { + throw `Unexpected probeResult.height (height is invalid: ${probeResult.height})`; + } + if (probeResult.wUnits != 'px') { + throw `Unexpected probeResult.wUnits (expected px but got ${probeResult.wUnits})`; + } + if (probeResult.width <= 0) { + throw `Unexpected probeResult.width (width is invalid: ${probeResult.width})`; + } + console.log(`Probing resulted in ${probeResult.width}x${probeResult.height}px`); - shouldModifiy = probeResult.height > IMG_MAX_HEIGHT_PX; + shouldModify = probeResult.height > IMG_MAX_HEIGHT_PX && (probeResult.width / probeResult.height) < MIN_ASPECT_RATION; } catch(e) { console.log('Probing failed:', e); // Immediately abort return match; } - if (shouldModifiy) { + if (shouldModify) { + wasMatchModified = true; console.log(`Modifying match '${match}'`); return `${g1}`; } @@ -74,6 +92,11 @@ module.exports = async ({github, context}) => { console.log(`Match '${match}' is ok/will not be modified`); return match; }); + + if (!wasMatchModified) { + console.log('Nothing was modified. Skipping update'); + return; + } // Update the corresponding element if (context.eventName == 'issue_comment') { From 7225199debff83ba2dd2839372a928ebe8070dbf Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Wed, 16 Feb 2022 20:31:15 +0100 Subject: [PATCH 115/119] Fixed typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was late when I typed this 😆 --- .github/workflows/image-minimizer.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/image-minimizer.js b/.github/workflows/image-minimizer.js index 273c6d328..80cc5294c 100644 --- a/.github/workflows/image-minimizer.js +++ b/.github/workflows/image-minimizer.js @@ -8,8 +8,8 @@ module.exports = async ({github, context}) => { const IMG_MAX_HEIGHT_PX = 600; // maximum width of GitHub issues/comments const IMG_MAX_WIDTH_PX = 800; - // all images that have a lower aspect ration (-> have a smaller width) than this will be minimized - const MIN_ASPECT_RATION = IMG_MAX_WIDTH_PX / IMG_MAX_HEIGHT_PX + // all images that have a lower aspect ratio (-> have a smaller width) than this will be minimized + const MIN_ASPECT_RATIO = IMG_MAX_WIDTH_PX / IMG_MAX_HEIGHT_PX // Get the body of the image let initialBody = null; @@ -76,7 +76,7 @@ module.exports = async ({github, context}) => { } console.log(`Probing resulted in ${probeResult.width}x${probeResult.height}px`); - shouldModify = probeResult.height > IMG_MAX_HEIGHT_PX && (probeResult.width / probeResult.height) < MIN_ASPECT_RATION; + shouldModify = probeResult.height > IMG_MAX_HEIGHT_PX && (probeResult.width / probeResult.height) < MIN_ASPECT_RATIO; } catch(e) { console.log('Probing failed:', e); // Immediately abort From 42aafd3a2de61261f8940851496287e4ee9741d9 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Fri, 18 Feb 2022 20:36:10 +0100 Subject: [PATCH 116/119] Update NewPipe Extractor to v0.21.14 --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index ead430fd1..042818a03 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -189,7 +189,7 @@ dependencies { // name and the commit hash with the commit hash of the (pushed) commit you want to test // This works thanks to JitPack: https://jitpack.io/ implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751' - implementation 'com.github.TeamNewPipe:NewPipeExtractor:65129e6' + implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.21.14' /** Checkstyle **/ checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}" From 08eb70833d8fffca0be036ea6eba7e6b4a8a6a19 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 18 Feb 2022 20:37:07 +0100 Subject: [PATCH 117/119] Translated using Weblate (Chinese (Simplified)) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 100.0% (64 of 64 strings) Translated using Weblate (Chinese (Traditional, Hong Kong)) Currently translated at 6.2% (4 of 64 strings) Translated using Weblate (Malay) Currently translated at 60.0% (368 of 613 strings) Translated using Weblate (Estonian) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Finnish) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Arabic) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Arabic) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Chinese (Traditional, Hong Kong)) Currently translated at 63.9% (392 of 613 strings) Translated using Weblate (Portuguese) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Dutch) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Dutch) Currently translated at 64.0% (41 of 64 strings) Translated using Weblate (Hebrew) Currently translated at 53.1% (34 of 64 strings) Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Polish) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Greek) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Dutch) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (German) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Polish) Currently translated at 54.6% (35 of 64 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (64 of 64 strings) Translated using Weblate (Norwegian Bokmål) Currently translated at 95.2% (584 of 613 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Slovak) Currently translated at 98.0% (601 of 613 strings) Translated using Weblate (Hungarian) Currently translated at 99.5% (610 of 613 strings) Translated using Weblate (English) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (63 of 63 strings) Translated using Weblate (Dutch) Currently translated at 46.0% (29 of 63 strings) Translated using Weblate (Hebrew) Currently translated at 52.3% (33 of 63 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (63 of 63 strings) Translated using Weblate (Interlingua) Currently translated at 35.0% (215 of 613 strings) Translated using Weblate (Danish) Currently translated at 49.1% (301 of 613 strings) Translated using Weblate (Norwegian Bokmål) Currently translated at 94.2% (578 of 613 strings) Translated using Weblate (Estonian) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Finnish) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Arabic) Currently translated at 99.6% (611 of 613 strings) Translated using Weblate (Dutch) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Dutch) Currently translated at 28.5% (18 of 63 strings) Translated using Weblate (Dutch) Currently translated at 28.5% (18 of 63 strings) Translated using Weblate (Swedish) Currently translated at 48.3% (30 of 62 strings) Translated using Weblate (French) Currently translated at 66.1% (41 of 62 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (62 of 62 strings) Translated using Weblate (Estonian) Currently translated at 99.8% (612 of 613 strings) Translated using Weblate (Catalan) Currently translated at 99.1% (608 of 613 strings) Translated using Weblate (Tamil) Currently translated at 55.4% (340 of 613 strings) Translated using Weblate (Finnish) Currently translated at 99.0% (607 of 613 strings) Translated using Weblate (Swedish) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Armenian) Currently translated at 19.0% (117 of 613 strings) Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Persian) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Turkish) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Indonesian) Currently translated at 99.8% (612 of 613 strings) Translated using Weblate (Japanese) Currently translated at 99.8% (612 of 613 strings) Translated using Weblate (French) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (English) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Sardinian) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Arabic) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Portuguese (Portugal)) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Kurdish (Central)) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Catalan) Currently translated at 99.3% (609 of 613 strings) Translated using Weblate (Lithuanian) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Hebrew) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Portuguese) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Italian) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Dutch) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (French) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Spanish) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (German) Currently translated at 100.0% (613 of 613 strings) Added translation using Weblate (German (Low)) Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Polish) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Greek) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Russian) Currently translated at 100.0% (613 of 613 strings) Translated using Weblate (Malay) Currently translated at 4.8% (3 of 62 strings) Translated using Weblate (Chinese (Traditional, Hong Kong)) Currently translated at 4.8% (3 of 62 strings) Translated using Weblate (Galician) Currently translated at 94.9% (581 of 612 strings) Translated using Weblate (Malay) Currently translated at 60.1% (368 of 612 strings) Translated using Weblate (Malay) Currently translated at 60.1% (368 of 612 strings) Translated using Weblate (Tamil) Currently translated at 49.8% (305 of 612 strings) Translated using Weblate (Finnish) Currently translated at 97.2% (595 of 612 strings) Translated using Weblate (Arabic) Currently translated at 100.0% (612 of 612 strings) Translated using Weblate (Chinese (Traditional, Hong Kong)) Currently translated at 57.1% (350 of 612 strings) Translated using Weblate (French) Currently translated at 99.6% (610 of 612 strings) Translated using Weblate (English (United Kingdom)) Currently translated at 7.6% (47 of 612 strings) Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (62 of 62 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (62 of 62 strings) Translated using Weblate (Tamil) Currently translated at 44.6% (273 of 612 strings) Translated using Weblate (Arabic) Currently translated at 99.8% (611 of 612 strings) Co-authored-by: A Co-authored-by: Agnieszka C Co-authored-by: Ajeje Brazorf Co-authored-by: Albert Vila Co-authored-by: Alex25820 Co-authored-by: Alfonso Scarpino Co-authored-by: Allan Nordhøy Co-authored-by: Danial Behzadi Co-authored-by: Davit Mayilyan Co-authored-by: Denys Nykula Co-authored-by: Eric Co-authored-by: GnuPGを使うべきだ Co-authored-by: GobinathAL Co-authored-by: Guillem Co-authored-by: Hosted Weblate Co-authored-by: Ihor Hordiichuk Co-authored-by: JY3 Co-authored-by: Jeff Huang Co-authored-by: John Smith Co-authored-by: Karl Tammik Co-authored-by: Lim Jia Ming Co-authored-by: Linerly Co-authored-by: Marian Hanzel Co-authored-by: Mark Co-authored-by: Mohammed Anas <6daf084a-8eaf-40fb-86c7-8500077c3b69@anonaddy.me> Co-authored-by: Mohammed Anas Co-authored-by: MohammedSR Vevo Co-authored-by: My Co-authored-by: Ray Co-authored-by: Rex_sa Co-authored-by: Ricardo Co-authored-by: S3aBreeze Co-authored-by: SamTada Co-authored-by: Software In Interlingua Co-authored-by: THANOS SIOURDAKIS Co-authored-by: Thomas Frarke Co-authored-by: TobiGr Co-authored-by: Vasilis K Co-authored-by: VfBFan Co-authored-by: Ville Rantanen Co-authored-by: WB Co-authored-by: Yaron Shahrabani Co-authored-by: chr56 Co-authored-by: gymka Co-authored-by: jojo Co-authored-by: mm4c Co-authored-by: nzgha Co-authored-by: ssantos Co-authored-by: translator Co-authored-by: xainsworth <202120614015@ogr.balikesir.edu.tr> Co-authored-by: Ács Zoltán Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/fr/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/he/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ms/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/nl/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pl/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/sv/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/uk/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/zh_Hans/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/zh_Hant_HK/ Translation: NewPipe/Metadata --- app/src/main/res/values-ar/strings.xml | 65 ++-- .../main/res/values-b+zh+HANS+CN/strings.xml | 3 +- app/src/main/res/values-ca/strings.xml | 14 +- app/src/main/res/values-ckb/strings.xml | 12 +- app/src/main/res/values-da/strings.xml | 1 + app/src/main/res/values-de/strings.xml | 7 +- app/src/main/res/values-el/strings.xml | 5 +- app/src/main/res/values-en-rGB/strings.xml | 5 +- app/src/main/res/values-es/strings.xml | 1 + app/src/main/res/values-et/strings.xml | 5 +- app/src/main/res/values-fa/strings.xml | 3 +- app/src/main/res/values-fi/strings.xml | 26 +- app/src/main/res/values-fr/strings.xml | 7 +- app/src/main/res/values-gl/strings.xml | 44 ++- app/src/main/res/values-he/strings.xml | 1 + app/src/main/res/values-hu/strings.xml | 1 + app/src/main/res/values-hy/strings.xml | 15 +- app/src/main/res/values-ia/strings.xml | 8 + app/src/main/res/values-in/strings.xml | 1 + app/src/main/res/values-it/strings.xml | 1 + app/src/main/res/values-ja/strings.xml | 3 +- app/src/main/res/values-lt/strings.xml | 21 +- app/src/main/res/values-ms/strings.xml | 6 +- app/src/main/res/values-nb-rNO/strings.xml | 5 +- app/src/main/res/values-nds/strings.xml | 2 + app/src/main/res/values-nl/strings.xml | 3 +- app/src/main/res/values-pl/strings.xml | 11 +- app/src/main/res/values-pt-rBR/strings.xml | 3 +- app/src/main/res/values-pt-rPT/strings.xml | 1 + app/src/main/res/values-pt/strings.xml | 11 +- app/src/main/res/values-ru/strings.xml | 1 + app/src/main/res/values-sc/strings.xml | 1 + app/src/main/res/values-sk/strings.xml | 15 + app/src/main/res/values-sv/strings.xml | 1 + app/src/main/res/values-ta/strings.xml | 286 +++++++++++++----- app/src/main/res/values-tr/strings.xml | 9 +- app/src/main/res/values-uk/strings.xml | 5 +- app/src/main/res/values-zh-rHK/strings.xml | 142 +++++---- app/src/main/res/values-zh-rTW/strings.xml | 1 + app/src/main/res/values/strings.xml | 4 +- .../metadata/android/fr/changelogs/981.txt | 2 + .../metadata/android/he/changelogs/982.txt | 1 + .../metadata/android/he/changelogs/983.txt | 9 + .../metadata/android/ms/changelogs/63.txt | 8 + .../metadata/android/ms/changelogs/64.txt | 8 + .../metadata/android/ms/full_description.txt | 1 + .../metadata/android/ms/short_description.txt | 1 + .../metadata/android/nl/changelogs/63.txt | 8 + .../metadata/android/nl/changelogs/64.txt | 8 + .../metadata/android/nl/changelogs/770.txt | 4 + .../metadata/android/nl/changelogs/820.txt | 1 + .../metadata/android/nl/changelogs/830.txt | 1 + .../metadata/android/nl/changelogs/850.txt | 1 + .../metadata/android/nl/changelogs/860.txt | 7 + .../metadata/android/nl/changelogs/870.txt | 2 + .../metadata/android/nl/changelogs/900.txt | 14 + .../metadata/android/nl/changelogs/910.txt | 1 + .../metadata/android/nl/changelogs/920.txt | 9 + .../metadata/android/nl/changelogs/950.txt | 4 + .../metadata/android/nl/changelogs/952.txt | 7 + .../metadata/android/nl/changelogs/953.txt | 1 + .../metadata/android/nl/changelogs/954.txt | 6 - .../metadata/android/nl/changelogs/957.txt | 16 +- .../metadata/android/nl/changelogs/958.txt | 15 + .../metadata/android/nl/changelogs/961.txt | 12 + .../metadata/android/nl/changelogs/962.txt | 2 + .../metadata/android/nl/changelogs/963.txt | 1 + .../metadata/android/nl/changelogs/964.txt | 8 + .../metadata/android/nl/changelogs/965.txt | 6 + .../metadata/android/nl/changelogs/966.txt | 14 + .../metadata/android/nl/changelogs/967.txt | 1 + .../metadata/android/nl/changelogs/968.txt | 7 + .../metadata/android/nl/changelogs/973.txt | 4 + .../metadata/android/nl/changelogs/974.txt | 5 + .../metadata/android/nl/changelogs/975.txt | 17 ++ .../metadata/android/nl/changelogs/976.txt | 10 + .../metadata/android/nl/changelogs/977.txt | 10 + .../metadata/android/nl/changelogs/978.txt | 1 + .../metadata/android/nl/changelogs/979.txt | 2 + .../metadata/android/nl/changelogs/980.txt | 13 + .../metadata/android/nl/changelogs/981.txt | 2 + .../metadata/android/nl/changelogs/982.txt | 1 + .../metadata/android/nl/changelogs/983.txt | 9 + .../metadata/android/nl/full_description.txt | 2 +- .../metadata/android/nl/short_description.txt | 2 +- .../metadata/android/pl/changelogs/983.txt | 9 + .../metadata/android/sv/changelogs/870.txt | 2 + .../metadata/android/sv/changelogs/910.txt | 1 + .../metadata/android/sv/changelogs/950.txt | 4 + .../metadata/android/sv/changelogs/953.txt | 1 + .../metadata/android/sv/changelogs/955.txt | 3 + .../metadata/android/sv/changelogs/956.txt | 1 + .../metadata/android/sv/changelogs/960.txt | 4 + .../metadata/android/sv/changelogs/962.txt | 2 + .../metadata/android/sv/changelogs/963.txt | 1 + .../metadata/android/sv/changelogs/967.txt | 1 + .../metadata/android/sv/changelogs/971.txt | 3 + .../metadata/android/sv/changelogs/973.txt | 4 + .../metadata/android/sv/changelogs/974.txt | 5 + .../metadata/android/sv/changelogs/978.txt | 1 + .../metadata/android/uk/changelogs/65.txt | 1 + .../metadata/android/uk/changelogs/66.txt | 1 + .../metadata/android/uk/changelogs/68.txt | 1 + .../metadata/android/uk/changelogs/69.txt | 1 + .../metadata/android/uk/changelogs/70.txt | 1 + .../metadata/android/uk/changelogs/740.txt | 1 + .../metadata/android/uk/changelogs/750.txt | 1 + .../metadata/android/uk/changelogs/760.txt | 1 + .../metadata/android/uk/changelogs/800.txt | 1 + .../metadata/android/uk/changelogs/810.txt | 1 + .../metadata/android/uk/changelogs/840.txt | 1 + .../metadata/android/uk/changelogs/982.txt | 1 + .../metadata/android/uk/changelogs/983.txt | 9 + .../metadata/android/uk/full_description.txt | 2 +- .../android/zh-Hans/changelogs/982.txt | 1 + .../android/zh-Hans/changelogs/983.txt | 9 + .../android/zh-Hans/full_description.txt | 2 +- .../android/zh_Hant_HK/changelogs/981.txt | 2 + .../android/zh_Hant_HK/changelogs/983.txt | 9 + .../android/zh_Hant_HK/full_description.txt | 1 + .../android/zh_Hant_HK/short_description.txt | 1 + 121 files changed, 855 insertions(+), 255 deletions(-) create mode 100644 app/src/main/res/values-nds/strings.xml create mode 100644 fastlane/metadata/android/fr/changelogs/981.txt create mode 100644 fastlane/metadata/android/he/changelogs/982.txt create mode 100644 fastlane/metadata/android/he/changelogs/983.txt create mode 100644 fastlane/metadata/android/ms/changelogs/63.txt create mode 100644 fastlane/metadata/android/ms/changelogs/64.txt create mode 100644 fastlane/metadata/android/ms/full_description.txt create mode 100644 fastlane/metadata/android/ms/short_description.txt create mode 100644 fastlane/metadata/android/nl/changelogs/63.txt create mode 100644 fastlane/metadata/android/nl/changelogs/64.txt create mode 100644 fastlane/metadata/android/nl/changelogs/770.txt create mode 100644 fastlane/metadata/android/nl/changelogs/820.txt create mode 100644 fastlane/metadata/android/nl/changelogs/830.txt create mode 100644 fastlane/metadata/android/nl/changelogs/850.txt create mode 100644 fastlane/metadata/android/nl/changelogs/860.txt create mode 100644 fastlane/metadata/android/nl/changelogs/870.txt create mode 100644 fastlane/metadata/android/nl/changelogs/900.txt create mode 100644 fastlane/metadata/android/nl/changelogs/910.txt create mode 100644 fastlane/metadata/android/nl/changelogs/920.txt create mode 100644 fastlane/metadata/android/nl/changelogs/950.txt create mode 100644 fastlane/metadata/android/nl/changelogs/952.txt create mode 100644 fastlane/metadata/android/nl/changelogs/953.txt delete mode 100644 fastlane/metadata/android/nl/changelogs/954.txt create mode 100644 fastlane/metadata/android/nl/changelogs/958.txt create mode 100644 fastlane/metadata/android/nl/changelogs/961.txt create mode 100644 fastlane/metadata/android/nl/changelogs/962.txt create mode 100644 fastlane/metadata/android/nl/changelogs/963.txt create mode 100644 fastlane/metadata/android/nl/changelogs/964.txt create mode 100644 fastlane/metadata/android/nl/changelogs/965.txt create mode 100644 fastlane/metadata/android/nl/changelogs/966.txt create mode 100644 fastlane/metadata/android/nl/changelogs/967.txt create mode 100644 fastlane/metadata/android/nl/changelogs/968.txt create mode 100644 fastlane/metadata/android/nl/changelogs/973.txt create mode 100644 fastlane/metadata/android/nl/changelogs/974.txt create mode 100644 fastlane/metadata/android/nl/changelogs/975.txt create mode 100644 fastlane/metadata/android/nl/changelogs/976.txt create mode 100644 fastlane/metadata/android/nl/changelogs/977.txt create mode 100644 fastlane/metadata/android/nl/changelogs/978.txt create mode 100644 fastlane/metadata/android/nl/changelogs/979.txt create mode 100644 fastlane/metadata/android/nl/changelogs/980.txt create mode 100644 fastlane/metadata/android/nl/changelogs/981.txt create mode 100644 fastlane/metadata/android/nl/changelogs/982.txt create mode 100644 fastlane/metadata/android/nl/changelogs/983.txt create mode 100644 fastlane/metadata/android/pl/changelogs/983.txt create mode 100644 fastlane/metadata/android/sv/changelogs/870.txt create mode 100644 fastlane/metadata/android/sv/changelogs/910.txt create mode 100644 fastlane/metadata/android/sv/changelogs/950.txt create mode 100644 fastlane/metadata/android/sv/changelogs/953.txt create mode 100644 fastlane/metadata/android/sv/changelogs/955.txt create mode 100644 fastlane/metadata/android/sv/changelogs/956.txt create mode 100644 fastlane/metadata/android/sv/changelogs/960.txt create mode 100644 fastlane/metadata/android/sv/changelogs/962.txt create mode 100644 fastlane/metadata/android/sv/changelogs/963.txt create mode 100644 fastlane/metadata/android/sv/changelogs/967.txt create mode 100644 fastlane/metadata/android/sv/changelogs/971.txt create mode 100644 fastlane/metadata/android/sv/changelogs/973.txt create mode 100644 fastlane/metadata/android/sv/changelogs/974.txt create mode 100644 fastlane/metadata/android/sv/changelogs/978.txt create mode 100644 fastlane/metadata/android/uk/changelogs/65.txt create mode 100644 fastlane/metadata/android/uk/changelogs/66.txt create mode 100644 fastlane/metadata/android/uk/changelogs/68.txt create mode 100644 fastlane/metadata/android/uk/changelogs/69.txt create mode 100644 fastlane/metadata/android/uk/changelogs/70.txt create mode 100644 fastlane/metadata/android/uk/changelogs/740.txt create mode 100644 fastlane/metadata/android/uk/changelogs/750.txt create mode 100644 fastlane/metadata/android/uk/changelogs/760.txt create mode 100644 fastlane/metadata/android/uk/changelogs/800.txt create mode 100644 fastlane/metadata/android/uk/changelogs/810.txt create mode 100644 fastlane/metadata/android/uk/changelogs/840.txt create mode 100644 fastlane/metadata/android/uk/changelogs/982.txt create mode 100644 fastlane/metadata/android/uk/changelogs/983.txt create mode 100644 fastlane/metadata/android/zh-Hans/changelogs/982.txt create mode 100644 fastlane/metadata/android/zh-Hans/changelogs/983.txt create mode 100644 fastlane/metadata/android/zh_Hant_HK/changelogs/981.txt create mode 100644 fastlane/metadata/android/zh_Hant_HK/changelogs/983.txt create mode 100644 fastlane/metadata/android/zh_Hant_HK/full_description.txt create mode 100644 fastlane/metadata/android/zh_Hant_HK/short_description.txt diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 0b17fdfd2..d1f19dbc2 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -214,7 +214,7 @@ استيراد قاعدة البيانات تصدير قاعدة البيانات يلغي السجل الحالي والاشتراكات وقوائم التشغيل والإعدادات (اختياريًا) - تصديرالسجل، وقوائم تشغيل، والإعدادات، والاشتراكات + تصدير السجل، وقوائم تشغيل، والإعدادات، والاشتراكات عرض المعلومات إضافة إلى تحليل @@ -238,7 +238,7 @@ هل تريد حذف قائمة التشغيل هذه؟ تم إنشاء قائمة التشغيل تمت إضافتها إلى قائمة التشغيل - ملئ الشاشة + ملء الشاشة تكبير تنزيل ملف البث الإشارات المرجعية @@ -255,9 +255,9 @@ تناسب مع الشاشة توليد تلقائي إستيراد - إستعادة مِن + استعادة مِن تصدير إلى - عملية الإستعادة جارية … + عملية الاستعادة جارية … عملية التصدير جارية … إستيراد ملف معرفك, soundcloud.com/هويتك @@ -411,7 +411,7 @@ المواضع في القوائم إظهار مؤشّرات وضع التشغيل في القوائم امسح البيانات - تم حذف وضع التشغيل + تم حذف كل مواقف التشغيل نقل الملف أو حذفه يوجد ملف بهذا الاسم مسبقاً لا يمكن الكتابة فوق الملف @@ -420,11 +420,11 @@ لم يتبقى مساحة في الجهاز تم فقد التقدم بسبب حذف الملف انتهى وقت الاتصال - هل تريد محو سجل التنزيل أو حذف جميع الملفات التي تم تنزيلها؟ + هل تريد محو سجل التنزيل، أم تريد حذف جميع الملفات التي تم تنزيلها؟ حد قائمة انتظار التنزيل سيتم تشغيل تنزيل واحد في نفس الوقت بدء التنزيلات - إيقاف التحميل مؤقتا + إيقاف التحميل مؤقتًا اسأل عن مكان التنزيل سيتم سؤالك عن مكان حفظ كل تنزيل. \nتمكين منتقي مجلد النظام (SAF) إذا كنت تريد التنزيل إلى بطاقة SD خارجية @@ -465,7 +465,7 @@ محلي أُضيف مؤخرًا الأكثر إعجابًا - تم إنشاؤه-تلقائيًا (لم يتم العثور على برنامج تحميل) + مُنشأة تلقائيًا (لم يتم العثور على رافع) استرد لا يمكن استرداد هذا التنزيل اختيار مثيل @@ -486,11 +486,11 @@ %d ثانية %d ثانية - هل تعتقد تحميل التغذية بطيء جدا؟ إذا كان الأمر كذلك، فحاول تمكين التحميل السريع (يمكنك تغييره في الإعدادات أو بالضغط على الزر أدناه). + هل تعتقد أن تحميل التغذية بطيءٌ جدًا؟ إذا كان الأمر كذلك، فحاول تمكين التحميل السريع (يمكنك تغييره في الإعدادات أو بالضغط على الزر أدناه). \n \nيقدم NewPipe استراتيجيتين لتحميل الخلاصة: \n• جلب قناة الاشتراك بأكملها، وهي بطيئة ولكنها كاملة. -\n• استخدام نقطة نهاية خدمة مخصصة، وهي سريعة ولكنها عادة لا تكتمل. +\n• استخدام نقطة نهاية خدمة مخصصة، وهي سريعة ولكنها عادةً لا تكتمل. \n \nالفرق بين الاثنين هو أن العنصر السريع عادة ما يفتقر إلى بعض المعلومات، مثل مدة العنصر أو نوعه (لا يمكن التمييز بين مقاطع الفيديو المباشرة والأخرى العادية) وقد يعيد عناصر أقل. \n @@ -525,15 +525,15 @@ مجموعات القنوات %d يوم - %d أيام + %d يوم %d أيام %d أيام - %d أيام - %d أيام + %d يومًا + %d يومًا %d ساعة - %d ساع + %d ساعة %d ساعة %d ساعات %d ساعة @@ -551,9 +551,9 @@ إلغاء كتم الصوت كتم الصوت مساعدة - هذا المحتوى ليس مدعوم من قبل NewPipe. + هذا المحتوى ليس مدعومًا من قبل NewPipe. \n -\nنأمل أن يكون مدعوما في التحديثات القادمة. +\nنأمل أن يكون مدعومًا في التحديثات القادمة. ∞ فيديو +100 فيديو الفنانين @@ -577,7 +577,7 @@ إظهار الاشتراكات غير المجمعة فقط لا توجد إشارات مرجعية لقائمة التشغيل حتى الآن اختر قائمة تشغيل - يرجى مراجعة ما إذا توجد بالفعل مشكلة تناقش التحطم الموجود بالفعل.عند إنشاء تذاكر مكررة، فإنك تستغرق منا وقتًا يمكن أن نقضيه في إصلاح الخطأ الفعلي. + يرجى مراجعة ما إذا توجد بالفعل مشكلة تناقش التحطم الموجود بالفعل. عند إنشاء تذاكر مكررة، فإنك تستغرق منا وقتًا يمكن أن نقضيه في إصلاح الخطأ الفعلي. تقرير على GitHub نسخ التقرير مُنسق عرض نتائج ل: %s @@ -618,7 +618,7 @@ إظهار الصورة المصغرة قم بإيقاف التشغيل لإخفاء مربعات المعلومات الوصفية بمعلومات إضافية حول منشئ، البث أو محتوى البث أو طلب البحث إظهار معلومات التعريف - الأخيرة + حديثة حساب التجزئة إشعارات لتقدم تجزئة الفيديو إشعار تجزئة الفيديو @@ -633,17 +633,17 @@ يتوفر هذا المحتوى فقط للمستخدمين الذين قاموا بالدفع، لذلك لا يمكن بثه أو تنزيله عبر NewPipe. يتوفر هذا الفيديو فقط لأعضاء YouTube Music Premium، لذلك لا يمكن بثه أو تنزيله من قبل NewPipe. هذا المحتوى خاص، لذلك لا يمكن دفقه أو تنزيله بواسطة NewPipe. - هذا مسار SoundCloud Go + ، على الأقل في بلدك ، لذلك لا يمكن دفقه أو تنزيله بواسطة NewPipe. + هذا مسار SoundCloud Go+، على الأقل في بلدك، لذلك لا يمكن دفقه أو تنزيله بواسطة NewPipe. هذا المحتوى غير متوفر في بلدك. اغلق التطبيق قسريا هذا الفيديو مقيد بالفئة العمرية. -\nنظرا لسياسات YouTube الجديدة المتعلقة بمقاطع الفيديو المقيدة بالفئة العمرية، لا يمكن ل NewPipe الوصول إلى أي من مقاطع الفيديو الخاصة بها وبالتالي لا يمكن تشغيلها. +\nنظرا لسياسات YouTube الجديدة المتعلقة بمقاطع الفيديو المقيدة بالفئة العمرية، لا يمكن لـNewPipe الوصول إلى أي من مقاطع الفيديو الخاصة بها وبالتالي لا يمكن تشغيلها. إذاعة المميزة حل بدأ التنزيل يمكنك اختيار نسقك الليلي المفضل أدناه - حدد موضوعك الليلي المفضل - %s + حدد موضوعك الليلي المفضل — %s تلقائي (سمة الجهاز) الثيم الليلي إظهار تفاصيل القناة @@ -653,14 +653,14 @@ خاص غير مدرج عامة - عنوان URL للصورة المصغرة + رابط الصورة المصغرة المضيف الدعم اللغة الحد العمري الخصوصيّة الرخصة - الفئة + الوسوم الصنف تعطيل تحديد النص في الوصف تمكين تحديد نص في الوصف @@ -672,10 +672,10 @@ حساب منشئ المحتوى قد تم إنهائه. \nلن يتمكن NewPipe من تحميل هذه الخلاصة في المستقبل. \nهل تريد إلغاء الاشتراك من هذه القناة؟ - تعذر تحميل تغذية ل \'%s\'. + تعذر تحميل تغذية لـ\'%s\'. خطأ في تحميل الخلاصة بدءًا من Android 10، يتم دعم \"Storage Access Framework\" فقط - لا يتم دعم \"Storage Access Framework\" على Android KitKat والإصدارات الأقدم + \"Storage Access Framework\" غير مدعوم على Android KitKat والإصدارات الأقدم سيتم سؤالك عن مكان حفظ كل تنزيل لم يتم تعيين مجلد التحميل، الرجاء اختيار مجلد التحميل الافتراضي الآن إيقاف @@ -688,7 +688,7 @@ جودة عالية (أكبر) معاينة مصغرة على شريط التمرير علّمه كفيديو تمت مشاهدته - اعجب بها منشئ المحتوى + أعجب بها منشئ المحتوى جاري تحميل تفاصيل القناة… خطأ في عرض تفاصيل القناة أظهر أشرطة ملونة لبيكاسو أعلى الصور تشير إلى مصدرها: الأحمر للشبكة والأزرق للقرص والأخضر للذاكرة @@ -697,12 +697,12 @@ اقتراحات البحث المحلية اسحب العناصر لإزالتها - اكتمل %1$s التنزيل - اكتمل %1$s التنزيل - اكتمل %1$s التنزيل - اكتملت %1$s التنزيلات - اكتملت %1$s التنزيلات - اكتملت %1$s التنزيلات + اكتمل %1$s تنزيل + اكتمل %1$s تنزيل + اكتمل %1$s تنزيل + اكتملت %1$s تنزيلات + اكتمل %1$s تنزيل + اكتمل %1$s تنزيل اكتمل التنزيل @@ -736,4 +736,5 @@ \nالرجاء تثبيت مدير ملفات متوافق مع Storage Access Framework. يتم تشغيله في الخلفية تعليق مثبت + LeakCanary غير متوفر \ 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 10777db8f..9ae77924a 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 @@ -115,7 +115,7 @@ 等待中 已暂停 已加入队列 - 排队 + 加入队列 操作已被系统拒绝 下载失败 没有评论 @@ -676,4 +676,5 @@ NewPipe 遇到了一个错误,点击此处报告此错误 已经在后台播放 置顶评论 + LeakCanary 不可用 \ No newline at end of file diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 327175f1c..034cbc875 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -285,7 +285,8 @@ \n3. Premeu \"Totes les dades incloses\", després \"Dessel·lecciona-ho tot\", llavors sel·leccioneu només \"Subscripcions\" i finalment premeu \"D\'acord\". \n4. Premeu \"Pas següent\" i llavors a \"Crea una exportació\" \n5. Premeu el botó \"Baixa\" un cop hagi aparegut -\n6. Del fitxer comprimit baixat, extreieu-ne el fitxer subscripcions.json (es troba a \"Takeout/YouTube i YouTube Music/subscripcions/subscripcions.json\") i importeu-lo aquí.
+\n6. Premeu a IMPORTA EL FITXER i sel·leccioneu el fitxer .zip descarregat +\n7. [En cas que la importació del fitxer .zip hagi fallat] extreieu-ne el fitxer subscripcions.csv (es troba generalment a \"Takeout/YouTube i YouTube Music/subscripcions/subscripcions.csv\"), premeu a IMPORTA EL FITXER i sel·leccioneu el fitxer .csv extret.
Importeu un perfil del SoundCloud mitjançant l\'URL o l\'identificador del vostre perfil: \n \n1. Activeu el «Mode d\'ordinador» en un navegador (el lloc web no està disponible per a dispositius mòbils) @@ -401,7 +402,8 @@ Limita la cua de baixades Inicia les baixades Pausa les baixades - Si us demanarà la ubicació de cada baixada + Se us demanarà la ubicació de cada baixada. +\nHeu d\'activar el SAF si voleu descarregar-ho a una targeta SD externa Posicions a les llistes Mostra els indicadors de posició de reproducció a les llistes Neteja les dades @@ -414,9 +416,8 @@ S\'ha esborrat les posicions de reproducció El fitxer s\'ha mogut o suprimit Només una baixada alhora - Utilitza SAF - El SAF (Storage Access Framework; estructura d\'accés a l\'emmagatzematge) us permet realitzar baixades a una memòria externa com una targeta SD. -\nAlguns dispositius no en són compatibles + Fes servir el SAF + El SAF (Storage Access Framework; estructura d\'accés a l\'emmagatzematge) us permet realitzar baixades a una memòria externa com una targeta SD. Esborra les posicions de reproducció Esborra totes les posicions de reproducció Voleu suprimir tots els punts de reproducció\? @@ -482,7 +483,7 @@ \nEn definitiva, l\'elecció depèn de si preferiu rapidesa a assegurar-vos que l\'informació és precisa. Desactiva el mode ràpid Activa el mode ràpid - Disponible en alguns serveis, normalment és més ràpid, però podria només incloure un nombre limitat de contingut i sovint informació incomplerta (per exemple, sense durada, tipus…). + Disponible en alguns serveis, normalment és més ràpid, però podria només incloure un nombre limitat de contingut i sovint informació incomplerta (per exemple, sense durada, tipus…) Recupera des d\'un feed dedicat si és possible Actualitza sempre Temps que ha de passar perquè una subscripció es consideri obsoleta — %s @@ -687,4 +688,5 @@ Mostrar \"tancar de forma violenta el reproductor\" Mostra una opció de fallada quan s\'utilitza el reproductor Mostra les cintes de color Picasso a la part superior de les imatges que indiquen la seva font: vermell per a la xarxa, blau per al disc i verd per a la memòria + El LeakCanary no està disponible \ No newline at end of file diff --git a/app/src/main/res/values-ckb/strings.xml b/app/src/main/res/values-ckb/strings.xml index 36de64297..036aa19f5 100644 --- a/app/src/main/res/values-ckb/strings.xml +++ b/app/src/main/res/values-ckb/strings.xml @@ -191,7 +191,7 @@ بینراو نییە ئەو فایله‌ بوونی نییە یان دەسەڵاتی خوێندنەوە و نوسینی لاوازە ناتوانرێت ماڵپەڕ شیبکرێتەوە - ڕه‌نووسه‌ ڕێ پێدراوه‌كانله‌ فایله‌ ناوییه‌كاندا + ڕه‌نووسه‌ ڕێپێدراوه‌كان له‌ فایله‌ ناوییه‌كاندا ئایدییەکەت ، soundcloud.com/yourid یارمەتی چی نوێ هه‌یه‌ @@ -462,9 +462,9 @@ ڕه‌نووسی جێگۆڕین ڕێكخستنه‌كان دابه‌زێنراو - بۆ هاورده‌ كردنی بەژداربوونەکانی یوتوب له‌ گووگڵه‌وه‌: + بۆ هاورده‌كردنی بەژداربوونەکانی یوتوب له‌ گووگڵه‌وه‌: \n -\n1. ئەم بەستەرە بکەوە: %1$s +\n1. ئەم بەستەرە بکەرەوە: %1$s \n2. بچۆرەژوورەوە گەر داوای‌ کرد \n3. كرته‌ بكه‌ له‌ \"All data included\"، پاشان كرته‌ بكه‌ له‌ \"Deselect all\" ، پاشان ته‌نیا \"subscriptions\" هه‌ڵبژێره‌ پاشان كرته‌ له‌ \"OK\" بكه‌ \n4. كرته‌ بكه‌ له‌ \"Next step\" و دواتر له‌ \"Create export\" @@ -682,4 +682,10 @@ بابەتە نوێیەکانی فیید لێدوانی هەڵواسراو کڕاش کردنی لێدەر + پیشاندانی هەڵەی سناکباڕ + هیچ ڕێکخەرێکی فایلی گونجاو نەدۆزرایەوە بۆ ئەم کردارە. +\nتکایە ڕێکخەری فایلییەک دابمەزرێنە لۆ هەوڵدانی ناکاراکردنی \'%s\' لە ڕێکخستنەکانی دابەزاندندا. + LeakCanary بەردەست نییە + هیچ ڕێکخەرێکی فایلی گونجاو نەدۆزرایەوە بۆ ئەم کردارە. +\nتکایە ڕێکخەرێکی فایلی دابمەزرێنە کە گونجاوبێت لەگەڵ دەسەڵاتی گەیشتن بە بیرگە. \ No newline at end of file diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 23abdc2da..d348dc4a2 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -396,4 +396,5 @@ Tredje handlingstast Viser resultater for: %s Åben med + LeakCanary er ikke tilgængelig \ 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 a4c622087..ba15174a9 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -600,7 +600,7 @@ Dieses Video ist nur für YouTube Music Premium-Mitglieder verfügbar und kann daher nicht von NewPipe gestreamt oder heruntergeladen werden. Dies ist ein SoundCloud Go+ Track, zumindest in deinem Land, kann er von NewPipe nicht gestreamt oder heruntergeladen werden. Dieser Inhalt ist in deinem Land nicht verfügbar. - Absturz der App + App abstürzen lassen Dieses Video ist altersbeschränkt. \nAufgrund neuer YouTube-Richtlinien mit altersbeschränkten Videos kann NewPipe auf keinen dieser Videostreams zugreifen und ist daher nicht in der Lage, es abzuspielen. Radio @@ -673,8 +673,8 @@ Suche nach Aktualisierungen… Manuelle Prüfung auf neue Versionen Neue Feed-Elemente - \"Absturz des Players\" anzeigen - Absturz des Players + \"Player abstürzen lassen\" anzeigen + Player abstürzen lassen Zeigt eine Absturzoption an, wenn der Player verwendet wird Benachrichtigung über Fehlerberichte Benachrichtigungen zur Meldung von Fehlern @@ -688,4 +688,5 @@ \nBitte installiere einen Storage Access Framework kompatiblen Dateimanager. Wird bereits im Hintergrund abgespielt Angehefteter Kommentar + LeakCanary ist nicht verfügbar \ 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 804cbc5bc..29745830a 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -79,7 +79,7 @@ Αδύνατη η αλλαγή της εγγραφής Αδύνατη η ενημέρωση της εγγραφής Συνδρομές - Αγαπημένες λίστες αναπαραγωγής + Λίστες αναπαραγωγής με σελιδοδείκτες Τι νέο υπάρχει Στο παρασκήνιο Αναδυόμενο παράθυρο @@ -673,7 +673,7 @@ Χειροκίνητος έλεγχος για νέα έκδοση Έλεγχος αναβάθμισης Νέα αντικείμενα τροφοδοσίας - Εμφάνιση «κατάρρευσης αναπαραγωγέα» + Εμφάνιση «Κατάρρευσης αναπαραγωγέα» Εμφανίζει μια επιλογή κατάρρευσης κατά τη χρήση του αναπαραγωγέα Κατάρρευση αναπαραγωγέα Ειδοποίηση αναφοράς σφάλματος @@ -688,4 +688,5 @@ Εμφάνιση μιας snackbar σφάλματος Αναπαράγεται ήδη στο παρασκήνιο Καρφιτσωμένο σχόλιο + Το LeakCanary δεν είναι διαθέσιμο \ No newline at end of file diff --git a/app/src/main/res/values-en-rGB/strings.xml b/app/src/main/res/values-en-rGB/strings.xml index 2fc6954fd..b1c3d0187 100644 --- a/app/src/main/res/values-en-rGB/strings.xml +++ b/app/src/main/res/values-en-rGB/strings.xml @@ -16,8 +16,9 @@ \n2. Log in when asked \n3. Click on ‘All data included’, then on ‘Deselect all’, then select only ‘subscriptions’ and click ‘OK’ \n4. Click on ‘Next step’ and then on ‘Create export’ -\n5. Click on the ‘Download’ button after it appears and -\n6. From the downloaded takeout zip extract the .json file (usually under ‘YouTube and YouTube Music/subscriptions/subscriptions.json’) and import it here. +\n5. Click on the ‘Download’ button after it appears +\n6. Click on IMPORT FILE below and select the downloaded .zip file +\n7. [If the .zip import fails] Extract the .csv file (usually under ‘YouTube and YouTube Music/subscriptions/subscriptions.csv’), click on IMPORT FILE below and select the extracted csv file
Press ‘Done’ when solved This video is age restricted. \n diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 442bfeb24..bd40f0c61 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -691,4 +691,5 @@ \nPor favor instale un gestor de archivos compatible con \"Sistema de Acceso al Almacenamiento\". Comentario fijado Ya se reproduce en segundo plano + LeakCanary no está disponible \ No newline at end of file diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index e7f75ea09..b22d1e782 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -312,7 +312,7 @@ Anneta NewPipe võtab privaatsust väga tõsiselt. Seetõttu ei kogu rakendus ilma nõusolekuta mingeid andmeid. \nNewPipe privaatsuspoliitika selgitab üksikasjalikult, milliseid andmeid saadetakse ja kogutakse veateate saatmisel. - NewPipe vaba avatud koodiga tarkvara. Seada võib kasutada, uurida, jagada ja parandada. Täpsemalt - seda võib levitada ja/või muuta vastavalt Vaba Tarkvara Sihtasutuse avaldatud GNU Üldise Avaliku Litsentsi v.3 (või hilisem) tingimustele. + NewPipe vaba avatud koodiga tarkvara. Seada võid kasutada, uurida, jagada ja parandada nii, nagu õigemaks pead. Täpsemalt - seda võid levitada ja/või muuta vastavalt Vaba Tarkvara Sihtasutuse avaldatud GNU Üldise Avaliku Litsentsi v.3 (või sinu valikul hilisema versiooni) tingimustele. Teavita elutsüklist väljas vigadest Impordi SoundCloudi profiil trükkides URL või oma ID: \n @@ -673,7 +673,7 @@ Kontrolli uuendusi Kontrolli uuendusi käsitsi Uued andmevoo kirjed - Näita „jooksuta meediamängija kokku“ nupukest + Näita „Jooksuta meediamängija kokku“ nupukest Näitab valikut meediamängija kokkujooksutamiseks NewPipe töös tekkis viga, sellest teavitamiseks klõpsi Jooksuta meediamängija kokku @@ -688,4 +688,5 @@ Selle tegevuse jaoks ei leidunud sobilikku failihaldurit. \nPalun paigalda nutiseadmesse failihaldur, mis järgib Storage Access Framework reeglistikku. Esiletõstetud kommentaar + LeakCanary pole saadaval \ No newline at end of file diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index 20494637d..db8e85f17 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -353,7 +353,7 @@ کنش پیش‌فرض در زمان باز کردن محتوا — %s تغییر سبک پس‌زمینه و اندازه متن توضیحات پخش‌کننده. برای تأثیر، نیازمند آغاز دوبارهٔ کاره است پاک کردن تاریخچه جریان‌های پخش شه و موقعیت‌های پخش - نیوپایپ، یک نرم‌افزار آزاد کپی‌لِفت است: شما می‌توانید از آن استفاده، آن را بررسی کرده و به دیگران بدهید و اگر مایل باشید، بهترش کنید. به طور خاص، شما می‌توانید آن را تحت پروانه عمومی همگانی گنو نسخه ۳ و یا در صورت تمایل بالاتر، که توسط بنیاد نرم‌افزار آزاد منتشر شده تغییر داده و بازنشر دهید. + نیوپایپ یک نرم‌افزار آزاد کپی‌لفتی است: می‌توانید به دلخواه خود استفاده، بررسی، هم‌رسانی و بهترش کنید. به طور خاص می‌توانید ذیل نگارش ۳ یا هر نگارش بالاتری از پروانهٔ جامع همگانی گنو که به دست بنیاد نرم‌افزار آزاد منتشر شده، تغییر و بازنشرش دهید. حریم شخصی شما برای پروژه نیویایپ بسیاری جدی است. در نتیجه، این برنامه هیچ اطلاعاتی را بدون رضایت شما گردآوری نمی‌کند. \nسیاست‌های حریم شخصی نیوپایپ با جزئیات توضیح می‌دهد که وقتی گزارش یک خطا را می‌فرستید، چه داده‌هایی ذخیره و فرستاده می‌شود. به منظور هماهنگی با مقررات حفاظت داده عمومی اروپا (GDPR) در اینجا توجه شما را به سیاست حریم شخصی نیوپایپ جلب می‌کنیم. لطفا آن را به دقت مطالعه کنید. @@ -688,4 +688,5 @@ خطایی رخ داد. آگاهی را ببینید نظر سنجاق شده در حال پخش در پس‌زمینه + لیک‌کاناری موجود نیست \ No newline at end of file diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 581ba1eb9..2c871c051 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -78,8 +78,8 @@ Pyyhi Paras resoluutio Peru - NewPipe Ilmoitus - Ilmoitukset NewPipen tausta- ja ponnahdusikkunasoittimille + NewPipe ilmoitus + Ilmoitukset NewPipen soittimille Virhe Verkkovirhe Kaikkia esikatselukuvia ei voitu ladata @@ -304,7 +304,7 @@ \n3. Klikkaa \"Kaikki Youtube-data valittuna\", sitten \"Poista kaikki valinnat\", sitten ainoastaan \"tilaukset\" ja klikkaa \"OK\" \n4. Klikkaa \"Seuraava vaihe\" ja \"Luo vienti\" \n5. Klikkaa \"Lataa\"-painiketta tämän ilmestyessä -\n6. Klikkaa TUO TIEDOSTO alhaalta ja valitse ladattu tiedosto +\n6. Klikkaa TUO TIEDOSTO alhaalta ja valitse ladattu .zip-tiedosto \n7. [Jos zip-tiedoston tuonti epäonnistuu] Pura .csv-tiedosto (yleensä sijainnissa \"Youtube ja Youtube Musiikki/tilaukset/tilaukset.csv\") ja klikkaa TUO TIEDOSTO alhaalta ja valitse purettu csv-tiedosto Tuo SoundCloud-profiili kirjoittamalla joko osoite tai ID:si: \n @@ -337,7 +337,7 @@ Peru tilaus Valitse välilehti Valmis - Jono + Lisää jonoon Eteen-/taaksepäinkelauksen aika-askeleen pituus Hiljattain lisätyt Paikalliset @@ -369,7 +369,7 @@ Lataaminen ulkoiselle SD-kortille ei ole mahdollista. Nollataanko latauskansion sijainti\? Ulkoinen tallennustila ei käytettävissä Ohje - Ilmoitukset uudesta NewPipe-versiosta + Ilmoitukset uusista NewPipe-versioista Sovelluspäivitysilmoitus Tiedosto poistettu Esittäjät @@ -672,4 +672,20 @@ Tarkista päivitykset Tarkista manuaalisesti onko uusia versioita saatavilla Tarkistetaan päivityksiä… + Ilmoitukset, joilla raportoidaan virheistä + Kiinnitetty kommentti + Virheraportti-ilmoitus + NewPipe kohtasi virheen, näpäytä raportoidaksesi + Tapahtui virhe, katso ilmoitus + Luo virheilmoitus + LeakCanary ei ole saatavilla + Näytä \"Kaada soitin\" + Kaada soitin + Toiminnolle ei löytynyt sopivaa tiedostonhallintaohjelmaa. +\nAsenna tiedostonhallintaohjelma, joka on yhteensopiva Storage Access Frameworkin kanssa. + Toiminnolle ei löytynyt sopivaa tiedostonhallintaohjelmaa. +\nAsenna tiedostonhallintaohjelma tai kokeile asettaa \'%s\' pois käytöstä latausasetuksista. + Näytä soitinta käytettäessä soittimen kaatamisen vaihtoehto + Näytä virheen ponnahdusilmoitus + Uudet syötteet \ 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 d4946f545..8acc53603 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -310,7 +310,7 @@ Voulez-vous supprimer entièrement l’historique de recherche \? Historique de recherche supprimé 1 élément supprimé. - NewPipe est un logiciel sous licence libre copyleft : vous pouvez l’utiliser, l’étudier, le partager et l’améliorer comme bon vous semble. Plus précisément, vous pouvez le redistribuer ou le modifier sous les termes de la licence générale publique GNU, comme publiée par la Free Software Foundation, dans sa version 3, ou, à votre convenance, dans une quelconque version ultérieure. + NewPipe est un logiciel sous licence libre copyleft : vous pouvez l’utiliser, l’étudier, le partager, et l’améliorer comme bon vous semble. Plus précisément, vous pouvez le redistribuer ou le modifier sous les termes de la licence générale publique GNU, comme publiée par la Free Software Foundation, dans sa version 3, ou, à votre convenance, dans une quelconque version ultérieure. Politique de confidentialité de NewPipe Lire la politique de confidentialité Voulez-vous également importer les paramètres \? @@ -383,7 +383,7 @@ Utile lors du basculement aux données mobiles, bien que certains téléchargements ne peuvent pas être suspendus Mode de vue en liste post-traitement - Liste de lecture + Mettre en file d\'attente Action refusée par le système Le post-traitement a échoué Nombre d’essais maximum @@ -685,9 +685,10 @@ Créer une notification d\'erreur Aucun gestionnaire de fichiers approprié n\'a été trouvé pour cette action. \nVeuillez installer un gestionnaire de fichiers compatible avec l\'Infrastructure d\'accès au stockage. - Montrer une erreur en bas de l\'écran + Afficher une barre d\'erreur Aucun gestionnaire de fichier approprié n\'a été trouvé pour cette action. \nVeuillez installer un gestionnaire de fichiers ou essayez de désactiver \'%s\' dans les paramètres de téléchargement. Commentaire épinglé Une lecture est déjà en arrière-plan + LeakCanary n\'est pas disponible \ No newline at end of file diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 39d49f7e2..a9357a5cd 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -73,7 +73,7 @@ Continuar reproducindo o vídeo despois das interrupcións (como, por exemplo, as chamadas) Descarregar Mostrar vídeos \"seguintes\" e \"semellantes\" - Mostrar a suxestión \"Manteña presionado para engadir á cola\" + Mostrar a suxestión \"Manteña presionado para engadir á fila\" Amosar o consello ao premer o fondo ou o botón emerxente \"Detalles:\" no vídeo URL non soportado País predeterminado para o contido @@ -86,7 +86,7 @@ Reproducindo en segundo plano Reproducindo en modo «popup» Contido - Contido restrinxido para certa idade + Mostrar contido con restrición de idade En directo Descargas Descargas @@ -106,15 +106,15 @@ Só unha vez Ficheiro Notificación do NewPipe - Notificacións para os reprodutores de fondo e reprodutores emerxentes de NewPipe + Notificacións para o reprodutor de NewPipe [Descoñecido] Mudar para o segundo plano Mudar para o «popup» Mudar para principal Importar base de datos Exportar base de datos - Anula o teu historial e subscricións actuais - Exportar historial, subscricións e listas de reprodución + Anula o seu historial, subscricións, listas de reprodución e (opcionalmente) configuracións + Exportar historial, subscricións, listas de reprodución e configuración Limpar historial de reproducións Elimina o historial de transmisións reproducidas e as posicións da reprodución Eliminar todo o historial de reproducións\? @@ -145,7 +145,7 @@ Non hai emisións para descargar Deculpe, isto non debería ter acontecido. Informar deste erro por enderezo electrónico - Desculpe, ocorreron algúns erros. + Desculpe, algo foi mal. Informe Información: Que ocorreu: @@ -227,7 +227,7 @@ \nA política de privacidade do NewPipe explica con máis detalle que datos son enviados e gardados cando envía un relatorio de erros. Ler a política de privacidade Licenza do NewPipe - NewPipe é un software libre copyleft: Podes usar, estudar compartir e melloralo a vontade. En concreto, pode redistribuír e / ou modificala segundo os termos da Licenza Pública Xeral GNU publicada pola Free Software Foundation, xa sexa a versión 3 da licenza, ou (na súa opción) calquera outra versión posterior. + NewPipe é un software libre copyleft: Pode usar, estudar compartir e melloralo a vontade. En concreto, pode redistribuír e / ou modificala segundo os termos da Licenza Pública Xeral GNU publicada pola Free Software Foundation, xa sexa a versión 3 da licenza, ou (na súa opción) calquera outra versión posterior. Ler a licenza Historial Historial @@ -494,7 +494,7 @@ Non hai dispoñible conta de subscritores Cambiar o servizo actualmente seleccionado: Verifique se xa existe un problema que fala do seu fallo. Ao crear billetes duplicados, gasta o tempo que nós poderiamos gastar en solucionar o erro real. - Informar dun erro en GitHub + Reportar en GitHub Copia o informe con formato Dar permiso para mostrar noutros aplicativos Quere restaurar os valores predeterminados\? @@ -508,7 +508,7 @@ Eliminas todas as posicións de reprodución\? Elimina todas as posicións de reprodución Elimina as posicións de reprodución - Notificacións para a nova versión de NewPipe + Notificacións para as novas versións de NewPipe Notificación da actualización do aplicativo Ficheiro eliminado Artistas @@ -518,8 +518,8 @@ Vídeos Este vídeo está restrinxido por idade. \n -\nSe desexa visualizalo, habilite \"%1$s\" nos axustes. - Modo restrinxido de YouTube +\nSe desexa visualizalo, habilite \"%1$s\" nas opcións. + Activar modo restrinxido de YouTube Actualizacións A instancia xa existe Non se puido validar a instancia @@ -542,7 +542,7 @@ Amosando resultados para: %s Procesando Repetir - Podes seleccionar como máximo tres accións para amosar na notificación compacta! + Pode seleccionar como máximo tres accións para amosar na notificación compacta! Primeiro botón de acción Segundo botón de acción Terceiro botón de acción @@ -566,7 +566,7 @@ Categoría Deshabilitar a selección do texto da descrición Habilitar a selección do texto na descrición - Agora podes seleccionar o texto na descrición. Teña en conta que a páxina pode cintilar e as ligazóns poden non ser clicábeis no modo selección. + Agora pode seleccionar o texto na descrición. Teña en conta que a páxina pode cintilar e as ligazóns poden non ser clicábeis no modo selección. Automático (Tema do dispositivo) Radio %s dá este motivo: @@ -617,7 +617,7 @@ Prendido Provedor Destacado - Este contido só está dispoñíbel para usuarios que pagaran por el, así que non pode ser transmitido ou decarregado por NewPipe. + Este contido só está dispoñíbel para usuarios que pagaran por el, así que non pode ser transmitido ou descarregado por NewPipe. Será preguntado onde desexa gardar cada descarga Non mostrar Baixa calidade (máis pequeno) @@ -656,4 +656,20 @@ Cambiar dun reprodutor a outro pode substituír a súa cola Barallar Edite cada acción da notificación premendo nela. Seleccione ata tres delas para seren mostradas na notificación compacta usando as checkboxes da dereita + Enfileirar o seguinte vídeo + Inciar reprodutor principal en pantalla completa + Non iniciar vídeos no reprodutor mini, mais cambiar a pantalla completa directamente, se a rotación estiver bloqueada. Aínda pode acceder o reprodutor mini ao saír da pantalla completa + Deslice os elementos para removelos + Non foi atopado ningún xestor de arquivos adecuado para esta acción. +\nPor favor instale un ou tente deshabilitar \'%s\' nas opcións de descarregamento. + Non foi atopado ningún xestor de arquivos adecuado para esta acción. +\nPor favor instale un compatíbel co Sistema de Acceso ao Almacenamento. + Valorado polo creador + Ocorreu un erro, vexa a notificación + Auto-enfileirar + Esta é unha pista de SoundCloud Go+, polo menos no seu país, así que non pode ser transmitida ou descarregada por NewPipe. + Notificación de relatorio de erros + Notificacións para reportar erros + NewPipe atopou un erro, presione para reportar + Comentario fixado \ 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 dfbca0e4a..3ec3ee00b 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -712,4 +712,5 @@ \nנא להתקין מנהל קבצים שתומך בתשתית גישה לאחסון.
כבר מתנגן ברקע הערה ננעצה + LeakCanary אינה זמינה \ No newline at end of file diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index cc398b4d9..04fe0cd01 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -688,4 +688,5 @@ Rögzített megjegyzés Már megy a lejátszás a háttérben + LeakCanary nem elérhető \ No newline at end of file diff --git a/app/src/main/res/values-hy/strings.xml b/app/src/main/res/values-hy/strings.xml index d7da33600..ea2750a93 100644 --- a/app/src/main/res/values-hy/strings.xml +++ b/app/src/main/res/values-hy/strings.xml @@ -21,7 +21,7 @@ Մաքրել Հրապարակվել է %1$s Տեղադրել - Վերացնել + Չեղարկել Բացել բրաուզերում Ձայնային բեռնման պանակ Ընտրեք ներբեռնման թղթապանակը տեսաֆայլերի համար @@ -131,4 +131,17 @@ Միշտ Բեռնել Ցանկերում դիրքերը + Ինքնանվագարկում + Մաքրել դիտման պատմությունը + Մաքրել ներբեռնման պատմությունը + Աուդիո + Նշել որպես դիտված + Կրկնել + Նվագարկիչ + Պատմություն և քեշ + Գիշերային ոճ + Կանգ + Պատմություն + Պատմություն + Թրենդային \ 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 index e19955a66..656a37d25 100644 --- a/app/src/main/res/values-ia/strings.xml +++ b/app/src/main/res/values-ia/strings.xml @@ -227,4 +227,12 @@ Supporto Recente Interne + Aperir con + Suggestiones de recerca remote + Cargar miniaturas + Notification + Monstrante resultatos pro: %s + Solmente alicun apparatos pote reproducer videos 2K/4K + Initiar le reproductor principal in schermo plen + Solmente le URLs HTTPS es supportate \ No newline at end of file diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index bed00bfe5..3a714b5ab 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -676,4 +676,5 @@ \nMohon instal sebuah manajer file yang kompatibel dengan Storage Access Framework.
Komentar dipin Sudah diputar di latar belakang + LeakCanary tidak tersedia \ 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 66932597e..524e83a89 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -688,4 +688,5 @@ \nInstallane uno compatibile con Storage Access Framework.
Commento in primo piano Già in riproduzione in sottofondo + LeakCanary non è disponibile \ No newline at end of file diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 1b191c994..f659a9149 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -272,7 +272,7 @@ 支援する NewPipe プロジェクトはあなたのプライバシーを非常に大切にしています。あなたの同意がない限り、アプリはいかなるデータも収集しません。 \nNewPipe のプライバシー・ポリシーでは、クラッシュリポート送信時にどのような種類のデータが送信・記録されるかを詳細に説明しています。 - NewPipe はコピーレフトなソフトウェアです。あなたは自由にそれを使用し、研究し、そして改善することができます。あなたは、GNU フリーソフトウェア財団が公開する GNU General Public ライセンス バージョン3以降の下に、自由に再配布・修正を行うことができます。 + NewPipe はコピーレフトなソフトウェアです。あなたは自由にそれを使用し、研究し、共有し、そして改善することができます。あなたは、GNU フリーソフトウェア財団が公開する GNU General Public ライセンス バージョン3以降の下に、自由に再配布・修正を行うことができます。 最終再生日時 最も再生された動画 拡大 @@ -676,4 +676,5 @@ プレイヤー使用時にクラッシュオプションを表示 エラー通知を作成 エラーを報告する通知 + LeakCanaryが利用不可能です \ No newline at end of file diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index e5bfd4506..7608e6821 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -134,7 +134,7 @@ Atgal Groti viską NewPipe pranešimai - Foninio ir langelio rėžimo grotuvų pranešimai + NewPipe grotuvo pranešimai [Nežinoma] Srauto atkurti nepavyko Įvyko nepataisoma grotuvo klaida @@ -310,7 +310,7 @@ Išvalyti reCAPTCHA slapukus Pranešimas apie video maišos progresą Video maišos pranešimas - Pranešimas apie naują NewPipe versija + Pranešimas apie naują NewPipe versiją Programos atnaujinimo pranešimas Failą Failas pašalintas @@ -470,7 +470,7 @@ Užverti Sustabdyti Perrašyti - Eilė + Į eilę apdorojama eilėje sustabdyta @@ -685,4 +685,19 @@ Tikrinti ar yra atnaujinimų rankiniu būdu Tikrinti ar yra atnaujinimų… Nauji sklaidos kanalo elementai + LeakCanary neprieinama + Naudojant grotuvą rodo lūžio parinkty + Rodyti klaidos juostą + Prisegtas komentaras + Nerasta tinkama failų tvarkyklė. +\nĮdiekite „Storage Access Framework“ suderinamą su šia failų tvarkykle. + Pranešimai pranešimui apie klaidas + Rodyti „grotuvas užlūžo“ + Sukurti klaidos pranešimą + NewPipe susidūrė su klaida, paspauskite norėdami pranešti + Šiam veiksmui nerastas tinkama failų tvarkyklė. +\nĮdiekite failų tvarkyklę arba pabandykite išjungti „%s“ parsiuntimo nustatymuose. + Užlūžo + Klaidos pranešimo pranešimas + Įvyko klaida, peržiūrėti pranešimą \ No newline at end of file diff --git a/app/src/main/res/values-ms/strings.xml b/app/src/main/res/values-ms/strings.xml index 8a4691219..d102b529d 100644 --- a/app/src/main/res/values-ms/strings.xml +++ b/app/src/main/res/values-ms/strings.xml @@ -1,6 +1,6 @@ - Tekan \"Cari\" untuk bermula + Tekan kanta kaca \"Cari\" untuk bermula Diterbitkan pada %1$s Tiada pemain strim ditemui. Muat turun VLC\? Tiada pemain strim yang ditemui (anda boleh memasang VLC untuk memainkan). @@ -43,7 +43,7 @@ Papar resolusi yang lebih tinggi Hanya peranti tertentu yang boleh bermain video 2K/4K Main dengan Kodi - App Kore tidak dijumpai. Pasangkan\? + Pasangkan aplikasi Kore yang tidak dijumpai\? Paparkan opsyen \"Main dengan Kodi\" Paparkan opsyen untuk memain video dengan Kodi Audio @@ -442,4 +442,6 @@ tidak boleh tulis ganti fail Fail dengan nama yang sama sudah ada Jangan tunjuk + Nyahbisu + Minta Android menyesuaikan warna pemberitahuan sesuai dengan warna utama di thumbnail (perhatikan bahawa ini tidak tersedia dalam semua perangkat) \ 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 92b3a30ed..251083236 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -118,7 +118,7 @@ Tøm Beste oppløsning NewPipe-merknad - Merknad for NewPipe-bakgrunn og oppsprettsspillere + Merknad for NewPipe sin avspiller Last ned Tillate tegn i filnavn Ugyldige tegn erstattes av denne verdien @@ -364,7 +364,7 @@ pauset I kø etterbehandling - + Legg i kø Handling avvist av systemet Nedlasting mislyktes Generer unikt navn @@ -684,4 +684,5 @@ Vis et feil-alternativsfelt Installer en filbehandler først, eller skru av «%s» i nedlastingsinnstillingene. Installer en filbehandler som støtter lagringstilgangsrammeverk først. + LeakCanary er ikke tilgjengelig \ No newline at end of file diff --git a/app/src/main/res/values-nds/strings.xml b/app/src/main/res/values-nds/strings.xml new file mode 100644 index 000000000..a6b3daec9 --- /dev/null +++ b/app/src/main/res/values-nds/strings.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index f3837ef7d..92eabcab1 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -310,7 +310,7 @@ De gehele zoekgeschiedenis wissen\? Zoekgeschiedenis gewist 1 item verwijderd. - NewPipe is vrije software: je kan het gebruiken, bestuderen, delen en verbeteren zoveel je maar wil. Je kan het opnieuw uitgeven en/of aanpassen volgens de voorwaarden van de GNU General Public License, gepubliceerd door de Free Software Foundation, versie 3 van de licentie, of (indien gewenst) om het even welke latere versie. + NewPipe is vrije software: je kan het gebruiken, bestuderen, delen en verbeteren zoveel je maar wilt. Je kan het opnieuw uitgeven en/of aanpassen volgens de voorwaarden van de GNU General Public License, gepubliceerd door de Free Software Foundation, versie 3 van de licentie, of (indien gewenst) om het even welke latere versie. Wil je ook de instellingen importeren? NewPipe\'s privacybeleid Het NewPipe-project neemt privacy serieus. Daarom verzamelt de app geen gegevens zonder jouw toestemming. @@ -688,4 +688,5 @@ Er is geen geschikte bestandsbeheerder gevonden voor deze actie. \nInstalleer een bestandsbeheerder die compatibel is met het Storage Access Framework. Vastgemaakt commentaar + LeakCanary is niet beschikbaar \ 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 0577f2f5d..55300925b 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -175,10 +175,10 @@ Większość znaków specjalnych Dotacja - NewPipe jest rozwijany przez wolontariuszy, którzy poświęcają swój wolny czas, by zapewnić Ci jak najlepsze wrażenia podczas korzystania z aplikacji. To dobry moment, aby wesprzeć programistów i sprawić, by program był jeszcze lepszy, delektując się filiżanką kawy. + NewPipe jest rozwijany przez wolontariuszy, którzy poświęcają swój wolny czas, zapewniając Ci najlepsze wrażenia z użytkowania. To dobry moment na wsparcie programistów i sprawienie, aby NewPipe był jeszcze lepszy, podczas gdy oni będą mogli delektować się filiżanką kawy. Wspomóż Strona internetowa - By otrzymać więcej informacji oraz najnowsze wiadomości o NewPipe, odwiedź naszą stronę. + Odwiedź stronę NewPipe, aby uzyskać więcej informacji i najnowsze wiadomości. Czy chcesz usunąć tę pozycję z historii wyszukiwania? Zawartość strony głównej Pusta strona @@ -355,7 +355,7 @@ Nie udało się odczytać zapisanych kart, więc będą używane domyślne Przywróć domyślne Czy chcesz przywrócić ustawienia domyślne\? - Liczba subskrybentów jest niedostępna + Liczba subskrybentów niedostępna Karty wyświetlane na stronie głównej Aktualizacje Pokazuj powiadomienie zachęcające do pobrania aktualizacji aplikacji, gdy jest dostępna nowa wersja @@ -639,7 +639,7 @@ Tagi Kategoria Otwórz stronę - Teraz możesz zaznaczyć tekst wewnątrz opisu. Pamiętaj, że strona może migotać, a łącza mogą nie być klikane w trybie zaznaczania. + Teraz możesz zaznaczyć tekst wewnątrz opisu. Pamiętaj, że strona może migotać, a łącza mogą nie być klikalne w trybie zaznaczania. %s podaje ten powód: Konto zamknięte Tryb szybki dla ładowania kanału nie dostarcza więcej informacji na ten temat. @@ -694,7 +694,7 @@ Nowe pozycje kanału Pokazuje opcję psucia podczas korzystania z odtwarzacza Zepsuj odtwarzacz - Pokazuj „zepsuj odtwarzacz” + Pokazuj „Zepsuj odtwarzacz” Powiadomienie raportu o błędach Powiadomienia do zgłaszania błędów NewPipe napotkał błąd. Naciśnij, aby zgłosić @@ -707,4 +707,5 @@ \nZainstaluj menedżer plików zgodny z Storage Access Framework. Już jest odtwarzane w tle Przypięty komentarz + LeakCanary jest niedostępne \ 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 a77d38f97..841839909 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -673,7 +673,7 @@ Procurar manualmente por novas versões Procurando por atualizações… Travar o player - Mostrar \"travar o player\" + Mostrar \"Travar o player\" Mostra uma opção de travamento ao usar o player Novos itens do feed Notificação de relatório de erro @@ -688,4 +688,5 @@ \nInstale um gerenciador de arquivos ou tente desativar \'%s\' nas configurações de download.
Já está tocando em segundo plano Comentário fixado + O LeakCanary não está disponível \ No newline at end of file diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 85fe30ca1..ef920fb9c 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -688,4 +688,5 @@ \nPor favor, instale um gestor de ficheiros compatível com o Storage Access Framework.
Comentário fixado Já está a reproduzir em segundo plano + LeakCanary não está disponível \ 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 326bab03b..70c50a89e 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -68,7 +68,7 @@ Iniciar Pausa Eliminar - Checksum + Soma de controlo Nome do ficheiro Erro Toque para detalhes @@ -79,7 +79,7 @@ Processos Descarga NewPipe Aplicação terminou em erro - O quê:\\nPedido:\\nIdioma do conteúdo:\\nPaís do conteúdo\\nIdioma da app\\nServiço:\\nHora GMT:\\nPacote:\\nVersão:\\nVersão do SO: + O quê:\\nPedido:\\nIdioma do conteúdo:\\nPaís do conteúdo\\nIdioma da aplicação\\nServiço:\\nHora GMT:\\nPacote:\\nVersão:\\nSO Versão: Abrir no modo popup Preto Tudo @@ -97,7 +97,7 @@ Resolução padrão para janela popup Mostrar resoluções mais altas Apenas alguns dispositivos conseguem reproduzir vídeos em 2K/4K - Popup + popup Lembrar propriedades do popup Limpar Segundo plano @@ -421,7 +421,7 @@ Limpar posições de reprodução Remove todas as posições de reprodução Remover todas as posições de reprodução\? - Alternar serviço, agora selecionado: + Alternar serviço atualmente selecionado: \'Kiosk\' padrão Ninguém está a ver @@ -674,7 +674,7 @@ A procurar atualizações… Novos itens Travar o reprodutor - Mostrar \"travar o reprodutor\" + Mostrar \"Travar o reprodutor\" Mostra uma opção de travamento ao usar o reprodutor Notificação de relatório de erros Notificações para reportar erros @@ -688,4 +688,5 @@ \nPor favor, instale um gestor de ficheiros compatível com o Storage Access Framework.
Já está a reproduzir em segundo plano Comentário fixado + LeakCanary não está disponível \ 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 6c357fa13..e5a8e53b8 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -704,4 +704,5 @@ \nПожалуйста, установите файловый менеджер, совместимый со Storage Access Framework (SAF).
Уже проигрывается в фоне Закреплённый комментарий + LeakCanary недоступна \ No newline at end of file diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml index 3ca5ae972..1b4e4c37c 100644 --- a/app/src/main/res/values-sc/strings.xml +++ b/app/src/main/res/values-sc/strings.xml @@ -688,4 +688,5 @@ Faghe serrare su riproduidore Cummentu apicadu Giai in riprodutzione in s\'isfundu + LeakCanary no est a disponimentu \ No newline at end of file diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 09f6e484a..1253ef053 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -685,4 +685,19 @@ Ručne skontrolovať nové verzie Kontrolujú sa aktualizácie… Nové položky informačného kanála + Pre túto akciu sa nenašiel vhodný správca súborov. +\nNainštalujte si správcu súborov alebo skúste vypnúť \'%s\' v nastaveniach sťahovania. + Zobraziť „zlyhanie prehrávača“ + LeakCanary nie je k dispozícii + Pre túto akciu sa nenašiel vhodný správca súborov. +\nNainštalujte správcu súborov kompatibilného s rozhraním Storage Access Framework. + Pripnutý komentár + Zlyhanie prehrávača + Nahlásenie chyby + Hlásenie chýb + V NewPipe sa vyskytla chyba, klepnutím ju nahláste + Vyskytla sa chyba, pozrite si upozornenie + Zobrazí možnosť zlyhania pri používaní prehrávača + Zobraziť krátke oznámenie chyby + Oznámte chybu \ No newline at end of file diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 59d7e9b75..d7c571a4a 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -688,4 +688,5 @@ \nInstallera en filhanterare som är kompatibel med Storage Access Framework. Spelas redan i bakgrunden Fäst kommentar + LeakCanary är inte tillgänglig \ No newline at end of file diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml index 5c1e38214..c762d21d4 100644 --- a/app/src/main/res/values-ta/strings.xml +++ b/app/src/main/res/values-ta/strings.xml @@ -2,76 +2,76 @@ ஆரம்பிக்க பூதக்கண்ணாடியைத் தட்டு. %1$s அன்று வெளியிடப்பட்டது - நிகழ்பட ஓட்டி கண்டறியப்படவில்லை. VLC நிறுவவா\? + நிகழ்பட ஓட்டி இல்லை. VLCஐ நிறுவவா\? நிறுவு ரத்துசெய் உலாவியில் திற பகிர் பதிவிறக்கம் தேடு - அமைப்புகள் + அமைவு இதனுடன் பகிர் - நிகழ்பட ஓட்டி கண்டறியப்படவில்லை (தாங்கள் VLC-ஐ பயன்படுத்தலாம்). - திரைமேல் நிலையில் காட்டவும் - நிகழ்பட கோப்பை பதிவிறக்கு + நிகழ்பட ஓட்டி இல்லை (இதை இயக்க VLC-ஐப் பயன்படுத்தலாம்). + திரைமேல் நிலையில் காட்டு + நிகழ்பட கோப்பைப் பதிவிறக்கு \"%1$s\" என்றீர்களா\? - வேறு நிகழ்பட ஓட்டியை பயன்படுத்தவும் - வேறு ஒலி இயக்கியை பயன்படுத்தவும் - குழுசேர் - குழு சேர்க்கப்பட்டது - சேனல் குழுவிளகப்பட்டது - குழுசேர்தலை மாற்ற இயலவில்லை - குழுசேர்தலை புதுப்பிக்க இயலவில்லை + வேறு நிகழ்பட ஓட்டியைப் பயன்படுத்து + வேறு ஒலி இயக்கியைப் பயன்படுத்து + சந்தாசேர் + சந்தாசேர்ந்தாயிற்று + சேனல் சந்தாநீக்கப்பட்டது + சந்தாவை மாற்ற முடியவில்லை + சந்தாவைப் புதுப்பிக்க முடியவில்லை தகவல் காண்பி - குழுசேர்ப்புகள் - குறிக்கப்பட்ட காணொலி பட்டியல்கள் + சந்தாக்கள் + நூற்குறித்த ஒளிச்சரங்கள் புதிதாக - பின்னால் + பின்புலம் திரைமேல் - சேர் - காணொலி பதிவிறக்க கோப்புறை - பதிவிறக்கப்பட்ட காணொலிகள் இங்கு சேமிக்கப்படும் - காணொலியின் தரவிறக்கக் கோப்புறையை தேர்வு செய்க - ஒலி பதிவிறக்க கோப்புறை - தரவிறக்கப்பட்ட ஒலி கோப்புகள் இங்கே சேமிக்கப்பட்டுள்ளது - ஒலி கோப்புகளுக்கான பதிவிறக்கப் பாதையை தேர்வு செய்க - முதல் பிரிதிறன் - முதல் திரைமேல் நிலை பிரிதிறன் - மேம்பட்ட பிரிதிறன்களைக் காண்பி - Kodi கொண்டு இயக்கு - காணாத Kore செயலியை நிறுவவா\? - \"Kodi கொண்டு இயக்கு\" இடப்பை காண்பி + இதற்கு சேர் + காணொளி பதிவிறக்க அடைவு + பதிவிறங்கிய காணொளி கோப்புகள் இங்கே தேங்கும் + காணொளியின் பதிவிறக்க அடைவை தேர்வு செய் + ஒலி பதிவிறக்க அடைவு + பதிவிறங்கிய ஒலி கோப்புகள் இங்கே தேங்கும் + ஒலி கோப்புகளுக்கான பதிவிறக்கப் அடைவை தேர்வு செய் + இயல்பிருப்பு பிரிதிறன் + இயல்பிருப்பு திரைமேல் நிலை பிரிதிறன் + உயரிய பிரிதிறன்களைக் காட்டு + Kodiயுடன் இயக்கு + இல்லாத Kore செயலியை நிறுவவா\? + \"Kodiயுடன் இயக்கு\" இடப்பைக் காட்டு ஒலி - முதல் ஒலி வடிவம் - முதல் காணிலி வடிவம் - வார்ப்புரு - வெளிர் - அடர் - கருப்பு - திரைமேல் அளவையும் இடத்தையும் நினைவுகொள் + இயல்பிருப்பு ஒலி வடிவம் + இயல்பிருப்பு காணொளி வடிவம் + தோற்றம் + வெளிர்ந்த + இருண்ட + கருமை + திரைமேல் பண்புகளை நினைவுகொள் திரைமேல் நிலையின் கடைசி அளவையும் இடத்தையும் நினைவுகொள் சிறுபடத்தைக் இறக்கு பட பதுக்ககம் அழிக்கப்பட்டது மேல்நிலைத்தரவின் பதுக்ககம் அழிக்கப்பட்டது - பதுக்ககத்திலிருக்கும் வலைப்பக்கத் தரவு அழிக்கப்பட்டது + பதுக்ககப்படுத்திய வலைப்பக்கத் தரவை நீக்கு மேல்நிலைத் தரவு பதுக்ககம் அழிக்கப்பட்டது - ஆலோசனைகளை தேடு + பரிந்துரைகளைத் தேடு தேடல் வரலாறு பார்த்த வரலாறு - பார்த்த காணொலிகளை குறிப்பிடு + பார்த்த காணொளிகளை குறிப்பிடு பதிவிறக்கு இயக்கி பண்பு - ஒலி மற்றும் காணொலி - வரலாறு மற்றும் பதுக்ககம் + காணொளியும் ஒலியும் + வரலாறும் பதுக்ககமும் தோற்றம் பிண்ணணியில் ஓடுகிறது திரைமேல் நிலையில் ஓடுகிறது - நேரடி ஒளிபரப்பு + நேரலை பதிவிறக்கங்கள் பதிவிறக்கங்கள் அனைத்தும் - காணொலி பட்டியல்கள் + ஒளிச்சரங்கள் பயனர்கள் ஆம் அழி @@ -79,11 +79,11 @@ ஒரு முறை கோப்பு பார்த்த வரலாற்றை அழி - பார்த்த வரலாறு அழிக்கப்பட்டது. + பார்த்த வரலாறு அழிக்கப்பட்டது தேடல் வரலாற்றை அழி - தேடல் வரலாறு அழிக்கப்பட்டது. + தேடல் வரலாறு அழிக்கப்பட்டது கோப்பு பெயர் காலியாக இருக்க முடியாது - மன்னியுங்கள். சிறிய பிழை நிகழ்ந்தது. + மன்னிக்கவும், ஏதோ தவறாகிற்று. தகவல்: விவரங்கள்: விருப்பங்கள் @@ -93,46 +93,46 @@ காணொலி ஒலி மீண்டும் முயற்சி - சில பிரிதிறன்களில் ஒலி நீக்கப்படும் + சில பிரிதிறன்களில் ஒலியை நீக்கும் சில சாதனங்கள் மட்டுமே 2k/4k காணொளிகளை இயக்கமுடியும் - காணொளிகலை Kodi media center கொண்டு இயக்கும் இடப்பை காண்பி + காணொளிகளை Kodi media centerஉடன் இயக்கும் இடப்பைக் காட்டு வேகமான பொருத்தமற்ற தேடலை பயன்படுத்து - தேடும்போது காட்டுவதற்கான பரிந்துரைகளைத் தெரிவுசெய் + தேடும்போது காட்ட, பரிந்துரைகளைத் தெரிவுசெய் தொலைபேசி அழைப்பு போன்ற குறுக்கீடுகளுக்கு பிறகு தொடரவும் - \'அடுத்து\' மற்றும் \'ஒப்பான\' காணொளிகலை காண்பி - தேடப்பட்ட வாக்கியத்தை அமைவிடத்தில் சேமிக்கவும் - ஆதரிக்கப்படாத URL - இயல்புநிலை தகவல்களின் நாடு - பிழைதிருத்து + \'அடுத்து\' மற்றும் \'ஒப்பான\' காணொளிகளைக் காட்டு + தேடல் வாக்கியத்தை அமைவிடத்தில் தேக்கு + ஆதரிக்கப்படாத உரலி + உள்ளடக்க இயல்பிருப்பு நாடு + வழுநீக்கு உள்ளடக்கம் - வயது வரம்புக்கு உட்பட்டது - அடுத்த தாரையில் தானாக சேர் + வயது வரம்புக்குட்பட்ட உள்ளடக்கத்தைக் காட்டு + அடுத்த பாய்வில் தானாக-தாரைபடுத்து பிழை அறிக்கை சேனல்கள் செயலிழக்கச் செய்யப்பட்டுள்ளது முந்தய நிலைக்குச் செல் அனைத்தையும் இயக்கு - NewPipe அறிவிப்புகள் + NewPipe அறிவிப்பு [அறியப்படவில்லை] பின்னனிக்கு மாறு - \"சேர்ப்பதர்க்கு அழுத்தவும்\" அறிவிப்பை காண்பி + \"சாரைபடுத்த நீண்டழுத்து\" துணுக்குதவியைக் காட்டு தகவல்கலை இறக்குமதி செய் தகவல்கலை ஏற்றுமதி செய் - தற்போதைய வரலாறு, சந்தாக்கள், இயக்குபட்டியல்கள் மற்றும் (விரும்பினால்) அமைப்புகள் ஐ மீறும் - வரலாறு, சந்தாக்கள், இயக்குபட்டியல்கள் மற்றும் அமைப்புகளை ஏற்றுமதி செய் + தற்போதைய வரலாறு, சந்தாக்கள், ஒளிச்சரங்கள் மற்றும் (விரும்பினால்) அமைவை மீறும் + வரலாறு, சந்தாக்கள், ஒளிச்சரங்கள் மற்றும் அமைவை ஏற்றுமதி செய் பார்த்த வரலாறு முழுவதையும் அழி\? தேடப்பட்ட வார்த்தைகளின் வரலாற்றை அழி தேடல் வரலாறு முழுவதையும் அழி\? பிழை சிறந்த திரைத் தெளிவுத்திறன் - NewPipe பின்னனி மற்றும் பாப்அப் இயக்கிகளின் அறிவிப்புகள் + NewPipe இயக்கிக்கான அறிவிப்புகள் பாப்அப் இயக்கிக்கு மாறு - குழுவிலகு - வரிசை + சந்தாநீக்கு + சாரைபடுத்து நெட்வொர்க் பிழை செயலி நிறுத்தப்பட்டது மன்னிக்கவும். - மின்னஞ்சல் மூலம் பிழையை தெரிவிக்கவும் + மின்னஞ்சல் மூலம் இப்பிழையைப் புகாரளி என்ன நடந்தது: உங்கள் கருத்து: வெறுப்புகள் @@ -165,11 +165,11 @@ புதுப்பித்தல்கள் கோப்பு அழிக்கப்பட்டது செயலி புதுப்பித்தல் அறிவிப்பு - புதிய NewPipe பதிப்புக்கு அறிவிப்பு + புதிய NewPipe பதிப்புக்கான அறிவிப்புகள் வெளி சேமிப்பு இயலாது பின்தொடர்பவர்கள் எண்ணிக்கை இல்லை நிகழ்வுகள் - கருத்துக்களை காண்பி + கருத்துக்களைக் காண்பி கருத்துக்களை மறைக்க அணை தானாக ஓட்டு திரையிடலை தொடங்கு @@ -189,12 +189,12 @@ வரலாறு வரலாறு மேனிலை தகவல் காட்டு - வீடியோ விளக்கம் மற்றும் கூடுதல் தகவல்களை மறைக்க அணைக்கவும் + காணொளி விளக்கம் மற்றும் கூடுதல் தகவல்களை மறைக்க அணை விளக்கத்தைக் காட்டு செயலிலுள்ள இயக்கி வரிசை மாற்றப்படும் ஒரு இயக்கி விட்டு மறு இயக்கி மாறுதல் உங்கள் வரிசையை மாற்றக்கூடும் துல்லியமற்ற நாடல் குறைந்த துல்லியத்துடன் விரைவாக நாட இயக்கியை அனுமதிக்கிறது. 5, 15 அ 25 நொடிகள் நாடுவது இதனுடன் செயல்படாது - இருள் தோற்றம் + இரவு தோற்றம் சிறுபடத்திலுள்ள முதன்மை நிறத்திற்கேற்ப அறிவிப்பின் நிறத்தை Androidஐ தனிப்பயனாக்கச் செய் (இது எல்லா சாதனங்களிலும் கிடைக்காதென்பதை குறித்துக்கொள்) அறிவிப்பை வண்ணமயமாக்கு ஏதுமில்லை @@ -208,10 +208,10 @@ மூன்றாம் செயல் பொத்தான் இரண்டாம் செயல் பொத்தான் முதல் செயல் பொத்தான் - அறிவிப்பில் காட்டப்பட்டுள்ள காணொலி சிறுவுருவத்தை 16: 9 முதல் 1: 1 அம்ச விகிதம் வரை அளவிடு (சிதைவுகளை அறிமுகப்படுத்தலாம்) - சிறுவுருவத்தை 1: 1 அம்ச விகிதத்திற்கு அளவிடு + அறிவிப்பில் தெரியும் காணொளி சிறுபடத்தை 16: 9 முதல் 1: 1 அம்ச விகிதம் வரை அளவிடு (சிதைவுகளை அறிமுகப்படுத்தலாம்) + சிறுபடத்தை 1: 1 அம்ச விகிதத்திற்கு அளவிடு %s :க்கான முடிவுகளைக் காட்டுகிறது - இதன்மூலம் திற + இதனுடன் திற பற்றி நியூபைப் பற்றி நடப்பு @@ -219,12 +219,148 @@ குறைந்த தரம் மொபைல் தரவைப் பயன்படுத்தும் போது வீடியோ தரத்தைக் கட்டுப்படுத்துங்கள் வரம்பற்ற - கிடைக்கவில்லை - பார்த்ததாக குறிக்கவும் + உள்ளடக்கம் கிடைக்கவில்லை + பார்த்ததாகக் குறி சரி - அனைத்து சிறு படங்களையும் காட்ட முடியவில்லை - வலைத்தளத்தை பயன்படுத்த முடியவில்லை + எல்லா சிறுபடங்களையும் ஏற்ற முடியவில்லை + வலைத்தளத்தைப் பாகுபடுத்த முடியவில்லை தொலைதேடல் பரிந்துரைகள் - தானாக-சாரை + தானாக-தாரைபடுத்தல் கடைசியாக மீட்பொலித்த இருப்பிடத்தை மீட்டெடு + உள்ளூர் தேடல் பரிந்துரைகள் + பாய்வு உருவாக்குநர், பாய்வு உள்ளடக்கம் அ தேடல் கோரிக்கை குறித்த கூடுதல் தகவலையுடைய மேனிலைத் தகவட்பெட்டிகளை மறைக்க அணை + பியர்டியூப் நிகழ்வுகள் + புற SD அட்டைக்குப் பதிவிறக்குதல் சாத்தியமில்லை. பதிவிறக்க அடைவிடத்தை அகரமாக்கவா\? + reCAPTCHA நினைவிகளைத் துடை + இயல்பிருப்புகளை மீட்டெடுக்க வேண்டுமா\? + உறவுடைய உருப்படிகள் + reCAPTCHAஐ தீர்க்கையில் NewPipe சேமிக்கும் நினைவிகளைத் துடை + முதன்மை இயக்கியை முழுதிரையில் துவக்கு + நிகழ்வை செல்லுபடுயாக்க முடியவில்லை + எல்லா இயக்கக குறியிடங்களையும் அழிக்கும் + எல்லா இயக்கக குறியிடங்களையும் அழிக்கவா\? + இயக்கக குறியிடங்கள் அழிக்கப்பட்டன + விவரிப்பு + தொகுப்புகள் + உதவி + கலைஞர்கள் + காணொளிகள் + HTTPS உரலிகள் மட்டுமே ஆதரிக்கப்படுகின்றன + நிகழ்வு உரலியை உள்ளிடு + நிகழ்வைச் சேர் + உமக்குப் பிடித்த நிகழ்வை கண்டுபிடி இங்கு %s + உம் அபிமான பியர்டியூப் நிகழ்வுகளைத் தேர்ந்தெடு + உள்ளடக்க இயல்பிருப்பு மொழி + இயக்குதலைத் மறுதொடர் + நி + நிகழ்வு ஏற்கனவே உள்ளது + அறிவிப்பு + யூடியூபின் \"கட்டுப்பாடு பயன்முறை\"ஐ இயக்கு + பாடல்கள் + பிழைகளைப் புகாரளிக்க அறிவிப்புகள் + reCAPTCHA நினைவிகள் துடைக்கப்பட்டன + இயக்கிய பாய்வுகள் மற்றும் இயக்கக குறியிடங்களின் வரலாற்றை அழிக்கும் + இயக்கக குறியிடங்களை அழி + பதிவிறக்கச்சிறுபட்டியை அமைக்க முடியவில்லை + இயல்பிருப்புகளை மீட்டெடு + NewPipe பிழையைச் எதிர்கொண்டது, புகாரளிக்க தட்டு + புகாரளி + என்ன:\\nகோரிக்கை:\\nஉள்ளடக்க மொழி:\\nஉள்ளடக்க நாடு:\\nசெயலி மொழி:\\nசேவை:\\nGMT நேரம்:\\nசிப்பம்:\\nபதிப்பு:\\nOS பதிப்பு: + காணொளியை இயக்கு, காலவளவு: + கருத்தளிப்புகள் + + ப.ல + இயக்கியைச் சிதை + சிறுபடங்களேற்றுவதை தவிர்த்து தரவு மற்றும் நினைவகப் பயன்பாட்டைச் சேமிக்க அணை. மாற்றங்கள் நினைவகத்துள் மற்றும் வட்டின்மீதுள்ள பிடிதரவைத் துடைக்கும் + பட்டியல்களில் இயக்கக குறியட நிலைகாட்டிகளைக் காட்டு + துணையியக்கியில் காணொளிகளை துவக்காதே, ஆனால் தானாக சுழற்றல் பூட்டப்பட்டிருந்தால் நேரடியாக முழுதிரைக்குத் திரும்பு. முழுதிரையை வெளியேறி நீங்கள் இன்னும் துணையியக்கியை அணுகலாம் + உரலியை அங்கீகரக்க முடியவில்லை. மற்றொரு செயலியில் திறக்கவா\? + இக்காணொளி வயது வரம்புக்குட்டபட்டது. +\n +\nஇதைக் காண வேண்டுமெனில் அமைவில் \"%1$s\"ஐ இயக்கு. + பிழையறிக்கை அறிவிப்பு + இப்பாய்வினை இயக்க முடியவில்லை + மீட்கவியலாத இயக்கி பிழை ஏற்பட்டது + பிழை ஏற்பட்டது, அறிவிப்பைப் பார் + இயக்கி பிழையிலிருந்து மீளப்பெறுகிறது + கோப்பு இல்லை அ அதனை எழுதபடிக்கும் அனுமதி குறைகிறது + பதிவிறக்கா எப்பாய்வும் கிடைக்கவில்லை + சேமித்த தாவல்களை வாசிக்க முடியவில்லை, ஆக இயல்பிருப்புகளைப் பயன்படுத்துகிறது + GitHub இல் புகாரளி + இவ்வகை தொடுப்புகளைப் புற இயக்கிகள் ஆதரக்கா + வடிவமைக்கப்பட்ட அறிக்கையை நகலெடு + பிற செயலிகள் மீது காட்டும் அனுமதி கொடு + கோரிய உள்ளடக்கத்தை ஏற்றுகிறது + தானாக + உம் அபிமான இருண்ட தோற்றத்தைத் தேர்ந்தெடு — %s + மூடு + தகவலைப் பெறுகிறது… + + %1$s பதிவிறக்கம் அழிக்கபட்டது + %1$s பதிவிறக்கங்கள் அழிக்கபட்டன + + நகலகத்திற்கு நகலெடுக்கபட்டது + செயலியின் மொழி + பதிவிறக்க அடைவு இன்னும் அமைக்கப்படவில்லை, இப்போதைக்கு இயல்பிருப்பு பதிவிறக்க அடைவைத் தெரிவுசெய் + இப்பெயருடன் ஒரு பதிவிறக்கம் நிலுவையிலுள்ளது + பின்னர் பதிவிறக்க அடைவை அமைவில் வரையறுக்கவும் + பதிவிறக்கம் + பதிவிறக்க தட்டு + பதிவிறக்கத்தை ரத்துசெய்வதற்கு முன் செய்யவேண்டிய அதிகபட்ச முயற்சிகள் + + பதிவிறக்கம் முடிந்தது + %s பதிவிறக்கங்கள் முடிந்தன + + இப்பெயருடன் ஒரு பதிவிறக்கம் நடைபெறுகிறது + புதிய பதிப்பு கிடைத்தால் செயலி புதுப்பிப்பு பற்றி நினைப்பூட்ட ஓர் அறிவிப்பைக் காட்டு + பூட்டுத்திரைப் பின்புலத்திற்கும் அறிவிப்புகளுக்கும் சிறுபடத்தைப் பயன்படுத்து + முகப்புப்பக்க உள்ளடக்கம் + உம் அபிமான இருண்ட தோற்றத்தைக் கீழே தேர்ந்தெடுக்கலாம் + இப்பதிவிறக்கத்தை மீட்டெடுக்க முடியவில்லை + உருப்படிகளை அகற்ற அவற்றைத் தேய் + பிழை அறிவிப்பைப் படை + NewPipe புதுப்பிப்பு கிடைக்கிறது! + அருகலையில் மட்டும் + ஒருபோதுமில்லை + பட்டியல் பார்வை முறை + இப்பெயருடன் ஏற்கனவே ஒரு பதிவிறக்கிய கோப்பு உள்ளது + பதிவிறக்கிய கோப்புகளை அழி + இயங்குதள இயல்பிருப்பு + சிறுபடங்காட்டு + தானியங்கி (சாதன தோற்றம்) + அடுத்தைச் சாரைபடுத்து + அடுத்தது சாரைபடுத்தப்பட்டது + மறுபெயரிடு + பதிவுத்தட விவரங்களை ஏற்றுகிறது… + ஒளிச்சர நூற்குறிகள் இன்னுமில + நூற்குறியை நீக்கு + ஒளிச்சர சிறுபடமாக அமை + ஒளிச்சரம் படைக்கப்பட்டது + மாற்றீடு வரியுரு + ஒளிச்சரப் பக்கம் + ஒன்றிணைக்கா சந்தாக்களை மட்டும் காட்டு + பதிவுத்தட விவரங்களைக் காட்டுவதில் பிழை + அமைவையும் இறக்குமதி செய்யவா\? + பின்னணியில் இயங்கத் துவங்கு + + பதிவுத்தட விவரங்களைக் காட்டு + ஒளிச்சரத்தைத் தேர்ந்தெடு + ஒளிச்சரத்தில் சேர் + ஒளிச்சரத்தை நூற்குறி + ஒளிச்சரமிடப்பட்டது + தானாக-உண்டான (பதிவேற்றி எதுவுமில்லை) + சாரைபடுத்த நீண்டழுத்து + சாரைபடுத்து + எப்பதிவுத்தட சந்தாக்களுமில்லை + ஒலியமைவு + புதிய ஒளிச்சரம் + சந்தாக்களை இறக்குமதி செய்ய முடியவில்லை + ஒளிச்சர சிறுபடம் மாறியது. + கோப்புப்பெயர்களில் அனுமதிக்கப்பட்ட வரியுருக்கள் + இந்த ஒளிச்சரத்தை அழிக்கவா\? + சாரைபடுத்தப்பட்டது + சந்தாக்களை ஏற்றுமதி செய்ய முடியவில்லை + சந்தாக்களைத் தேர்ந்தெடு + செல்லா வரியுருக்கள் இம்மதிப்புடன் மாற்றீடுசெய்யப்படும் + நயமான \'திற\' செயல் \ 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 c96034a9c..22f0cb9d9 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -20,7 +20,7 @@ Ses indirme klasörü İndirilen ses dosyaları burada depolanır Ses dosyaları için indirme klasörünü seç - Öntanımlı çözünürlük + Varsayılan çözünürlük Kodi ile oynat Eksik Kore uygulaması yüklensin mi\? \"Kodi ile oynat\" seçeneğini göster @@ -283,7 +283,7 @@ \nSürdürmek istiyor musunuz\? Küçük resimleri yükle Küçük resimlerin yüklenmesini önleyerek veri ve hafıza kullanımından tasarruf etmek için kapatın. Değişiklikler, hem bellek içi hem de diskteki resim önbelleğini temizler - Resim önbelleği silindi + Resim önbelleği temizlendi Önbelleğe alınmış üstverileri temizle Önbelleğe alınmış tüm web sayfası verilerini kaldır Üstveri önbelleği temizlendi @@ -425,8 +425,8 @@ Öntanımlı Kiosk Kimse izlemiyor - %s izliyor - %s izliyor + %s izleyen + %s izleyen Kimse dinlemiyor @@ -688,4 +688,5 @@ Oynatıcıyı çöktür Zaten arka planda oynuyor Sabitlenmiş yorum + LeakCanary mevcut değil \ 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 9c8e57b81..6af7304d8 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -318,7 +318,7 @@ Видалити всю історію пошуку\? Історію пошуку видалено Видалено 1 елемент. - NewPipe є вільним копілефт застосунком: ви можете використовувати, поширювати та вдосконалювати його на власний розсуд. Зокрема, ви можете розповсюджувати та/або змінювати її за умов дотримання вимог GNU General Public License 3-ї версії або (на ваш вибір) будь-якої пізнішої версії, опублікованої Free Software Foundation. + NewPipe є вільним (копілефт) застосунком: ви можете використовувати, поширювати та вдосконалювати його на власний розсуд. Зокрема ви можете розповсюджувати та/або змінювати його за умов дотримання вимог GNU General Public License 3-ї версії або (на ваш вибір) будь-якої пізнішої версії, опублікованої Free Software Foundation. Імпортувати разом з налаштуваннями\? Політика приватності NewPipe Проєкт NewPipe дуже серйозно ставиться до вашої приватності. Тому застосунок не збирає ніяких даних без вашої згоди. @@ -688,7 +688,7 @@ Перевірка нових версій вручну Перевірка оновлень… Нові записи стрічки - Показати «збій програвача» + Показати «Збій програвача» Показує параметр збою під час використання програвача Збій програвача Сповіщення про звіт про помилку @@ -703,4 +703,5 @@ Створити сповіщення про помилку Уже відтворюється у фоновому режимі Закріплений коментар + LeakCanary недоступний \ No newline at end of file diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 306cd17e2..d584ae3fe 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -2,61 +2,61 @@ 安裝 取消 - 於 %1$s 發佈 + 喺 %1$s 發佈 分享 下載 搜尋 設定 - 你是不是在寻找:%1$s? - 使用外置影片播放器 - 使用外置聲音播放器 + 您係咪想搵「%1$s」? + 用外面嘅影片播放器 + 用外面嘅音樂播放器 影片下載路徑 - 已下載的影片將保存在此處 - 選擇視頻的下載文件夾 + 下載咗嘅影片檔案會收埋喺度 + 揀選影片檔案嘅下載資料夾 預設解像度 - 使用 Kodi 播放 - 您要安裝遺失的 Kore 程式嗎? - 顯示「使用 Kodi 播放」的選項 - 顯示以 Kodi 媒體中心播放影片的選項 + 用 Kodi 嚟播放 + 要唔要裝缺少嘅 Kore app? + 顯示「用 Kodi 嚟播放」嘅選項 + 顯示以 Kodi 媒體中心播放影片嘅選項 聲音 預設聲音檔案格式 主題 黑暗 明亮 下載 - 顯示下一部及相關的影片 - 不支援此網址 - 預設內容語言 - 影片及聲音 + 顯示「接續落」同「咁上下」嘅影片 + 唔支援呢個網址 + 內容預設語言 + 影音 外觀 背景播放 網絡問題 - 影片預覽縮圖 - 上載者的個人頭像縮圖 + 播放影片,片長: + 上載者嘅頭像縮圖 讚好 討厭 - 找不到任何串流播放器,要安裝 VLC 嗎? - 使用瀏覽器開啟 + 搵唔到串流播放器。要唔要裝 VLC? + 喺瀏覽器開啟 分享影片 - 聲音下載路徑 - 已下載的聲音將保存在此處 - 選擇聲音檔案的下載路徑 - 點擊 \"搜索\" 以開始使用 + 音樂下載資料夾 + 下載咗嘅音樂檔案會收埋喺度 + 揀選音樂檔案嘅下載資料夾 + 撳放大鏡開始。 內容 - 顯示已設年齡限制的影片 + 顯示年齡設限嘅內容 直播 問題 - 無法載入全部縮圖 - 無法為影片地址的簽署解碼。 - 無法讀取網站。 - 無法設定下載清單 - 抱歉,這是不應該發生的。 - 透過電郵彙報問題 - 抱歉,程式出現了問題。 + 載入唔晒全部縮圖 + 影片 URL 簽章解唔到碼 + 解析唔到網站 + 設定唔到下載功能表 + 啫係嗱,世事講唔埋嘅,真係唔好意思。 + 以電郵報告今次問題 + 出咗啲問題,唔好意思。 報告 - 資料: + 資訊: 事發經過: - 您的意見(請以英文輸入): + 您嘅意見 (請以英文輸入): 詳情: 影片 聲音 @@ -64,72 +64,72 @@ 下載 下載 問題報告 - 未能提供內容。 + 內容未能提供 開始 暫停 刪除 - 校驗和 + 校驗碼 檔案名稱 線程 錯誤 - NewPipe 正在下載 - 按一下以查看詳情 - 請稍候… - 已複製至剪貼板 - 請選擇下載資料夾。 + NewPipe 下載緊 + 撳一下睇詳情 + 請等等… + 複製咗去剪貼簿 + 請之後喺設定度揀定一個下載資料夾 在畫中畫模式開啟 預設畫中畫解像度 顯示更高解像度 - 只有某些裝置能夠播放 2K 或 4K 影片 + 得某啲機至播到 2K/4K 影片 預設影片檔案格式 純黑 以畫中畫模式播放 所有 - 應用程式或介面出現問題 - 事件:\\n請求:\\n內容語言:\\n服務:\\nGMT 時間:\\nPackage:\\n版本:\\n作業系統版本: - K - M + App/界面閃退 + 經過:\\n請求:\\n內容語言:\\n內容國家:\\nApp 語言:\\n服務:\\nGMT 時間:\\n封裝:\\n版本:\\nOS 版本: + + 百萬 reCAPTCHA 挑戰 畫中畫模式需要此權限 需完成 reCAPTCHA 挑戰 - 移除某些解像度的影片的聲音 + 某啲解像度可能會冇聲 背景播放 畫中畫播放 記住畫中畫大小及位置 記住最近設定的畫中畫大小及位置 搜尋建議 - 進行搜尋時顯示建議 + 揀選搜尋嘅時候顯示邊啲建議 不適用 清除 最佳解像度 - B + 十億 關於 NewPipe 第三方版權特許 © %1$s %2$s,根據 %3$s 特許版權所有 關於 特許 - 在 Android 上運作自由輕便的 Youtube 前端。 + 喺 Android 上盡享自由輕便串流。 檢視我們的 GitHub NewPipe 嘅授權協議 無論您僅想分享您對 NewPipe 的一些構思,還是願意設計和翻譯程式介面,甚至想幫我們整理或重新編寫原始碼,我們都無任歡迎。貢獻更多,應用程式便會變得更好! 檢閱特許 貢獻 - 清除觀看歷史 - 找不到串流播放器 (您可以安裝並使用VLC播放)。 + 抹走睇過嘅紀錄 + 搵唔到串流播放器 (您可以裝 VLC 嚟播)。 下載串流檔案 訂閱 - 已訂閱 + 訂閱咗 取消訂閱 已成功取消訂閱頻道 - 無法變更訂閱 - 無法更新訂閱 + 轉唔到訂閱 + 更新唔到訂閱 顯示資訊 訂閱項目 已收藏播放清單 - 使用粗略快查 - 添加到 + 用粗略快轉 + 加入去 選擇標籤 第一粒動作掣 第二粒動作掣 @@ -155,7 +155,7 @@ 關閉去隱藏影片描述同附加資訊 剔低睇過 開啟方式 - 搵呢挺嘢:%s + 搵緊呢挺嘢:%s 第五粒動作掣 撳一下下面每粒掣去更改各個通知動作。用右手邊嘅格仔剔選最多三個,擺喺精簡通知度顯示 精簡通知最多淨係擺到三個動作! @@ -188,7 +188,7 @@ 檔案 NewPipe 通知 App 更新通知 - NewPipe 新版本通知 + NewPipe 有新版本嘅通知 抹走 reCAPTCHA Cookie 頻道 影片 @@ -224,7 +224,7 @@ 畀權限去喺其他 app 上面顯示 去 GitHub 度報告 留言 - 相關嘅嘢 + 咁上下嘅嘢 描述 播放唔到呢個串流 發生無法復原嘅播放器錯誤 @@ -323,7 +323,7 @@ ∞ 部影片 未開放留言 建立 - 未設定下載資料夾,請立即揀選預設嘅下載資料 + 未設定下載資料夾,請立即揀選預設嘅下載資料夾 刪除咗 1 個項目。 執執佢 未裝 app 嚟播放呢個檔案 @@ -398,4 +398,28 @@ 執好就撳一下「搞掂」 靜音 處理緊… 可能要等等 + 使播放器崩潰 + 自動輪候 + 係咪要全部剷走晒睇過嘅紀錄? + 顯示元資訊 + 關閉去隱藏元資訊窗口,收起有關串流創作者、串流內容或者搜尋請求嘅額外資訊 + 顯示「撳住就輪候」提示 + 揀選啱您心水嘅 PeerTube 站 + 紀錄與快取 + NewPipe 播放器嘅通知 + 抹除元資料快取 + 抹除咗元資料快取 + 自動輪候接續落串流 + 排隊播要完 (又未設定循環播放) 嘅時候就追加一條啱上下嘅串流 + PeerTube 站 + 去 %s 發掘啱您心水嘅站 + 播放清單 + 問題報告通知 + 報告問題嘅通知 + 剷走播放過嘅串流同播放到邊個位嘅紀錄 + 剷走咗睇過嘅紀錄 + NewPipe 遇到問題,撳一下去報告 + 發生問題,詳見通知 + 拖拉執排位 + 轉換服務,而家揀選咗嘅係: \ No newline at end of file diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 2696962de..bc1f40873 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -676,4 +676,5 @@ 發生錯誤,請檢視通知 釘選留言 已經在背景播放 + LeakCanary 無法使用 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 64ed6980b..54551be14 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -353,7 +353,7 @@ The NewPipe project takes your privacy very seriously. Therefore, the app does not collect any data without your consent.\nNewPipe\'s privacy policy explains in detail what data is sent and stored when you send a crash report. Read privacy policy NewPipe\'s License - NewPipe is copyleft libre software: You can use, study share and improve it at will. Specifically you can redistribute and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + NewPipe is copyleft libre software: You can use, study, share, and improve it at will. Specifically you can redistribute and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Read license History @@ -452,7 +452,7 @@ Disable media tunneling if you experience a black screen or stuttering on video playback Show image indicators Show Picasso colored ribbons on top of images indicating their source: red for network, blue for disk and green for memory - Show \"crash the player\" + Show \"Crash the player\" Shows a crash option when using the player Crash the app Show an error snackbar diff --git a/fastlane/metadata/android/fr/changelogs/981.txt b/fastlane/metadata/android/fr/changelogs/981.txt new file mode 100644 index 000000000..e3c301ce8 --- /dev/null +++ b/fastlane/metadata/android/fr/changelogs/981.txt @@ -0,0 +1,2 @@ +Suppression du support de MediaParser pour corriger les échec des lectures après le transfère en mémoire tampon sur Android 11+. +Désactivation de la tunnelisation de media sur les Philips QM16XE pour corriger les problèmes de lectures. diff --git a/fastlane/metadata/android/he/changelogs/982.txt b/fastlane/metadata/android/he/changelogs/982.txt new file mode 100644 index 000000000..8123c9da3 --- /dev/null +++ b/fastlane/metadata/android/he/changelogs/982.txt @@ -0,0 +1 @@ +תוקנה התקלה ש־YouTube לא מנגן אף תזרים. diff --git a/fastlane/metadata/android/he/changelogs/983.txt b/fastlane/metadata/android/he/changelogs/983.txt new file mode 100644 index 000000000..7c9645995 --- /dev/null +++ b/fastlane/metadata/android/he/changelogs/983.txt @@ -0,0 +1,9 @@ +הוספת מנשק משתמש והתנהגות חדשים לנגיעה כפולה לקפיצות +אפשר מעתה לחפש בהגדרות +הדגשת הערות נעוצות +הוספת תמיכה בפתיחה עם יישומון לעותק ה־PeerTube של FSFE +נוספו התראות שגיאה +תוקן ניגון מחדש של הפריט הראשון בתור במהלך תזרימים חיים בטרם כשל בתהליך +ההמתנה לאגירה במהלך תזרימים חיים התארכה עד להחלטה על כשל +תוקן סדר תוצאות החיפוש המקומיות +תוקנו שדות פריט ריקים בתור הנגינה diff --git a/fastlane/metadata/android/ms/changelogs/63.txt b/fastlane/metadata/android/ms/changelogs/63.txt new file mode 100644 index 000000000..3627f442a --- /dev/null +++ b/fastlane/metadata/android/ms/changelogs/63.txt @@ -0,0 +1,8 @@ +###Penambahbaikan +- Pengaturan Import/Eksport #1333 +- Mengurangi Pengambaran berlebih (peningkatan prestasi) #1371 +- Penambahbaikan kecil kepada kod #1375 +- Penambahan semua tentang GDPR #1420 + +###Diperbaiki +- Pemuat turun: pembaikian kepada kegagalan ketika memuat muat turun yang belum selesai daripada fail-fail format .giga #1407 diff --git a/fastlane/metadata/android/ms/changelogs/64.txt b/fastlane/metadata/android/ms/changelogs/64.txt new file mode 100644 index 000000000..111d0ecd8 --- /dev/null +++ b/fastlane/metadata/android/ms/changelogs/64.txt @@ -0,0 +1,8 @@ +### Penambahbaikan +- Menambah kemampuan untuk membataskan kualiti video jika menggunakan data mudah alih. #1339 +- Ingat kecerahan untuk sesi yang sedang dipakai #1442 +- Peningkatan prestasi muat turun untuk CPU yang lemah #1431 +- Penambahan sokongan (hidup) untuk sesi media #1433 + +###Diperbaiki +- Pembaikian kepada lagaan ketika memulakan muat turun (Pembaikian sekarang tersedia untuk rilis binaan) #1441 diff --git a/fastlane/metadata/android/ms/full_description.txt b/fastlane/metadata/android/ms/full_description.txt new file mode 100644 index 000000000..59fd024c4 --- /dev/null +++ b/fastlane/metadata/android/ms/full_description.txt @@ -0,0 +1 @@ +NewPipe tidak menggunakan pustaka kerangka kerja Google sama sekali, atau layanan API Youtube. NewPipe cuma menghuraikan laman YouTube untuk mendapatkan maklumat yang diperlukan. Oleh itu, NewPipe boleh digunakan pada peranti tanpa Google Services. Anda juga tidak perlu memiliki akaun YouTube untuk menggunakan NewPipe, dan aplikasi ini adalah sepenuhnya FLOSS. diff --git a/fastlane/metadata/android/ms/short_description.txt b/fastlane/metadata/android/ms/short_description.txt new file mode 100644 index 000000000..0d19c025e --- /dev/null +++ b/fastlane/metadata/android/ms/short_description.txt @@ -0,0 +1 @@ +Sebuah klien YouTube percuma dan ringan untuk Android. diff --git a/fastlane/metadata/android/nl/changelogs/63.txt b/fastlane/metadata/android/nl/changelogs/63.txt new file mode 100644 index 000000000..3a8c7df1f --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/63.txt @@ -0,0 +1,8 @@ +### Verbeteringen +- Instellingen importeren/exporteren #1333 +- Overdraw verminderen (prestatieverbetering) #1371 +- Kleine code verbeteringen #1375 +- Alles toevoegen over GDPR #1420 + +### Opgelost +- Downloader: Crash bij laden van onafgemaakte downloads van .giga bestanden verhelpen #1407 diff --git a/fastlane/metadata/android/nl/changelogs/64.txt b/fastlane/metadata/android/nl/changelogs/64.txt new file mode 100644 index 000000000..610aba45a --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/64.txt @@ -0,0 +1,8 @@ +### Verbeteringen +- Mogelijkheid toegevoegd om de videokwaliteit te beperken bij gebruik van mobiele data. #1339 +- Helderheid voor de sessie onthouden #1442 +- Downloadprestaties voor zwakkere CPU's verbeterd #1431 +- (werkende) ondersteuning voor mediasessie toegevoegd #1433 + +### Opgelost +- Crash bij openen downloads verhelpen (fix nu beschikbaar voor release builds) #1441 diff --git a/fastlane/metadata/android/nl/changelogs/770.txt b/fastlane/metadata/android/nl/changelogs/770.txt new file mode 100644 index 000000000..0dd3080aa --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/770.txt @@ -0,0 +1,4 @@ +Veranderingen in 0.17.2 + +Opgelost +• Er was geen video beschikbaar diff --git a/fastlane/metadata/android/nl/changelogs/820.txt b/fastlane/metadata/android/nl/changelogs/820.txt new file mode 100644 index 000000000..8654a44c8 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/820.txt @@ -0,0 +1 @@ +Regex voor decrypt-functienaam hersteld, waardoor YouTube onbruikbaar werd. diff --git a/fastlane/metadata/android/nl/changelogs/830.txt b/fastlane/metadata/android/nl/changelogs/830.txt new file mode 100644 index 000000000..7ae654679 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/830.txt @@ -0,0 +1 @@ +SoundCloud client_id bijgewerkt om SoundCloud problemen op te lossen. diff --git a/fastlane/metadata/android/nl/changelogs/850.txt b/fastlane/metadata/android/nl/changelogs/850.txt new file mode 100644 index 000000000..4586c3c99 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/850.txt @@ -0,0 +1 @@ +In deze release is de versie van de YouTube-website bijgewerkt. De oude websiteversie wordt in maart stopgezet en daarom moet u NewPipe upgraden. diff --git a/fastlane/metadata/android/nl/changelogs/860.txt b/fastlane/metadata/android/nl/changelogs/860.txt new file mode 100644 index 000000000..8e7b52d72 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/860.txt @@ -0,0 +1,7 @@ +Verbeterd +- Bewaren en terugzetten of tempo en toonhoogte zijn ontgrendeld of niet +- Ondersteuning display-uitsparing in speler +- Afronden van aantal keer bekeken en aantal abonnees +- Optimalisatie van YouTube om minder data te gebruiken + +Meer dan 15 YouTube gerelateerde bugs zijn opgelost in deze versie. diff --git a/fastlane/metadata/android/nl/changelogs/870.txt b/fastlane/metadata/android/nl/changelogs/870.txt new file mode 100644 index 000000000..e3c317b36 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/870.txt @@ -0,0 +1,2 @@ +Dit is een hotfix-release die NewPipe bijwerkt om SoundCloud weer zonder veel gedoe te kunnen gebruiken. +De v2 API van SoundCloud wordt nu in de extractor gebruikt en de detectie van ongeldige client-ID's is verbeterd. diff --git a/fastlane/metadata/android/nl/changelogs/900.txt b/fastlane/metadata/android/nl/changelogs/900.txt new file mode 100644 index 000000000..46e79a624 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/900.txt @@ -0,0 +1,14 @@ +Nieuw +• Abonnementsgroepen en gesorteerde feeds +• Mute-knop in spelers + +Verbeterd +• Sta het openen van music.youtube.com en media.ccc.de links toe in NewPipe +• Verplaats twee instellingen van Uiterlijk naar Inhoud +• Verberg zoekopties van 5, 15, 25 seconden als onnauwkeurig zoeken is ingeschakeld + +Gemaakt +• sommige WebM-video's kunnen niet worden gezocht +• Databaseback-up op Android P +• Crasht bij het delen van een gedownload bestand +• Tonnen YouTube-extractieprobleem en meer ... diff --git a/fastlane/metadata/android/nl/changelogs/910.txt b/fastlane/metadata/android/nl/changelogs/910.txt new file mode 100644 index 000000000..5ce1177dd --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/910.txt @@ -0,0 +1 @@ +Opgelost: Database migratie verholpen waardoor NewPipe in sommige zeldzame gevallen niet kon starten. diff --git a/fastlane/metadata/android/nl/changelogs/920.txt b/fastlane/metadata/android/nl/changelogs/920.txt new file mode 100644 index 000000000..46bae2f6a --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/920.txt @@ -0,0 +1,9 @@ +Verbeterd + +• Uploaddatum en weergave telling toegevoegd voor items in het stroomraster +• Verbeteringen voor de lay-out van de koppen + +Opgelost + +• Vaste demp-knop veroorzaakt crashes op API 19 +• Probleem opgelost met het downloaden van lange 1080p 60fps-video's diff --git a/fastlane/metadata/android/nl/changelogs/950.txt b/fastlane/metadata/android/nl/changelogs/950.txt new file mode 100644 index 000000000..e0c42cf26 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/950.txt @@ -0,0 +1,4 @@ +Deze release bevat drie kleine oplossingen: +• Opslagtoegang op Android 10+ +• Kiosken openen +• Analyseren van lange video's met een vaste duur diff --git a/fastlane/metadata/android/nl/changelogs/952.txt b/fastlane/metadata/android/nl/changelogs/952.txt new file mode 100644 index 000000000..3ff60109a --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/952.txt @@ -0,0 +1,7 @@ +Verbeterd +• Automatisch afspelen is beschikbaar voor alle services (in plaats van alleen voor YouTube) + +Aangepast +• Vaste gerelateerde streams door de nieuwe voortzettingen van YouTube te ondersteunen +• YouTube-video's met leeftijdsbeperking +• [Android TV] Opgeloste overlay met focusaccenten diff --git a/fastlane/metadata/android/nl/changelogs/953.txt b/fastlane/metadata/android/nl/changelogs/953.txt new file mode 100644 index 000000000..ca4000ebd --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/953.txt @@ -0,0 +1 @@ +Hersteld: extractie van de decoderingsfunctie van YouTube. diff --git a/fastlane/metadata/android/nl/changelogs/954.txt b/fastlane/metadata/android/nl/changelogs/954.txt deleted file mode 100644 index bded0c210..000000000 --- a/fastlane/metadata/android/nl/changelogs/954.txt +++ /dev/null @@ -1,6 +0,0 @@ -• Nieuwe app-workflow: speel video's af op de detailpagina, veeg omlaag om de speler te minimaliseren -• MediaStyle-meldingen: aanpasbare acties in meldingen, prestatieverbeteringen -• Basisformaat wijzigen bij gebruik van NewPipe als desktop-app -• Toon dialoog met open opties in het geval van een niet-ondersteunde URL-toast -• Verbeter de ervaring met zoeksuggesties wanneer externe suggesties niet kunnen worden opgehaald -• Standaard videokwaliteit verhoogd naar 720p60 (in-app-speler) en 480p (pop- diff --git a/fastlane/metadata/android/nl/changelogs/957.txt b/fastlane/metadata/android/nl/changelogs/957.txt index ce334f310..a15317d4c 100644 --- a/fastlane/metadata/android/nl/changelogs/957.txt +++ b/fastlane/metadata/android/nl/changelogs/957.txt @@ -1,10 +1,10 @@ • Voeg specifieke wachtrij-acties samen -• 2-vinger-beweging om de speler te sluiten -• Wis reCAPTHA-cookies +• 2-vinger-swipe sluit speler +• Sta wissen van reCAPTCHA cookie toe • Optie om meldingen niet te kleuren -• Verbeter hoe video-details worden geopend om oneindig bufferen, instabiel gedrag bij het delen met NewPipe en andere onvolkomenheden op te lossen -• Versnel YouTube-videos en repareer die met leeftijdsbeperkingen -• Los crash bij versnellen/terugspoelen op -• Herschik lijsten niet bij het slepen van thumbnails -• Onthoud popup-eigenschappen nooit -• Santali +• Verbeter openen van video-details om oneindig bufferen, instabiel gedrag bij het delen met NewPipe en andere fouten op te lossen +• Maak YouTube-video's sneller en herstel video's met leeftijdsbeperking +• Los crash bij snel vooruit/terugspoelen op +• Herschik lijsten niet bij het slepen van miniaturen +• Onthoud popup-eigenschappen altijd +• Santali-taal diff --git a/fastlane/metadata/android/nl/changelogs/958.txt b/fastlane/metadata/android/nl/changelogs/958.txt new file mode 100644 index 000000000..e8b06f2d1 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/958.txt @@ -0,0 +1,15 @@ +Verbeteringen: +• Opnieuw toegevoegd, functie om miniatuur te verbergen op vergrendelscherm +• Veeg naar beneden om feed te verversen +• Verbeterd ophalen van lokale lijsten + +Gemaakt: +• Crash bij start van NewPipe nadat verwijdering uit RAM geheugen +• Crash bij start van NewPipe zonder internetverbinding +• Helderheid- en volume-instellingen worden beter gerespecteerd +• [YouTube] Lange speellijst hersteld + +Overig: +• Code opgeruimd +• Afhankelijkheid updates +• Update vertalingen diff --git a/fastlane/metadata/android/nl/changelogs/961.txt b/fastlane/metadata/android/nl/changelogs/961.txt new file mode 100644 index 000000000..d5598e739 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/961.txt @@ -0,0 +1,12 @@ +• [YouTube] Mix ondersteuning +• [YouTube] Weergave info over publieke omroepen en Covid-19 +• [media.ccc.de] Recente videos toegevoegd +• Somalische vertaling toegevoegd + +• Veel interne verbeteringen + +• Het delen van videos van binnen de speler opgelost +• Lege ReCaptcha webview opgelost +• Crash opgelost die voorkwam wanneer een stream was verwijderd van een lijst +• [PeerTube] Gerelateerde streams opgelost +• [YouTube] Opgelost: YouTube Muziek zoeken diff --git a/fastlane/metadata/android/nl/changelogs/962.txt b/fastlane/metadata/android/nl/changelogs/962.txt new file mode 100644 index 000000000..1d277329f --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/962.txt @@ -0,0 +1,2 @@ +"Recente" video's toegevoegd aan de service media.ccc.de. +Livestreams toegevoegd aan de service media.ccc.de en ook ondersteuning voor livestreams. diff --git a/fastlane/metadata/android/nl/changelogs/963.txt b/fastlane/metadata/android/nl/changelogs/963.txt new file mode 100644 index 000000000..049791212 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/963.txt @@ -0,0 +1 @@ +• [YouTube] Verbetering van vaste kanalen diff --git a/fastlane/metadata/android/nl/changelogs/964.txt b/fastlane/metadata/android/nl/changelogs/964.txt new file mode 100644 index 000000000..853ecdf8c --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/964.txt @@ -0,0 +1,8 @@ +- Hoofdstukken in spelerbediening worden ondersteund +- [PeerTube] Sepia zoeken toegevoegd +- Delen is terug in video detailweergave. Stream beschrijving verplaatst naar de tab lay-out +- Als helderheid-gebaar is uitgeschakeld, kan helderheid herstel ook uit +- Lijst-item 'Afspelen op Kodi' +- Opgelost : Crash als geen standaardbrowser is ingesteld op sommige toestellen. Dialogen voor delen verbeterd +- 'Afspelen/Pauze' met spatie-knop in fullscreen speler +- [media.ccc.de] Reparaties en verbeteringen diff --git a/fastlane/metadata/android/nl/changelogs/965.txt b/fastlane/metadata/android/nl/changelogs/965.txt new file mode 100644 index 000000000..141520552 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/965.txt @@ -0,0 +1,6 @@ +Crash verholpen die optrad bij het opnieuw ordenen van kanaalgroepen. +Probleem opgelost met het ophalen van meer YouTube-video's van kanalen en afspeellijsten. +Probleem opgelost met het krijgen van YouTube-opmerkingen. +Ondersteuning toegevoegd voor / watch /, / v / en / w / subpaden in YouTube-URL's. +Vaste extractie van SoundCloud-client-ID en geografisch beperkte inhoud. +Noord-Koerdische lokalisatie toegevoegd. diff --git a/fastlane/metadata/android/nl/changelogs/966.txt b/fastlane/metadata/android/nl/changelogs/966.txt new file mode 100644 index 000000000..0347eba15 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/966.txt @@ -0,0 +1,14 @@ +Nieuw: +- Nieuwe dienst toegevoegd: Bandcamp + +Verbeterd: +- Optie toegevoegd om de app het thema van het toestel te laten volgen +- Voorkom sommige crashes door een verbeterd foutpaneel te tonen +- Toon meer informatie over waarom inhoud niet beschikbaar is +- Hardware spatie knop activeert afspelen/pauzeren +- Toon "Download gestart" toast + +Opgelost: +- Zeer kleine miniatuur in video details bij afspelen op de achtergrond +- Lege titel in geminimaliseerde speler +- Laatste resize modus is niet correct diff --git a/fastlane/metadata/android/nl/changelogs/967.txt b/fastlane/metadata/android/nl/changelogs/967.txt new file mode 100644 index 000000000..cff771734 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/967.txt @@ -0,0 +1 @@ +Probleem opgelost dat YouTube niet goed werkte in de EU. Dit werd veroorzaakt door een nieuw cookie- en privacy-toestemmingssysteem waarvoor NewPipe een TOESTEMMINGS- cookie moet plaatsen. diff --git a/fastlane/metadata/android/nl/changelogs/968.txt b/fastlane/metadata/android/nl/changelogs/968.txt new file mode 100644 index 000000000..1078ea9f2 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/968.txt @@ -0,0 +1,7 @@ +Optie voor kanaaldetails toegevoegd aan menu lang indrukken. +Functionaliteit toegevoegd om de naam van de afspeellijst te hernoemen vanuit de afspeellijstinterface. +Laat de gebruiker pauzeren terwijl een video wordt gebufferd. +Het witte thema geoptimaliseerd. +Overlappende lettertypen opgelost bij gebruik van een grotere lettergrootte. +Opgelost: geen video op Formuler- en Zephier-apparaten. +Verschillende crashes opgelost. diff --git a/fastlane/metadata/android/nl/changelogs/973.txt b/fastlane/metadata/android/nl/changelogs/973.txt new file mode 100644 index 000000000..da52defab --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/973.txt @@ -0,0 +1,4 @@ +Hotfix +• Miniaturen en titels herstellen, die worden bijgesneden in rasterlay-out, vanwege een verkeerde berekening van hoeveel video's in één rij passen +• Herstel downloaddialoog verdwijnt zonder iets te doen indien geopend vanuit het deelmenu +• Een bibliotheek bijwerken die verband houdt met het openen van externe activiteiten, zoals de bestandskiezer voor Storage Access Framework diff --git a/fastlane/metadata/android/nl/changelogs/974.txt b/fastlane/metadata/android/nl/changelogs/974.txt new file mode 100644 index 000000000..0232655b2 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/974.txt @@ -0,0 +1,5 @@ +Hotfix +• Bufferproblemen veroorzaakt door YouTube-beperking oplossen +• Extractie van YouTube-opmerkingen en crashes met uitgeschakelde reacties oplossen +• YouTube-muziekzoekopdracht repareren +• PeerTube-livestreams repareren diff --git a/fastlane/metadata/android/nl/changelogs/975.txt b/fastlane/metadata/android/nl/changelogs/975.txt new file mode 100644 index 000000000..5055d3e43 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/975.txt @@ -0,0 +1,17 @@ +Nieuw +- Toon een thumbnail preview tijdens zoeken +- Detecteer uitgeschakeld commentaar +- Markeer een feed-item als bekeken +- Reactie-harten tonen + +Verbeterd +- Verbeter metadata en tags lay-out +- Pas servicekleuren toe op UI-onderdelen + +Opgelost +- Miniatuur in mini player +- Eindeloze buffering bij dubbele wachtrij-items +- Enkele spelerfouten als rotatie en sneller sluiten +- ReCAPTCHA die op de achtergrond geladen blijft +- Klikken uitschakelen tijdens verversen van feed +- Enkele downloader crashes diff --git a/fastlane/metadata/android/nl/changelogs/976.txt b/fastlane/metadata/android/nl/changelogs/976.txt new file mode 100644 index 000000000..03676c828 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/976.txt @@ -0,0 +1,10 @@ +- Optie: speler direct in volledig scherm openen +- Optie: keuze welke zoeksuggesties laten zien +- Donker thema nu donkerder + donker splash-scherm +- Verbeterde bestandskiezer: ongewenst wordt grijs +- Import YouTube-abonnementen opgelost +- Om een stream opnieuw te bekijken, nu opnieuw op de knop replay tikken +- Geluidssessie sluiten vastgezet +- [Android TV] Lange zoekbalksprongen verholpen bij gebruik DPad + +Om meer wijzigingen te zien, bekijk de changelog (en blog post) op de Links tab hieronder. diff --git a/fastlane/metadata/android/nl/changelogs/977.txt b/fastlane/metadata/android/nl/changelogs/977.txt new file mode 100644 index 000000000..9b854ecad --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/977.txt @@ -0,0 +1,10 @@ +- Toegevoegd: "volgende afspelen" knop aan lang-drukken menu +- Padvoorvoegsel voor YouTube-shorts toegevoegd aan intentiefilter +- Hersteld: import instellingen +- Verwissel zoekbalk positie met speler knoppen in wachtrij scherm +- Diverse fixes MediasessionManager +- Hersteld: zoekbalk niet voltooid na einde video +- Media tunneling uitgeschakeld op RealtekATV +- Vergroot aanklikbaar gebied spelersknoppen bij geminimaliseerde speler + +Voor meer wijzigingen: changelog (en blog post) links-tab hieronder diff --git a/fastlane/metadata/android/nl/changelogs/978.txt b/fastlane/metadata/android/nl/changelogs/978.txt new file mode 100644 index 000000000..8943365c6 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/978.txt @@ -0,0 +1 @@ +Het uitvoeren van de controle op een nieuwe NewPipe versie is verbeterd. Deze controle werd soms te vroeg uitgevoerd en leidde daardoor tot een crash van de app. Dat zou nu verholpen moeten zijn. diff --git a/fastlane/metadata/android/nl/changelogs/979.txt b/fastlane/metadata/android/nl/changelogs/979.txt new file mode 100644 index 000000000..a22c6e329 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/979.txt @@ -0,0 +1,2 @@ +- Hervatten van afspelen opgelost +- Verbeteringen om ervoor te zorgen dat de service die bepaalt of NewPipe moet controleren op nieuwe versiecontroles niet op de achtergrond wordt gestart diff --git a/fastlane/metadata/android/nl/changelogs/980.txt b/fastlane/metadata/android/nl/changelogs/980.txt new file mode 100644 index 000000000..17b7003c1 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/980.txt @@ -0,0 +1,13 @@ +Nieuw +• Optie "Toevoegen aan afspeellijst" toegevoegd aan menu delen +• Ondersteuning toegevoegd voor y2u.be en PeerTube verkorte links + +Verbeterd +• Afspeelsnelheid-Controls compacter gemaakt +• Feed markeert nu nieuwe items +• "Toon bekeken items" optie in de feed is nu opgeslagen + +Opgelost +• YouTube vind-ik-leuks en niet-leuks extractie opgelost +• Automatisch opnieuw afspelen na terugkeer uit de achtergrond is nu opgelost +En nog veel meer diff --git a/fastlane/metadata/android/nl/changelogs/981.txt b/fastlane/metadata/android/nl/changelogs/981.txt new file mode 100644 index 000000000..d30b0d1f1 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/981.txt @@ -0,0 +1,2 @@ +MediaParser-ondersteuning verwijderd om mislukte afspeelhervattingen na buffering op Android 11+ te verhelpen. +Media tunneling uitgeschakeld op Philips QM16XE om afspeelproblemen te verhelpen. diff --git a/fastlane/metadata/android/nl/changelogs/982.txt b/fastlane/metadata/android/nl/changelogs/982.txt new file mode 100644 index 000000000..deaa12d0c --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/982.txt @@ -0,0 +1 @@ +Opgelost: YouTube speelt geen stream af. diff --git a/fastlane/metadata/android/nl/changelogs/983.txt b/fastlane/metadata/android/nl/changelogs/983.txt new file mode 100644 index 000000000..a45e2fe69 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/983.txt @@ -0,0 +1,9 @@ +Toegevoegd: nieuwe 'dubbel-tik-naar-doorzoeken' UI en gedrag +Instellingen doorzoekbaar maken +Gepinde commentaren als zodanig markeren +Open-met-app ondersteuning toevoegen voor FSFE's PeerTube instantie +Foutmeldingen toevoegen +Herstel herhaling van het eerste wachtrij-item bij verandering van speler +Langer wachten bij buffering tijdens livestreams alvorens te falen +Volgorde van lokale zoekresultaten verbeteren +Herstel lege itemvelden in afspeelwachtrij diff --git a/fastlane/metadata/android/nl/full_description.txt b/fastlane/metadata/android/nl/full_description.txt index 2fa0ff5d0..3b8cef244 100644 --- a/fastlane/metadata/android/nl/full_description.txt +++ b/fastlane/metadata/android/nl/full_description.txt @@ -1 +1 @@ -NewPipe gebruikt geen enkele Google framework library, noch de YouTube API. Het analyseert de website alleen op zoek naar informatie die het nodig heeft. Daardoor kan deze app gebruikt worden zonder Google Services installatie. Daarnaast heb je geen YouTube-account nodig om NewPipe te gebruiken en is het FLOSS. +NewPipe gebruikt geen enkele Google framework library, noch de YouTube API. Het analyseert de website alleen op zoek naar informatie die het nodig heeft. Daardoor kan deze app gebruikt worden zonder Google Services installatie. Daarnaast heb je geen YouTube-account nodig om NewPipe te gebruiken, en is het FLOSS. diff --git a/fastlane/metadata/android/nl/short_description.txt b/fastlane/metadata/android/nl/short_description.txt index 3623d0a8d..907817858 100644 --- a/fastlane/metadata/android/nl/short_description.txt +++ b/fastlane/metadata/android/nl/short_description.txt @@ -1 +1 @@ -Een gratis, lichtgewicht YouTube-frontend voor Android. +Een gratis lichtgewicht YouTube frontend voor Android. diff --git a/fastlane/metadata/android/pl/changelogs/983.txt b/fastlane/metadata/android/pl/changelogs/983.txt new file mode 100644 index 000000000..f5fada987 --- /dev/null +++ b/fastlane/metadata/android/pl/changelogs/983.txt @@ -0,0 +1,9 @@ +Dodano nowe zachowanie typu „naciśnij dwukrotnie, aby przewinąć” +Możliwość przeszukiwania ustawień +Oznaczanie przypiętych komentarzy +Dodano obsługę otwierania w aplikacji instancji PeerTube FSFE +Dodano powiadomienia o błędach +Naprawiono powtarzanie pierwszej pozycji kolejki przy zmianie odtwarzacza +Wydłużono oczekiwanie podczas buforowania transmisji na żywo, zanim zakończy się ono niepowodzeniem +Naprawiono kolejność lokalnych wyników wyszukiwania +Naprawiono puste pozycje w kolejce odtwarzania diff --git a/fastlane/metadata/android/sv/changelogs/870.txt b/fastlane/metadata/android/sv/changelogs/870.txt new file mode 100644 index 000000000..fa2844e00 --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/870.txt @@ -0,0 +1,2 @@ +Detta är en hotfix-version som uppdaterar NewPipe så att du kan använda SoundCloud utan större problem igen. +SoundCloud's v2 API används nu i extraktorn och upptäckten av ogiltiga klient-ID:n har förbättrats. diff --git a/fastlane/metadata/android/sv/changelogs/910.txt b/fastlane/metadata/android/sv/changelogs/910.txt new file mode 100644 index 000000000..e944bea27 --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/910.txt @@ -0,0 +1 @@ +Fixade databasmigrering som hindrade NewPipe från att starta i vissa sällsynta fall. diff --git a/fastlane/metadata/android/sv/changelogs/950.txt b/fastlane/metadata/android/sv/changelogs/950.txt new file mode 100644 index 000000000..85779e384 --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/950.txt @@ -0,0 +1,4 @@ +Den här versionen innehåller tre små korrigeringar: +• Fixade lagringsåtkomst på Android 10+ +• Fixade öppningskiosker +• Fixade varaktighetstolkning av långa videor diff --git a/fastlane/metadata/android/sv/changelogs/953.txt b/fastlane/metadata/android/sv/changelogs/953.txt new file mode 100644 index 000000000..ab370bf37 --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/953.txt @@ -0,0 +1 @@ +Fixade extraktion av YouTubes dekrypteringsfunktion. diff --git a/fastlane/metadata/android/sv/changelogs/955.txt b/fastlane/metadata/android/sv/changelogs/955.txt new file mode 100644 index 000000000..2e6af8d11 --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/955.txt @@ -0,0 +1,3 @@ +[YouTube] Fixade sökningen för vissa användare +[YouTube] Fixade slumpmässiga dekrypteringsundantag +[SoundCloud] URL:er som slutar med ett snedstreck analyseras nu korrekt diff --git a/fastlane/metadata/android/sv/changelogs/956.txt b/fastlane/metadata/android/sv/changelogs/956.txt new file mode 100644 index 000000000..acb557def --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/956.txt @@ -0,0 +1 @@ +[YouTube] Fixade krasch vid laddning av en video diff --git a/fastlane/metadata/android/sv/changelogs/960.txt b/fastlane/metadata/android/sv/changelogs/960.txt new file mode 100644 index 000000000..9e7edd435 --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/960.txt @@ -0,0 +1,4 @@ +• Förbättrad beskrivning av exportdatabasalternativet i inställningar. +• Fixade analys av YouTube-kommentarer. +• Fixade visningsnamn för media.ccc.de tjänsten. +• Uppdaterade översättningar. diff --git a/fastlane/metadata/android/sv/changelogs/962.txt b/fastlane/metadata/android/sv/changelogs/962.txt new file mode 100644 index 000000000..0349562ed --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/962.txt @@ -0,0 +1,2 @@ +Lade till "senaste" videor till media.ccc.de tjänsten. +Lade till live sändningar till tjänsten media.ccc.de och stöd för live sändningar. diff --git a/fastlane/metadata/android/sv/changelogs/963.txt b/fastlane/metadata/android/sv/changelogs/963.txt new file mode 100644 index 000000000..3f2a6b748 --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/963.txt @@ -0,0 +1 @@ +• [YouTube] Fixade kanal fortsättning diff --git a/fastlane/metadata/android/sv/changelogs/967.txt b/fastlane/metadata/android/sv/changelogs/967.txt new file mode 100644 index 000000000..daa6d1376 --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/967.txt @@ -0,0 +1 @@ +Löste problemet med att YouTube inte fungerade korrekt i EU. Detta berodde på ett nytt system för cookies och samtycke till sekretess som kräver att NewPipe ställde in en CONSENT cookie. diff --git a/fastlane/metadata/android/sv/changelogs/971.txt b/fastlane/metadata/android/sv/changelogs/971.txt new file mode 100644 index 000000000..cd80648f2 --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/971.txt @@ -0,0 +1,3 @@ +Hotfix +• Öka bufferten för uppspelning efter återbuffring +• Fixade krasch på surfplattor och TV-apparater när du klickade på spelköikonen i spelaren diff --git a/fastlane/metadata/android/sv/changelogs/973.txt b/fastlane/metadata/android/sv/changelogs/973.txt new file mode 100644 index 000000000..5b5be8181 --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/973.txt @@ -0,0 +1,4 @@ +Hotfix +• Åtgärda miniatyrer och titlar som klipptes av i rutnätslayouten på grund av en felaktig beräkning av hur många videor som får plats på en rad +• Fixa att nedladdningsdialogrutan försvinner utan att göra något om den öppnas från delningsmenyn +• Uppdatera ett bibliotek relaterat till att öppna externa aktiviteter som filväljaren Storage Access Framework diff --git a/fastlane/metadata/android/sv/changelogs/974.txt b/fastlane/metadata/android/sv/changelogs/974.txt new file mode 100644 index 000000000..78153154b --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/974.txt @@ -0,0 +1,5 @@ +Hotfix +• Åtgärda buffringsproblem som orsakas av YouTube strypning +• Åtgärda extraktion av YouTube kommentarer och kraschar med inaktiverade kommentarer +• Fixade YouTube musiksökning +• Fixade PeerTube live sändningar diff --git a/fastlane/metadata/android/sv/changelogs/978.txt b/fastlane/metadata/android/sv/changelogs/978.txt new file mode 100644 index 000000000..2f7521531 --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/978.txt @@ -0,0 +1 @@ +Fixade kontrollen av en ny NewPipe-version. Denna kontroll utfördes ibland för tidigt och ledde därför till att appen kraschade. Detta bör vara åtgärdat nu. diff --git a/fastlane/metadata/android/uk/changelogs/65.txt b/fastlane/metadata/android/uk/changelogs/65.txt new file mode 100644 index 000000000..c394fc4f5 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/65.txt @@ -0,0 +1 @@ +Опис застарілий і задовгий. Перекладу не потребує. diff --git a/fastlane/metadata/android/uk/changelogs/66.txt b/fastlane/metadata/android/uk/changelogs/66.txt new file mode 100644 index 000000000..c394fc4f5 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/66.txt @@ -0,0 +1 @@ +Опис застарілий і задовгий. Перекладу не потребує. diff --git a/fastlane/metadata/android/uk/changelogs/68.txt b/fastlane/metadata/android/uk/changelogs/68.txt new file mode 100644 index 000000000..c394fc4f5 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/68.txt @@ -0,0 +1 @@ +Опис застарілий і задовгий. Перекладу не потребує. diff --git a/fastlane/metadata/android/uk/changelogs/69.txt b/fastlane/metadata/android/uk/changelogs/69.txt new file mode 100644 index 000000000..c394fc4f5 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/69.txt @@ -0,0 +1 @@ +Опис застарілий і задовгий. Перекладу не потребує. diff --git a/fastlane/metadata/android/uk/changelogs/70.txt b/fastlane/metadata/android/uk/changelogs/70.txt new file mode 100644 index 000000000..c394fc4f5 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/70.txt @@ -0,0 +1 @@ +Опис застарілий і задовгий. Перекладу не потребує. diff --git a/fastlane/metadata/android/uk/changelogs/740.txt b/fastlane/metadata/android/uk/changelogs/740.txt new file mode 100644 index 000000000..c394fc4f5 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/740.txt @@ -0,0 +1 @@ +Опис застарілий і задовгий. Перекладу не потребує. diff --git a/fastlane/metadata/android/uk/changelogs/750.txt b/fastlane/metadata/android/uk/changelogs/750.txt new file mode 100644 index 000000000..c394fc4f5 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/750.txt @@ -0,0 +1 @@ +Опис застарілий і задовгий. Перекладу не потребує. diff --git a/fastlane/metadata/android/uk/changelogs/760.txt b/fastlane/metadata/android/uk/changelogs/760.txt new file mode 100644 index 000000000..c394fc4f5 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/760.txt @@ -0,0 +1 @@ +Опис застарілий і задовгий. Перекладу не потребує. diff --git a/fastlane/metadata/android/uk/changelogs/800.txt b/fastlane/metadata/android/uk/changelogs/800.txt new file mode 100644 index 000000000..c394fc4f5 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/800.txt @@ -0,0 +1 @@ +Опис застарілий і задовгий. Перекладу не потребує. diff --git a/fastlane/metadata/android/uk/changelogs/810.txt b/fastlane/metadata/android/uk/changelogs/810.txt new file mode 100644 index 000000000..c394fc4f5 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/810.txt @@ -0,0 +1 @@ +Опис застарілий і задовгий. Перекладу не потребує. diff --git a/fastlane/metadata/android/uk/changelogs/840.txt b/fastlane/metadata/android/uk/changelogs/840.txt new file mode 100644 index 000000000..c394fc4f5 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/840.txt @@ -0,0 +1 @@ +Опис застарілий і задовгий. Перекладу не потребує. diff --git a/fastlane/metadata/android/uk/changelogs/982.txt b/fastlane/metadata/android/uk/changelogs/982.txt new file mode 100644 index 000000000..41d4d11ce --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/982.txt @@ -0,0 +1 @@ +Виправлено проблему невідтворюваності трансляцій YouTube. diff --git a/fastlane/metadata/android/uk/changelogs/983.txt b/fastlane/metadata/android/uk/changelogs/983.txt new file mode 100644 index 000000000..f500868bb --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/983.txt @@ -0,0 +1,9 @@ +Переоформлено прокручування дотиком двічі +Додано пошук у налаштуваннях +Підсвічено закріплені коментарі +Втілено відкриття застосунком адрес FSFE PeerTube +Додано сповіщення про збої +Виправлено повтор першого в черзі при зміні програвача +Підтримано довше очікування буферів живих потоків +Упорядковано результати локального пошуку +Виправлено порожні поля в черзі відтворення diff --git a/fastlane/metadata/android/uk/full_description.txt b/fastlane/metadata/android/uk/full_description.txt index 1f7a0bd4e..46fd17600 100644 --- a/fastlane/metadata/android/uk/full_description.txt +++ b/fastlane/metadata/android/uk/full_description.txt @@ -1 +1 @@ -NewPipe не використовує бібліотеки фреймворку Google або API YouTube, взаємодіючи тільки з сайтом служби для отримання потрібних відомостей. NewPipe може працювати на пристроях без встановлених Служб Google і не вимагає облікового запису YouTube, є вільним програмним забезпеченням. +NewPipe не використовує бібліотеки фреймворку Google або API YouTube, взаємодіючи тільки з сайтом служби для отримання потрібних відомостей. NewPipe може працювати на пристроях без установлених Служб Google і не вимагає облікового запису YouTube, є вільним програмним забезпеченням. diff --git a/fastlane/metadata/android/zh-Hans/changelogs/982.txt b/fastlane/metadata/android/zh-Hans/changelogs/982.txt new file mode 100644 index 000000000..8a5424c9e --- /dev/null +++ b/fastlane/metadata/android/zh-Hans/changelogs/982.txt @@ -0,0 +1 @@ +修复YouTube无法播放任何视频 diff --git a/fastlane/metadata/android/zh-Hans/changelogs/983.txt b/fastlane/metadata/android/zh-Hans/changelogs/983.txt new file mode 100644 index 000000000..056a95fe2 --- /dev/null +++ b/fastlane/metadata/android/zh-Hans/changelogs/983.txt @@ -0,0 +1,9 @@ +新增 新的双击视频寻址UI和行为 +新增 支持设置项目被搜索 +新增 突出显示置顶评论 +新增 为FSFE的PeerTube实例添加开放应用支持 +新增 错误报告通知 +修复 播放器变化后,重新播放播放队列中第一个项目 +改进 缓冲直播时,在失败前等待更长的时间 +修复 本地搜索结果的顺序异常 +修复 播放队列中的空白项目 diff --git a/fastlane/metadata/android/zh-Hans/full_description.txt b/fastlane/metadata/android/zh-Hans/full_description.txt index c168ee934..d55f32fa1 100644 --- a/fastlane/metadata/android/zh-Hans/full_description.txt +++ b/fastlane/metadata/android/zh-Hans/full_description.txt @@ -1 +1 @@ -NewPipe 不使用任何 Google 框架库组件,或 YouTube API。NewPipe 仅仅通过解析 YouTube 网页版来获取所需信息。因此该应用可工作在无 Google 服务的设备上。此外,你也不需要 YouTube 账号,NewPipe是自由开源软件(FLOSS)。 +NewPipe 不使用任何 Google 框架库组件,也不使用 YouTube API。NewPipe 仅仅通过解析 YouTube 网页版来获取所需信息。因此,可在没有安装 Google 服务的设备上使用 NewPipe。此外,使用 NewPipe 并不需要 YouTube 账号,NewPipe 是自由开源软件(FLOSS)。 diff --git a/fastlane/metadata/android/zh_Hant_HK/changelogs/981.txt b/fastlane/metadata/android/zh_Hant_HK/changelogs/981.txt new file mode 100644 index 000000000..cf0bd8588 --- /dev/null +++ b/fastlane/metadata/android/zh_Hant_HK/changelogs/981.txt @@ -0,0 +1,2 @@ +移除了對MediaParser的支持,以解決在Android 11+上緩衝後恢復播放失敗的問題。 +在Philips QM16XE上禁用了媒體隧道,以解決播放問題。 diff --git a/fastlane/metadata/android/zh_Hant_HK/changelogs/983.txt b/fastlane/metadata/android/zh_Hant_HK/changelogs/983.txt new file mode 100644 index 000000000..ec2edbe38 --- /dev/null +++ b/fastlane/metadata/android/zh_Hant_HK/changelogs/983.txt @@ -0,0 +1,9 @@ +新加撳兩下跳轉嘅介面同功能 +設定有得打字嚟搵 +留言置頂有色水分辨 +為 FSFE 嘅 PeerTube 站新加「用 app 嚟開」支援 +新加錯誤通知 +修正播放器轉變時重播隊頭項目 +直播串流緩衝時等耐啲先至算失敗 +修正本機搜尋結果嘅排位 +修正排隊播入面開天窗嘅項目欄位 diff --git a/fastlane/metadata/android/zh_Hant_HK/full_description.txt b/fastlane/metadata/android/zh_Hant_HK/full_description.txt new file mode 100644 index 000000000..1a516a17d --- /dev/null +++ b/fastlane/metadata/android/zh_Hant_HK/full_description.txt @@ -0,0 +1 @@ +NewPipe 沒有使用任何 Google 框架庫組件或是 YouTube API。NewPipe 只需解析網頁以獲取所需資訊,因此 NewPipe 可在沒有安裝 Google 服務的裝置上使用。此外,你亦無需 YouTube 帳號就能使用NewPipe,NewPipe 是自由及開放源碼軟件(FLOSS)。 diff --git a/fastlane/metadata/android/zh_Hant_HK/short_description.txt b/fastlane/metadata/android/zh_Hant_HK/short_description.txt new file mode 100644 index 000000000..fca9de0da --- /dev/null +++ b/fastlane/metadata/android/zh_Hant_HK/short_description.txt @@ -0,0 +1 @@ +一個自由輕量的 Android YouTube 前端。 From 54f0b3d8b3b156275a7aa8240759d44bf42fd43c Mon Sep 17 00:00:00 2001 From: TobiGr Date: Fri, 4 Feb 2022 20:54:25 +0100 Subject: [PATCH 118/119] Release NewPipe 0.22.0 (983) --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 042818a03..bbd8cf415 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,8 +16,8 @@ android { resValue "string", "app_name", "NewPipe" minSdk 19 targetSdk 29 - versionCode 982 - versionName "0.21.16" + versionCode 983 + versionName "0.22.0" multiDexEnabled true From 00767f4bf3c568f06735756939f78eb669ab8df5 Mon Sep 17 00:00:00 2001 From: Stypox Date: Fri, 18 Feb 2022 13:48:59 +0100 Subject: [PATCH 119/119] Fix fast seek overlay arc not correctly centered This happened in fullscreen player: while play-pause, brightness, volume, ... buttons were correctly centered in the app UI, the fast seek overlay was centered in the system UI, causing a mismatch between the two that looked ugly --- .../org/schabi/newpipe/player/Player.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 516eafcd9..e0debc4e7 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -572,14 +572,20 @@ public final class Player implements }); // PlaybackControlRoot already consumed window insets but we should pass them to - // player_overlays too. Without it they will be off-centered + // player_overlays and fast_seek_overlay too. Without it they will be off-centered. binding.playbackControlRoot.addOnLayoutChangeListener( - (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> - binding.playerOverlays.setPadding( - v.getPaddingLeft(), - v.getPaddingTop(), - v.getPaddingRight(), - v.getPaddingBottom())); + (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { + binding.playerOverlays.setPadding( + v.getPaddingLeft(), + v.getPaddingTop(), + v.getPaddingRight(), + v.getPaddingBottom()); + binding.fastSeekOverlay.setPadding( + v.getPaddingLeft(), + v.getPaddingTop(), + v.getPaddingRight(), + v.getPaddingBottom()); + }); } /**