Updated on 2026-08-14

This commit is contained in:
Tangem 2026-01-28 12:27:26 +05:00
parent 7f7060a547
commit 0cfab87af8
6 changed files with 37 additions and 15 deletions

View file

@ -225,7 +225,7 @@ internal class DefaultNewsRepository(
when (val apiResponse = newsApi.getTrendingNews(limit = limit, language = language)) {
is ApiResponse.Error -> {
Timber.e(
apiResponse.cause.cause,
apiResponse.cause,
"Trending news fetch failed cause: ${
when (val error = apiResponse.cause) {
is ApiResponseError.HttpException -> error.code
@ -238,7 +238,7 @@ internal class DefaultNewsRepository(
trendingNewsStore.clear()
trendingNewsStore.store(
key = TRENDING_NEWS_KEY,
value = TrendingNews.Error(error = newsErrorResolver.resolve(apiResponse.cause.cause)),
value = TrendingNews.Error(error = newsErrorResolver.resolve(apiResponse.cause)),
)
}
is ApiResponse.Success<NewsTrendingResponse> -> {

View file

@ -74,7 +74,7 @@ internal class DefaultFeedEntryComponent @AssistedInject constructor(
onArticleClick(
articleId = articleId,
preselectedArticlesId = preselectedArticlesId,
screenSource = AnalyticsParam.ScreensSources.Markets,
screenSource = AnalyticsParam.ScreensSources.Token,
)
},
),

View file

@ -13,33 +13,35 @@ internal sealed class MarketTokenAnalyticsEvent(
) : AnalyticsEvent(category = "CoinPage", event = event, params = params) {
data class TokenNewsViewed(
private val token: String,
private val tokenSymbol: String,
) : MarketTokenAnalyticsEvent(
event = "Token News Viewed",
params = mapOf(
AnalyticsParam.TOKEN_PARAM to token,
AnalyticsParam.TOKEN_PARAM to tokenSymbol,
),
), OneTimePerSessionEvent {
override val oneTimeEventId: String = event + token
override val oneTimeEventId: String = event + tokenSymbol
}
data class TokenNewsCarouselScrolled(
private val token: String,
private val tokenSymbol: String,
) : MarketTokenAnalyticsEvent(
event = "Token News Carousel Scrolled",
params = mapOf(
AnalyticsParam.TOKEN_PARAM to token,
AnalyticsParam.TOKEN_PARAM to tokenSymbol,
),
), OneTimePerSessionEvent {
override val oneTimeEventId: String = event + token
override val oneTimeEventId: String = event + tokenSymbol
}
data class TokenNewsLoadError(
private val tokenSymbol: String,
private val code: Int?,
private val message: String,
) : MarketTokenAnalyticsEvent(
event = "Token News Load Error",
params = mapOf(
AnalyticsParam.TOKEN_PARAM to tokenSymbol,
ERROR_CODE to (code ?: IS_NOT_HTTP_ERROR).toString(),
ERROR_MESSAGE to message,
),

View file

@ -329,14 +329,14 @@ internal class MarketsTokenDetailsModel @Inject constructor(
onFirstVisible = {
analyticsEventHandler.send(
MarketTokenAnalyticsEvent.TokenNewsViewed(
token = params.token.symbol,
tokenSymbol = params.token.symbol,
),
)
},
onScroll = {
analyticsEventHandler.send(
MarketTokenAnalyticsEvent.TokenNewsCarouselScrolled(
token = params.token.symbol,
tokenSymbol = params.token.symbol,
),
)
},
@ -351,6 +351,7 @@ internal class MarketsTokenDetailsModel @Inject constructor(
}
analyticsEventHandler.send(
MarketTokenAnalyticsEvent.TokenNewsLoadError(
tokenSymbol = params.token.symbol,
code = code,
message = message,
),

View file

@ -208,28 +208,36 @@ internal class NewsDetailsModel @Inject constructor(
newsIds = params.preselectedArticlesId,
language = currentLanguage,
).onLeft { errors ->
errors.onEach { (newsId, throwable) ->
errors.onEach { (newsId, error) ->
when {
// an article is opened from deeplink and is not found
params.screenSource == AnalyticsParam.ScreensSources.NewsLink.value &&
newsId == params.articleId &&
throwable is ApiResponseError.HttpException &&
throwable.code == ApiResponseError.HttpException.Code.NOT_FOUND
error is ApiResponseError.HttpException &&
error.code == ApiResponseError.HttpException.Code.NOT_FOUND
-> {
analyticsEventHandler.send(
NewsDetailsAnalyticsEvent.NewsLinkMismatch(
newsId = params.articleId,
code = error.code.numericCode,
message = error.message.orEmpty(),
),
)
}
// global request executing error
newsId < 0 -> {
Timber.e(throwable)
Timber.e(error)
}
else -> {
val (code, message) = when (error) {
is ApiResponseError.HttpException -> error.code.numericCode to error.message.orEmpty()
else -> null to ""
}
analyticsEventHandler.send(
NewsDetailsAnalyticsEvent.NewsArticleLoadError(
newsId = newsId,
code = code,
message = message,
),
)
}

View file

@ -2,6 +2,9 @@ package com.tangem.features.feed.model.news.details.analytics
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.AnalyticsParam.Key.ERROR_CODE
import com.tangem.core.analytics.models.AnalyticsParam.Key.ERROR_MESSAGE
import com.tangem.core.analytics.models.IS_NOT_HTTP_ERROR
import com.tangem.core.analytics.models.OneTimePerSessionEvent
internal sealed class NewsDetailsAnalyticsEvent(
@ -44,19 +47,27 @@ internal sealed class NewsDetailsAnalyticsEvent(
data class NewsArticleLoadError(
private val newsId: Int,
private val code: Int?,
private val message: String,
) : NewsDetailsAnalyticsEvent(
event = "News Article Load Error",
params = mapOf(
"News Id" to newsId.toString(),
ERROR_CODE to (code ?: IS_NOT_HTTP_ERROR).toString(),
ERROR_MESSAGE to message,
),
)
data class NewsLinkMismatch(
private val newsId: Int,
private val code: Int?,
private val message: String,
) : NewsDetailsAnalyticsEvent(
event = "News Link Mismatch",
params = mapOf(
"News Id" to newsId.toString(),
ERROR_CODE to (code ?: IS_NOT_HTTP_ERROR).toString(),
ERROR_MESSAGE to message,
),
)
}