Add Sign in confirm not a bot issue URL to the exception error message
Make error panel and error activity exception message URLs clickable via extension method Change ErrorMessage.getString to getText and return CharSequence, and use getText with formatArgs to preserve styling (i.e. URLs)
This commit is contained in:
parent
0cdf40cd5f
commit
e173bf4252
6 changed files with 50 additions and 13 deletions
|
|
@ -25,6 +25,7 @@ import org.schabi.newpipe.databinding.ActivityErrorBinding
|
|||
import org.schabi.newpipe.util.Localization
|
||||
import org.schabi.newpipe.util.ThemeHelper
|
||||
import org.schabi.newpipe.util.external_communication.ShareUtils
|
||||
import org.schabi.newpipe.util.text.setTextWithLinks
|
||||
|
||||
/**
|
||||
* This activity is used to show error details and allow reporting them in various ways.
|
||||
|
|
@ -100,7 +101,7 @@ class ErrorActivity : AppCompatActivity() {
|
|||
|
||||
// normal bugreport
|
||||
buildInfo(errorInfo)
|
||||
binding.errorMessageView.text = errorInfo.getMessage(this)
|
||||
binding.errorMessageView.setTextWithLinks(errorInfo.getMessage(this))
|
||||
binding.errorView.text = formErrorText(errorInfo.stackTraces)
|
||||
|
||||
// print stack trace once again for debugging:
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import org.schabi.newpipe.extractor.exceptions.YoutubeMusicPremiumContentExcepti
|
|||
import org.schabi.newpipe.ktx.isNetworkRelated
|
||||
import org.schabi.newpipe.player.mediasource.FailedMediaSource
|
||||
import org.schabi.newpipe.player.resolver.PlaybackResolver
|
||||
import org.schabi.newpipe.util.text.getText
|
||||
|
||||
/**
|
||||
* An error has occurred in the app. This class contains plain old parcelable data that can be used
|
||||
|
|
@ -135,8 +136,8 @@ class ErrorInfo private constructor(
|
|||
return getServiceName(serviceId)
|
||||
}
|
||||
|
||||
fun getMessage(context: Context): String {
|
||||
return message.getString(context)
|
||||
fun getMessage(context: Context): CharSequence {
|
||||
return message.getText(context)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
@ -146,20 +147,23 @@ class ErrorInfo private constructor(
|
|||
private val stringRes: Int,
|
||||
private vararg val formatArgs: String
|
||||
) : Parcelable {
|
||||
fun getString(context: Context): String {
|
||||
fun getText(context: Context): CharSequence {
|
||||
// Ensure locale aware context via ContextCompat.getContextForLanguage() (just in case context is not AppCompatActivity)
|
||||
val ctx = ContextCompat.getContextForLanguage(context)
|
||||
return if (formatArgs.isEmpty()) {
|
||||
// use ContextCompat.getString() just in case context is not AppCompatActivity
|
||||
ContextCompat.getString(context, stringRes)
|
||||
ctx.getText(stringRes)
|
||||
} else {
|
||||
// ContextCompat.getString() with formatArgs does not exist, so we just
|
||||
// replicate its source code but with formatArgs
|
||||
ContextCompat.getContextForLanguage(context).getString(stringRes, *formatArgs)
|
||||
ctx.resources.getText(stringRes, *formatArgs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const val SERVICE_NONE = "<unknown_service>"
|
||||
|
||||
const val SIGN_IN_CONFIRM_NOT_BOT_ISSUE_URL = "https://github.com/TeamNewPipe/NewPipe/issues/11139"
|
||||
|
||||
private fun getServiceName(serviceId: Int?) = // not using getNameOfServiceById since we want to accept a nullable serviceId and we
|
||||
// want to default to SERVICE_NONE
|
||||
ServiceList.all().firstOrNull { it.serviceId == serviceId }?.serviceInfo?.name
|
||||
|
|
@ -247,7 +251,9 @@ class ErrorInfo private constructor(
|
|||
ErrorMessage(R.string.youtube_music_premium_content)
|
||||
|
||||
throwable is SignInConfirmNotBotException ->
|
||||
ErrorMessage(R.string.sign_in_confirm_not_bot_error, getServiceName(serviceId))
|
||||
ErrorMessage(R.string.sign_in_confirm_not_bot_error,
|
||||
getServiceName(serviceId),
|
||||
SIGN_IN_CONFIRM_NOT_BOT_ISSUE_URL)
|
||||
|
||||
throwable is ContentNotAvailableException ->
|
||||
ErrorMessage(R.string.content_not_available)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import org.schabi.newpipe.MainActivity
|
|||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.ktx.animate
|
||||
import org.schabi.newpipe.util.external_communication.ShareUtils
|
||||
import org.schabi.newpipe.util.text.setTextWithLinks
|
||||
|
||||
class ErrorPanelHelper(
|
||||
private val fragment: Fragment,
|
||||
|
|
@ -64,7 +65,7 @@ class ErrorPanelHelper(
|
|||
|
||||
fun showError(errorInfo: ErrorInfo) {
|
||||
ensureDefaultVisibility()
|
||||
errorTextView.text = errorInfo.getMessage(context)
|
||||
errorTextView.setTextWithLinks(errorInfo.getMessage(context))
|
||||
|
||||
if (errorInfo.recaptchaUrl != null) {
|
||||
showAndSetErrorButtonAction(R.string.recaptcha_solve) {
|
||||
|
|
@ -109,7 +110,7 @@ class ErrorPanelHelper(
|
|||
fun showTextError(errorString: String) {
|
||||
ensureDefaultVisibility()
|
||||
|
||||
errorTextView.text = errorString
|
||||
errorTextView.setTextWithLinks(errorString)
|
||||
|
||||
setRootVisible()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ import org.schabi.newpipe.util.NavigationHelper
|
|||
*/
|
||||
class MediaBrowserPlaybackPreparer(
|
||||
private val context: Context,
|
||||
private val setMediaSessionError: BiConsumer<String, Int>, // error string, error code
|
||||
private val setMediaSessionError: BiConsumer<CharSequence, Int>, // error string, error code
|
||||
private val clearMediaSessionError: Runnable,
|
||||
private val onPrepare: Consumer<Boolean>
|
||||
) : PlaybackPreparer {
|
||||
|
|
@ -118,7 +118,7 @@ class MediaBrowserPlaybackPreparer(
|
|||
|
||||
private fun onPrepareError(throwable: Throwable) {
|
||||
setMediaSessionError.accept(
|
||||
ErrorInfo.getMessage(throwable, null, null).getString(context),
|
||||
ErrorInfo.getMessage(throwable, null, null).getText(context),
|
||||
PlaybackStateCompat.ERROR_CODE_APP_ERROR
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
package org.schabi.newpipe.util.text
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.text.SpannableString
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.text.util.Linkify
|
||||
import android.util.Patterns
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.text.parseAsHtml
|
||||
import androidx.core.text.toHtml
|
||||
import androidx.core.text.toSpanned
|
||||
|
||||
/**
|
||||
* Takes in a CharSequence [text]
|
||||
* and makes raw HTTP URLs and HTML anchor tags clickable
|
||||
*/
|
||||
fun TextView.setTextWithLinks(text: CharSequence) {
|
||||
val spanned = SpannableString(text)
|
||||
// Using the pattern overload of addLinks since the one with the int masks strips all spans from the text before applying new ones
|
||||
Linkify.addLinks(spanned, Patterns.WEB_URL, null)
|
||||
this.text = spanned
|
||||
this.movementMethod = LinkMovementMethod.getInstance()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets text from string resource with [id] while preserving styling and allowing string format value substitution of [formatArgs]
|
||||
*/
|
||||
fun Resources.getText(@StringRes id: Int, vararg formatArgs: Any?): CharSequence = getText(id).toSpanned().toHtml().format(*formatArgs).parseAsHtml()
|
||||
Loading…
Add table
Add a link
Reference in a new issue