Updated on 2026-08-14

This commit is contained in:
Tangem 2023-06-19 08:51:46 +03:00
parent 7e765758b4
commit efe271e1a0
24 changed files with 751 additions and 75 deletions

View file

@ -138,6 +138,8 @@
android:name="com.tangem.tap.features.sprinklr.ui.SprinklrActivity"
android:theme="@style/AppTheme" />
<activity android:name="com.tangem.feature.learn2earn.presentation.Learn2earnWebViewActivity"/>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"

View file

@ -1,59 +1,67 @@
package com.tangem.tap
import android.app.*
import android.content.*
import android.content.pm.*
import coil.*
import com.tangem.*
import com.tangem.blockchain.common.*
import com.tangem.blockchain.network.*
import com.tangem.core.analytics.*
import com.tangem.core.featuretoggle.manager.*
import com.tangem.data.source.preferences.*
import com.tangem.datasource.api.common.*
import com.tangem.datasource.asset.*
import com.tangem.datasource.config.*
import com.tangem.datasource.config.models.*
import com.tangem.datasource.connection.*
import com.tangem.domain.*
import com.tangem.domain.common.*
import com.tangem.features.wallet.featuretoggles.*
import com.tangem.tap.common.*
import com.tangem.tap.common.analytics.*
import com.tangem.tap.common.analytics.api.*
import com.tangem.tap.common.analytics.handlers.amplitude.*
import com.tangem.tap.common.analytics.handlers.appsFlyer.*
import com.tangem.tap.common.analytics.handlers.firebase.*
import com.tangem.tap.common.analytics.topup.*
import com.tangem.tap.common.chat.*
import com.tangem.tap.common.feedback.*
import com.tangem.tap.common.images.*
import com.tangem.tap.common.log.*
import com.tangem.tap.common.redux.*
import com.tangem.tap.common.redux.global.*
import com.tangem.tap.common.shop.*
import com.tangem.tap.domain.configurable.warningMessage.*
import com.tangem.tap.domain.tokens.*
import com.tangem.tap.domain.totalBalance.*
import com.tangem.tap.domain.totalBalance.di.*
import com.tangem.tap.domain.walletCurrencies.*
import com.tangem.tap.domain.walletCurrencies.di.*
import com.tangem.tap.domain.walletStores.*
import com.tangem.tap.domain.walletStores.di.*
import com.tangem.tap.domain.walletStores.repository.*
import com.tangem.tap.domain.walletStores.repository.di.*
import android.app.Application
import android.content.Context
import android.content.pm.PackageManager
import coil.ImageLoader
import coil.ImageLoaderFactory
import com.tangem.Log
import com.tangem.LogFormat
import com.tangem.blockchain.common.BlockchainSdkConfig
import com.tangem.blockchain.common.WalletManagerFactory
import com.tangem.blockchain.network.BlockchainSdkRetrofitBuilder
import com.tangem.core.analytics.Analytics
import com.tangem.core.featuretoggle.manager.FeatureTogglesManager
import com.tangem.data.source.preferences.PreferencesDataSource
import com.tangem.datasource.api.common.MoshiConverter
import com.tangem.datasource.asset.AssetReader
import com.tangem.datasource.config.ConfigManager
import com.tangem.datasource.config.FeaturesLocalLoader
import com.tangem.datasource.config.models.Config
import com.tangem.datasource.connection.NetworkConnectionManager
import com.tangem.domain.DomainLayer
import com.tangem.domain.common.LogConfig
import com.tangem.feature.learn2earn.domain.api.Learn2earnInteractor
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
import com.tangem.tap.common.analytics.AnalyticsFactory
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
import com.tangem.tap.common.analytics.handlers.amplitude.AmplitudeAnalyticsHandler
import com.tangem.tap.common.analytics.handlers.appsFlyer.AppsFlyerAnalyticsHandler
import com.tangem.tap.common.analytics.handlers.firebase.FirebaseAnalyticsHandler
import com.tangem.tap.common.analytics.topup.TopUpController
import com.tangem.tap.common.chat.ChatManager
import com.tangem.tap.common.feedback.AdditionalFeedbackInfo
import com.tangem.tap.common.feedback.FeedbackManager
import com.tangem.tap.common.images.createCoilImageLoader
import com.tangem.tap.common.log.TangemLogCollector
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.appReducer
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.common.shop.TangemShopService
import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager
import com.tangem.tap.domain.tokens.UserTokensRepository
import com.tangem.tap.domain.totalBalance.TotalFiatBalanceCalculator
import com.tangem.tap.domain.totalBalance.di.provideDefaultImplementation
import com.tangem.tap.domain.walletCurrencies.WalletCurrenciesManager
import com.tangem.tap.domain.walletCurrencies.di.provideDefaultImplementation
import com.tangem.tap.domain.walletStores.WalletStoresManager
import com.tangem.tap.domain.walletStores.di.provideDefaultImplementation
import com.tangem.tap.domain.walletStores.repository.WalletAmountsRepository
import com.tangem.tap.domain.walletStores.repository.WalletManagersRepository
import com.tangem.tap.domain.walletStores.repository.WalletStoresRepository
import com.tangem.tap.domain.walletStores.repository.di.provideDefaultImplementation
import com.tangem.tap.domain.walletconnect.WalletConnectRepository
import com.tangem.tap.domain.walletconnect2.domain.*
import com.tangem.tap.features.customtoken.api.featuretoggles.*
import com.tangem.tap.proxy.*
import com.tangem.tap.proxy.redux.*
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectSessionsRepository
import com.tangem.tap.features.customtoken.api.featuretoggles.CustomTokenFeatureToggles
import com.tangem.tap.proxy.AppStateHolder
import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.wallet.BuildConfig
import dagger.hilt.android.*
import kotlinx.coroutines.*
import okhttp3.logging.*
import org.rekotlin.*
import timber.log.*
import javax.inject.*
import dagger.hilt.android.HiltAndroidApp
import kotlinx.coroutines.runBlocking
import okhttp3.logging.HttpLoggingInterceptor
import org.rekotlin.Store
import timber.log.Timber
import javax.inject.Inject
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectRepository as WalletConnect2Repository
lateinit var store: Store<AppState>
@ -136,6 +144,9 @@ class TapApplication : Application(), ImageLoaderFactory {
@Inject
lateinit var walletConnectSessionsRepository: WalletConnectSessionsRepository
@Inject
lateinit var learn2ernInteractor: Learn2earnInteractor
override fun onCreate() {
super.onCreate()
@ -189,8 +200,9 @@ class TapApplication : Application(), ImageLoaderFactory {
appStateHolder.userTokensRepository = userTokensRepository
appStateHolder.walletStoresManager = walletStoresManager
scope.launch {
runBlocking {
featureTogglesManager.init()
learn2ernInteractor.init()
}
initTopUpController()

View file

@ -12,26 +12,38 @@ import androidx.compose.ui.platform.ComposeView
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import com.tangem.core.analytics.Analytics
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.learn2earn.presentation.Learn2earnViewModel
import com.tangem.tap.common.analytics.events.IntroductionProcess
import com.tangem.tap.common.redux.navigation.AppScreen
import com.tangem.tap.common.redux.navigation.NavigationAction
import com.tangem.tap.features.home.compose.StoriesScreen
import com.tangem.tap.features.home.redux.HomeAction
import com.tangem.tap.features.home.redux.HomeState
import com.tangem.tap.features.home.redux.Stories
import com.tangem.tap.features.tokens.legacy.redux.TokensAction
import com.tangem.tap.store
import dagger.hilt.android.AndroidEntryPoint
import org.rekotlin.StoreSubscriber
@AndroidEntryPoint
class HomeFragment : Fragment(), StoreSubscriber<HomeState> {
private var homeState: MutableState<HomeState> = mutableStateOf(store.state.homeState)
private val learn2earnViewModel by viewModels<Learn2earnViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
store.dispatch(HomeAction.OnCreate)
store.dispatch(HomeAction.Init)
if (learn2earnViewModel.isNeedToShowViewOnStoriesScreen()) {
store.dispatch(HomeAction.InsertStory(position = 0, Stories.OneInchPromo))
// re init homeState after inserting learn2earn story
homeState = mutableStateOf(store.state.homeState)
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
@ -79,6 +91,9 @@ class HomeFragment : Fragment(), StoreSubscriber<HomeState> {
private fun ScreenContent() {
StoriesScreen(
homeState,
onLearn2earnClick = {
learn2earnViewModel.onStoriesClick()
},
onScanButtonClick = {
Analytics.send(IntroductionProcess.ButtonScanCard())
store.dispatch(HomeAction.ReadCard())

View file

@ -26,7 +26,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.learn2earn.presentation.ui.OneInchStoriesScreen
import com.tangem.feature.learn2earn.presentation.ui.StoriesScreen
import com.tangem.tap.features.home.compose.content.*
import com.tangem.tap.features.home.compose.views.HomeButtons
import com.tangem.tap.features.home.compose.views.StoriesProgressBar
@ -39,6 +39,7 @@ import kotlin.math.max
@Composable
fun StoriesScreen(
homeState: MutableState<HomeState>,
onLearn2earnClick: () -> Unit,
onScanButtonClick: () -> Unit,
onShopButtonClick: () -> Unit,
onSearchTokensClick: () -> Unit,
@ -152,7 +153,7 @@ fun StoriesScreen(
colorFilter = if (currentStory.isDarkBackground) null else ColorFilter.tint(Color.Black),
)
when (currentStory) {
Stories.OneInchPromo -> OneInchStoriesScreen({})
Stories.OneInchPromo -> StoriesScreen(onLearn2earnClick)
Stories.TangemIntro -> FirstStoriesContent(isPaused, currentStory.duration) { hideContent.value = it }
Stories.RevolutionaryWallet -> StoriesRevolutionaryWallet(currentStory.duration)
Stories.UltraSecureBackup -> StoriesUltraSecureBackup(isPaused, currentStory.duration)
@ -215,6 +216,7 @@ fun StoriesScreen(
@Composable
private fun StoriesScreenPreview() {
StoriesScreen(
onLearn2earnClick = {},
onScanButtonClick = {},
onShopButtonClick = {},
onSearchTokensClick = {},

View file

@ -11,6 +11,8 @@ sealed class HomeAction : Action {
object OnCreate : HomeAction()
object Init : HomeAction()
data class InsertStory(val position: Int, val story: Stories) : HomeAction()
data class ReadCard(
val analyticsEvent: AnalyticsEvent? = Basic.CardWasScanned(AnalyticsParam.ScannedFrom.Introduction),
) : HomeAction()

View file

@ -12,6 +12,13 @@ private fun internalReduce(action: Action, state: AppState): HomeState {
var state = state.homeState
when (action) {
is HomeAction.InsertStory -> {
state = state.copy(
stories = state.stories.toMutableList().apply {
add(action.position, action.story)
},
)
}
is HomeAction.ScanInProgress -> {
state = state.copy(scanInProgress = action.scanInProgress)
}

View file

@ -11,7 +11,8 @@ data class HomeState(
val stories: List<Stories> = initDefaultStories(),
) : StateType {
val firstStory: Stories = stories[0]
val firstStory: Stories
get() = stories[0]
val btnScanStateInProgress: Boolean
get() = btnScanState.progressState == ProgressState.Loading
@ -20,7 +21,6 @@ data class HomeState(
companion object {
fun initDefaultStories(): List<Stories> = listOf(
Stories.OneInchPromo,
Stories.TangemIntro,
Stories.RevolutionaryWallet,
Stories.UltraSecureBackup,

View file

@ -1,8 +1,10 @@
package com.tangem.tap.features.welcome.redux
import android.content.Intent
import com.tangem.common.*
import com.tangem.common.core.TangemSdkError
import com.tangem.common.doOnFailure
import com.tangem.common.doOnResult
import com.tangem.common.doOnSuccess
import com.tangem.common.flatMap
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.tap.*
import com.tangem.tap.common.analytics.events.AnalyticsParam
@ -17,7 +19,6 @@ import com.tangem.tap.domain.model.builders.UserWalletBuilder
import com.tangem.tap.domain.scanCard.ScanCardProcessor
import com.tangem.tap.domain.userWalletList.unlockIfLockable
import com.tangem.tap.features.intentHandler.handlers.WalletConnectLinkIntentHandler
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError
import com.tangem.tap.features.signin.redux.SignInAction
import kotlinx.coroutines.launch
import org.rekotlin.Middleware
@ -98,15 +99,6 @@ internal class WelcomeMiddleware {
}
}
private fun handleInitialIntent(intent: Intent?) {
val isBackgroundScanNotHandled = !intentHandler.handleBackgroundScan(intent, hasSavedUserWallets = true)
val hasNotIncompletedBackup = !backupService.hasIncompletedBackup
if (isBackgroundScanNotHandled && hasNotIncompletedBackup) {
store.dispatchOnMain(WelcomeAction.ProceedWithBiometrics)
}
}
private suspend inline fun scanCardInternal(crossinline onCardScanned: suspend (ScanResponse) -> Unit) {
tangemSdkManager.setAccessCodeRequestPolicy(
useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes,

View file

@ -46,8 +46,8 @@
android:id="@+id/cl_wallet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:clipChildren="false"
android:clipToPadding="false"
android:paddingBottom="92dp">
<ImageView
@ -113,6 +113,15 @@
android:paddingTop="8dp"
app:layout_constraintTop_toBottomOf="@id/rv_warning_messages">
<FrameLayout
android:id="@+id/fl_learn_to_earn_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp" />
<include
android:id="@+id/l_wallet_rescan_warning"
layout="@layout/layout_wallet_rescan_warning"
@ -219,8 +228,8 @@
android:id="@+id/btn_add_token"
style="@style/TapPrimaryButton"
android:layout_width="match_parent"
android:layout_marginTop="8dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:text="@string/main_manage_tokens"
android:visibility="gone"