Updated on 2026-08-14
This commit is contained in:
parent
f4422dd3fb
commit
a107ddd36e
6 changed files with 148 additions and 12 deletions
|
|
@ -1,3 +0,0 @@
|
|||
package com.tangem.tap.common.extensions
|
||||
|
||||
fun StringBuilder.breakLine(count: Int = 1): StringBuilder = append("\n".repeat(count))
|
||||
|
|
@ -6,4 +6,17 @@ plugins {
|
|||
|
||||
android {
|
||||
namespace = "com.tangem.core.res"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation(projects.core.utils)
|
||||
|
||||
implementation(deps.timber)
|
||||
|
||||
// region Firebase libraries
|
||||
implementation(platform(deps.firebase.bom))
|
||||
implementation(deps.firebase.analytics)
|
||||
implementation(deps.firebase.crashlytics)
|
||||
// endregion
|
||||
}
|
||||
82
core/res/src/main/java/com/tangem/core/res/Resources.kt
Normal file
82
core/res/src/main/java/com/tangem/core/res/Resources.kt
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
package com.tangem.core.res
|
||||
|
||||
import android.content.res.Resources
|
||||
import androidx.annotation.PluralsRes
|
||||
import androidx.annotation.StringRes
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.tangem.utils.SupportedLanguages
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* Get a string resource safely or the resource name if an exception is thrown
|
||||
*
|
||||
* @param id resource id
|
||||
*/
|
||||
fun Resources.getStringSafe(@StringRes id: Int): String {
|
||||
return runCatching { getString(id) }
|
||||
.getOrResourceName(resources = this, id)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string resource safely or the resource name if an exception is thrown
|
||||
*
|
||||
* @param id resource id
|
||||
* @param formatArgs format args
|
||||
*/
|
||||
fun Resources.getStringSafe(@StringRes id: Int, vararg formatArgs: Any): String {
|
||||
return runCatching { getString(id, *formatArgs) }
|
||||
.recoverCatching {
|
||||
// If something goes wrong, returns the resource without arguments
|
||||
val string = getString(id)
|
||||
|
||||
reportIssue(resources = this, id, *formatArgs)
|
||||
|
||||
string
|
||||
}
|
||||
.getOrResourceName(resources = this, id, *formatArgs)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a plural string resource safely or the resource name if an exception is thrown
|
||||
*
|
||||
* @param id resource id
|
||||
* @param count count
|
||||
*/
|
||||
fun Resources.getPluralStringSafe(@PluralsRes id: Int, count: Int): String {
|
||||
return runCatching { getQuantityString(id, count) }
|
||||
.getOrResourceName(resources = this, id)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a plural string resource safely or the resource name if an exception is thrown
|
||||
*
|
||||
* @param id resource id
|
||||
* @param count count
|
||||
* @param formatArgs format args
|
||||
*/
|
||||
fun Resources.getPluralStringSafe(@PluralsRes id: Int, count: Int, vararg formatArgs: Any): String {
|
||||
return runCatching { getQuantityString(id, count, *formatArgs) }
|
||||
.getOrResourceName(resources = this, id, *formatArgs)
|
||||
}
|
||||
|
||||
private fun Result<String>.getOrResourceName(resources: Resources, id: Int, vararg formatArgs: Any): String {
|
||||
return getOrElse {
|
||||
reportIssue(resources, id, formatArgs)
|
||||
|
||||
// If something still goes wrong, returns the resource name
|
||||
resources.getResourceEntryName(id)
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportIssue(resources: Resources, id: Int, vararg formatArgs: Any) {
|
||||
val exception = IllegalStateException(
|
||||
"An error occurred while parsing the string:\n" +
|
||||
"\tname: R.string.${resources.getResourceEntryName(id)}\n" +
|
||||
"\targs: ${formatArgs.joinToString(prefix = "[", postfix = "]") { it.toString() }}\n" +
|
||||
"\tlocale: ${SupportedLanguages.getCurrentSupportedLanguageCode()}\n",
|
||||
)
|
||||
|
||||
Timber.tag("Resources").e(exception)
|
||||
|
||||
FirebaseCrashlytics.getInstance().recordException(exception)
|
||||
}
|
||||
|
|
@ -2,12 +2,56 @@ package com.tangem.core.ui.extensions
|
|||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import androidx.annotation.PluralsRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import com.google.zxing.BarcodeFormat
|
||||
import com.google.zxing.EncodeHintType
|
||||
import com.google.zxing.qrcode.QRCodeWriter
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
|
||||
import com.tangem.core.res.getPluralStringSafe
|
||||
import com.tangem.core.res.getStringSafe
|
||||
import java.util.Hashtable
|
||||
|
||||
/**
|
||||
* Get a string resource safely or the resource name if an exception is thrown
|
||||
*
|
||||
* @param id resource id
|
||||
* @param formatArgs format args
|
||||
*/
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
fun stringResourceSafe(@StringRes id: Int, vararg formatArgs: Any): String {
|
||||
val resources = LocalContext.current.resources
|
||||
|
||||
return if (formatArgs.isEmpty()) {
|
||||
resources.getStringSafe(id)
|
||||
} else {
|
||||
resources.getStringSafe(id, *formatArgs)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a plural string resource safely or the resource name if an exception is thrown
|
||||
*
|
||||
* @param id resource id
|
||||
* @param count count
|
||||
* @param formatArgs format args
|
||||
*/
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
fun pluralStringResourceSafe(@PluralsRes id: Int, count: Int, vararg formatArgs: Any): String {
|
||||
val resources = LocalContext.current.resources
|
||||
|
||||
return if (formatArgs.isEmpty()) {
|
||||
resources.getPluralStringSafe(id, count)
|
||||
} else {
|
||||
resources.getPluralStringSafe(id, count, *formatArgs)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
fun String.toQrCode(sizePx: Int = 256, paddingPx: Int = 0): Bitmap {
|
||||
val hintMap = Hashtable<EncodeHintType, Any>()
|
||||
|
|
|
|||
|
|
@ -6,12 +6,11 @@ import androidx.annotation.StringRes
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.AnnotatedString.Builder
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.decapitalize
|
||||
import com.tangem.core.res.getPluralStringSafe
|
||||
import com.tangem.core.res.getStringSafe
|
||||
import org.intellij.markdown.MarkdownElementTypes
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
|
|
@ -172,7 +171,7 @@ fun TextReference.resolveReference(): String {
|
|||
.map { if (it is TextReference) it.resolveReference() else it }
|
||||
.toTypedArray()
|
||||
|
||||
val resolvedReference = stringResource(id = id, *args)
|
||||
val resolvedReference = stringResourceSafe(id = id, *args)
|
||||
|
||||
if (decapitalize) {
|
||||
resolvedReference.replaceFirstChar { char -> char.lowercase() }
|
||||
|
|
@ -180,7 +179,7 @@ fun TextReference.resolveReference(): String {
|
|||
resolvedReference
|
||||
}
|
||||
}
|
||||
is TextReference.PluralRes -> pluralStringResource(id, count, *formatArgs.toTypedArray())
|
||||
is TextReference.PluralRes -> pluralStringResourceSafe(id, count, *formatArgs.toTypedArray())
|
||||
is TextReference.Str -> value
|
||||
is TextReference.Annotated -> value.text
|
||||
is TextReference.Combined -> {
|
||||
|
|
@ -201,9 +200,9 @@ fun TextReference.resolveReference(resources: Resources): String {
|
|||
.map { if (it is TextReference) it.resolveReference(resources) else it }
|
||||
.toTypedArray()
|
||||
|
||||
resources.getString(id, *args)
|
||||
resources.getStringSafe(id, *args)
|
||||
}
|
||||
is TextReference.PluralRes -> resources.getQuantityString(id, count, *formatArgs.toTypedArray())
|
||||
is TextReference.PluralRes -> resources.getPluralStringSafe(id, count, *formatArgs.toTypedArray())
|
||||
is TextReference.Str -> value
|
||||
is TextReference.Annotated -> value.text
|
||||
is TextReference.Combined -> {
|
||||
|
|
@ -225,10 +224,10 @@ fun TextReference.resolveAnnotatedReference(): AnnotatedString {
|
|||
.map { if (it is TextReference) it.resolveReference() else it }
|
||||
.toTypedArray()
|
||||
|
||||
formatAnnotated(stringResource(id = id, *args))
|
||||
formatAnnotated(stringResourceSafe(id = id, *args))
|
||||
}
|
||||
is TextReference.PluralRes -> formatAnnotated(
|
||||
pluralStringResource(id, count, *formatArgs.toTypedArray()),
|
||||
pluralStringResourceSafe(id, count, *formatArgs.toTypedArray()),
|
||||
)
|
||||
is TextReference.Str -> formatAnnotated(value)
|
||||
is TextReference.Annotated -> value
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import android.net.Uri
|
|||
import com.tangem.utils.SupportedLanguages
|
||||
import java.util.Locale
|
||||
|
||||
// TODO: [REDACTED_JIRA]
|
||||
internal fun seedPhraseLearnMoreUrl(): String {
|
||||
val language = Locale.getDefault().language
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue