diff --git a/app/build.gradle b/app/build.gradle index 3a4885cc13..74cb181d5c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,18 +6,21 @@ apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.firebase.crashlytics' android { - compileSdkVersion 30 + compileSdkVersion 31 defaultConfig { applicationId "com.tangem.wallet" versionCode project.hasProperty('versionCode') ? project.property('versionCode') as int : 1 versionName project.hasProperty('versionName') ? project.property('versionName') : "1.0.0.-SNAPSHOT" minSdkVersion 21 - targetSdkVersion 30 + targetSdkVersion 31 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } androidExtensions { experimental = true } + buildFeatures { + compose true + } buildTypes { release { debuggable false @@ -47,12 +50,14 @@ android { kotlinOptions { jvmTarget = JavaVersion.VERSION_1_8.toString() } - compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 coreLibraryDesugaringEnabled false } + composeOptions { + kotlinCompilerExtensionVersion '1.1.0' + } packagingOptions { exclude 'lib/x86_64/darwin/libscrypt.dylib' exclude 'lib/x86_64/freebsd/libscrypt.so' @@ -67,13 +72,13 @@ repositories { dependencies { implementation fileTree(include: ['*.aar'], dir: 'libs') - implementation 'androidx.core:core-ktx:1.6.0' - implementation 'androidx.appcompat:appcompat:1.3.1' - implementation 'androidx.fragment:fragment-ktx:1.3.6' - implementation 'androidx.constraintlayout:constraintlayout:2.1.1' - implementation 'com.google.android.material:material:1.4.0' - implementation "androidx.core:core-ktx:1.6.0" - implementation 'com.google.android.play:core:1.10.2' + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.1' + implementation 'androidx.fragment:fragment-ktx:1.4.1' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + implementation 'com.google.android.material:material:1.5.0' + implementation "androidx.core:core-ktx:1.7.0" + implementation 'com.google.android.play:core:1.10.3' implementation 'com.google.android.play:core-ktx:1.8.1' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' @@ -138,6 +143,13 @@ dependencies { // Google Pay implementation 'com.google.android.gms:play-services-wallet:19.1.0' + //Compose + implementation 'androidx.activity:activity-compose:1.4.0' + implementation 'androidx.compose.material:material:1.1.0' + implementation 'androidx.compose.animation:animation:1.1.0' + implementation 'androidx.compose.ui:ui-tooling:1.1.0' + implementation "com.google.accompanist:accompanist-appcompat-theme:0.23.0" + testImplementation 'junit:junit:4.13.2' testImplementation "com.google.truth:truth:1.1.3" androidTestImplementation 'androidx.test.ext:junit:1.1.3' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b38eacf816..4dfca87b23 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -44,6 +44,7 @@ android:value="true" /> () { +class HomeFragment : Fragment(R.layout.fragment_home), StoreSubscriber { - private lateinit var btnScanCard: ViewStateWidget - - override fun getOnboardingTopContainerId(): Int = R.layout.layout_onboarding_home_top + var homeState: MutableState = mutableStateOf(store.state.homeState) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val inflater = TransitionInflater.from(requireContext()) - exitTransition = inflater.inflateTransition(R.transition.fade) store.dispatch(HomeAction.Init) } @@ -39,50 +29,36 @@ class HomeFragment : BaseOnboardingFragment() { store.dispatch(BackupAction.CheckForUnfinishedBackup) - toolbar.hide() - val shareTransition = FragmentShareTransition( - listOf( - ShareElement(imv_front_card, ShareElement.imvFrontCard), - ShareElement(imv_back_card, ShareElement.imvBackCard), - ShareElement(bg_circle_large), - ShareElement(bg_circle_medium), - ShareElement(bg_circle_min), - ), - FrontCardEnterTransition(), - FrontCardExitTransition() - ) - - store.dispatch(HomeAction.SetFragmentShareTransition(shareTransition)) - - tv_header.setText(R.string.home_welcome_header) - tv_body.setText(R.string.home_welcome_body) - - btn_main_action.setText(R.string.home_button_scan) - btn_main_action.setOnClickListener { store.dispatch(HomeAction.ReadCard) } - btn_alternative_action.setText(R.string.home_button_get_new_card) - btn_alternative_action.setOnClickListener { store.dispatch(HomeAction.GoToShop) } - - btnScanCard = IndeterminateProgressButtonWidget(btn_main_action, progress) + getView()?.findViewById(R.id.cv_stories)?.setContent { + AppCompatTheme { + StoriesScreen( + homeState, + onScanButtonClick = { store.dispatch(HomeAction.ReadCard) }, + onShopButtonClick = { store.dispatch(HomeAction.GoToShop) } + ) + } + } } - override fun subscribeToStore() { + override fun onStart() { + super.onStart() store.subscribe(this) { state -> state.skipRepeats { oldState, newState -> oldState.homeState == newState.homeState }.select { it.homeState } } - storeSubscribersList.add(this) } + override fun onStop() { + super.onStop() + store.unsubscribe(this) + } + + override fun newState(state: HomeState) { if (activity == null) return - btnScanCard.changeState(state.btnScanState.progressState) - btnScanCard.mainView.isEnabled = state.btnScanState.enabled + homeState.value = state } - override fun onDestroyView() { - store.dispatch(HomeAction.SetFragmentShareTransition(null)) - super.onDestroyView() - } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/home/compose/FirstStoriesContent.kt b/app/src/main/java/com/tangem/tap/features/home/compose/FirstStoriesContent.kt new file mode 100644 index 0000000000..9dab20b43f --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/home/compose/FirstStoriesContent.kt @@ -0,0 +1,146 @@ +package com.tangem.tap.features.home.compose + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.core.Animatable +import androidx.compose.animation.core.LinearEasing +import androidx.compose.animation.core.tween +import androidx.compose.animation.scaleIn +import androidx.compose.animation.slideInVertically +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.* +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.tangem.wallet.R + +@OptIn(ExperimentalAnimationApi::class) +@Composable +fun FirstStoriesContent( + paused: Boolean, duration: Int = 8_000, + hideContent: (Boolean) -> Unit +) { + val screenState = remember { mutableStateOf(StartingScreenState.INIT) } + val progress = remember { Animatable(0f) } + + LaunchedEffect(paused) { + if (paused) { + progress.stop() + } else { + progress.animateTo( + targetValue = 2f, + animationSpec = tween( + durationMillis = duration, + easing = LinearEasing + ) + ) + } + } + + when (progress.value) { + in 0f..0.2f -> screenState.value = StartingScreenState.INIT + in 0.2f..0.3f -> screenState.value = StartingScreenState.BUY + in 0.3f..0.4f -> screenState.value = StartingScreenState.STORE + in 0.4f..0.5f -> screenState.value = StartingScreenState.SEND + in 0.5f..0.6f -> screenState.value = StartingScreenState.PAY + in 0.6f..0.7f -> screenState.value = StartingScreenState.EXCHANGE + in 0.7f..0.8f -> screenState.value = StartingScreenState.BORROW + in 0.8f..1f -> screenState.value = StartingScreenState.LEND + in 1f..1.2f -> screenState.value = StartingScreenState.SHOW_CARD + in 1.2f..2f -> screenState.value = StartingScreenState.MEET_TANGEM + } + + if (screenState.value == StartingScreenState.INIT) hideContent(true) + if (screenState.value == StartingScreenState.BUY) hideContent(false) + + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = + Modifier + .fillMaxSize(), + ) { + + val text = when (screenState.value) { + StartingScreenState.INIT -> null + StartingScreenState.BUY -> R.string.story_meet_buy + StartingScreenState.STORE -> R.string.story_meet_store + StartingScreenState.SEND -> R.string.story_meet_send + StartingScreenState.PAY -> R.string.story_meet_pay + StartingScreenState.EXCHANGE -> R.string.story_meet_exchange + StartingScreenState.BORROW -> R.string.story_meet_borrow + StartingScreenState.LEND -> R.string.story_meet_lend + StartingScreenState.SHOW_CARD -> R.string.story_meet_title + StartingScreenState.MEET_TANGEM -> R.string.story_meet_title + } + + if (screenState.value != StartingScreenState.MEET_TANGEM) { + Text( + text = text?.let { stringResource(text) } ?: "", + fontSize = 60.sp, + fontWeight = FontWeight.SemiBold, + modifier = Modifier + .padding(start = 40.dp, end = 40.dp) + .alpha(if (screenState.value == StartingScreenState.SHOW_CARD) 0f else 1f), + color = Color.White, + textAlign = TextAlign.Center, + + ) + } + + AnimatedVisibility( + visible = screenState.value == StartingScreenState.MEET_TANGEM, + enter = slideInVertically() { it / 2 } + ) { + Text( + text = text?.let { stringResource(text) } ?: "", + fontSize = 60.sp, + fontWeight = FontWeight.SemiBold, + modifier = Modifier + .padding(start = 40.dp, end = 40.dp), + color = Color.White, + textAlign = TextAlign.Center + ) + } + + AnimatedVisibility( + visible = screenState.value == StartingScreenState.SHOW_CARD || + screenState.value == StartingScreenState.MEET_TANGEM, + enter = scaleIn(initialScale = 3f) + ) { + Image( + painter = painterResource( + id = R.drawable.meet_tangem + ), + contentDescription = null, + contentScale = ContentScale.FillWidth, + modifier = Modifier.fillMaxWidth() + ) + } + } +} + +enum class StartingScreenState { + INIT, BUY, STORE, SEND, PAY, EXCHANGE, BORROW, LEND, SHOW_CARD, MEET_TANGEM +} + + +@Preview +@Composable +fun Stories1Preview() { + FirstStoriesContent(false, 7_000) {} +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/home/compose/HomeButtons.kt b/app/src/main/java/com/tangem/tap/features/home/compose/HomeButtons.kt new file mode 100644 index 0000000000..0c223b4096 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/home/compose/HomeButtons.kt @@ -0,0 +1,66 @@ +package com.tangem.tap.features.home.compose + +import androidx.compose.foundation.layout.* +import androidx.compose.material.Button +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.tangem.wallet.R +import androidx.compose.foundation.layout.fillMaxWidth as fillMaxWidth1 + +@Composable +fun HomeButtons( + isDarkBackground: Boolean, modifier: Modifier = Modifier, + onScanButtonClick: () -> Unit, + onShopButtonClick: () -> Unit +) { + val darkColorBackground = Color(0xFF26292E) + val darkColorButton = Color(0xFF080C10) + + Row( + horizontalArrangement = Arrangement.SpaceEvenly, + modifier = modifier.fillMaxWidth1() + ) { + Spacer(modifier = Modifier.size(16.dp)) + Button( + modifier = Modifier + .weight(1f) + .height(42.dp), + onClick = onScanButtonClick, + colors = ButtonDefaults.textButtonColors( + backgroundColor = if (isDarkBackground) darkColorBackground else Color.White, + contentColor = if (isDarkBackground) Color.White else darkColorButton + ) + ) { + Text( + text = stringResource(id = R.string.home_button_scan), + fontWeight = FontWeight.Medium, + fontSize = 16.sp + ) + } + Spacer(modifier = Modifier.size(8.dp)) + Button( + modifier = Modifier + .weight(1f) + .height(42.dp), + onClick = onShopButtonClick, + colors = ButtonDefaults.textButtonColors( + backgroundColor = if (isDarkBackground) Color.White else darkColorBackground, + contentColor = if (isDarkBackground) darkColorButton else Color.White + ) + ) { + Text( + text = stringResource(id = R.string.home_button_order), + fontWeight = FontWeight.Medium, + fontSize = 16.sp + ) + } + Spacer(modifier = Modifier.size(16.dp)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/home/compose/Stories.kt b/app/src/main/java/com/tangem/tap/features/home/compose/Stories.kt new file mode 100644 index 0000000000..59b7355b6c --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/home/compose/Stories.kt @@ -0,0 +1,145 @@ +package com.tangem.tap.features.home.compose + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.foundation.layout.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.tangem.tap.features.home.redux.HomeState +import com.tangem.tap.features.wallet.redux.ProgressState +import com.tangem.wallet.R +import kotlin.math.max + +@Composable +fun StoriesScreen( + homeState: MutableState = mutableStateOf(HomeState()), + onScanButtonClick: () -> Unit, + onShopButtonClick: () -> Unit +) { + val steps = 6 + val stepDuration = 8_000 + + val currentStep = remember { mutableStateOf(1) } + + val isDarkBackground = currentStep.value !in 3..5 + + val goToPreviousScreen = { + currentStep.value = max(1, currentStep.value - 1) + } + val goToNextScreen = { + currentStep.value = if (currentStep.value < steps) currentStep.value + 1 else 1 + } + + val isPressed = remember { mutableStateOf(false) } + val needsToBePaused = + remember(homeState) { mutableStateOf(homeState.value.btnScanState.progressState == ProgressState.Loading) } + val pause = isPressed.value || needsToBePaused.value + + val hideContent = remember { mutableStateOf(true) } + + Box( + Modifier + .fillMaxSize() + .background(Color(0xFF090E13)) + .pointerInput(Unit) { + val maxWidth = this.size.width + detectTapGestures( + onPress = { + val pressStartTime = System.currentTimeMillis() + isPressed.value = true + this.tryAwaitRelease() + val pressEndTime = System.currentTimeMillis() + val totalPressTime = pressEndTime - pressStartTime + if (totalPressTime < 200) { + val isTapOnRightTwoTiers = (it.x > (maxWidth / 2)) + if (isTapOnRightTwoTiers) { + goToNextScreen() + } else { + goToPreviousScreen() + } + } + isPressed.value = false + }, + ) + } + ) { + if (!isDarkBackground) { + Image( + painter = painterResource(id = R.drawable.ic_overlay), + contentDescription = null, + modifier = Modifier + .fillMaxSize(), + contentScale = ContentScale.FillBounds + ) + } + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = + Modifier + .fillMaxSize() + ) { + Spacer(modifier = Modifier.size(24.dp)) + StoriesProgressBar( + steps = steps, + currentStep = currentStep.value, +// paused = isPressed.value, + stepDuration = stepDuration, + paused = pause, + onStepFinished = goToNextScreen, + ) + Image( + painter = painterResource(id = R.drawable.ic_tangem_logo), + contentDescription = null, + contentScale = ContentScale.FillHeight, + modifier = Modifier + .padding(start = 16.dp, top = 10.dp) + .height(17.dp) + .alpha(if (hideContent.value) 0f else 1f) + .align(Alignment.Start), + colorFilter = if (isDarkBackground) null else ColorFilter.tint(Color.Black) + ) + } + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = Modifier.fillMaxWidth() + ) { + when (currentStep.value) { + 1 -> FirstStoriesContent(pause, stepDuration) { hideContent.value = it } + 2 -> StoriesRevolutionaryWallet() + 3 -> StoriesUltraSecureBackup() + 4 -> StoriesThousandsOfCurrencies() + 5 -> StoriesWeb3() + 6 -> StoriesWalletForEveryone() + } + } + HomeButtons( + isDarkBackground = isDarkBackground, + modifier = Modifier + .align(Alignment.BottomCenter) + .padding(37.dp), + onScanButtonClick = onScanButtonClick, + onShopButtonClick = onShopButtonClick + ) + } +} + + +@Preview +@Composable +fun InstagramScreenPreview() { + StoriesScreen(onScanButtonClick = {}, onShopButtonClick = {}) +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/home/compose/StoriesGeneralContent.kt b/app/src/main/java/com/tangem/tap/features/home/compose/StoriesGeneralContent.kt new file mode 100644 index 0000000000..3f9ba4c0a4 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/home/compose/StoriesGeneralContent.kt @@ -0,0 +1,120 @@ +package com.tangem.tap.features.home.compose + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.* +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.tangem.wallet.R + +@Composable +fun StoriesGeneralContent( + titleText: String, + subtitleText: String, + imageSource: Int?, + isDarkBackground: Boolean, + imageComposable: (() -> Unit)? = null, + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = + Modifier + .fillMaxWidth() + .fillMaxHeight(), + ) { + + Text( + text = titleText, + fontSize = 32.sp, + fontWeight = FontWeight.SemiBold, + modifier = Modifier + .padding(start = 40.dp, end = 40.dp), + color = if (isDarkBackground) Color.White else Color(0xFF090E13), + textAlign = TextAlign.Center + ) + + Spacer(modifier = Modifier.size(16.dp)) + + Text( + text = subtitleText, + fontSize = 20.sp, + fontWeight = FontWeight.Normal, + modifier = Modifier + .padding(start = 40.dp, end = 40.dp), + color = Color(0xFFA6AAAD), + textAlign = TextAlign.Center + ) + + Spacer(modifier = Modifier.size(25.dp)) + + if (imageSource != null) { + Image( + painter = painterResource(id = imageSource), + contentDescription = null, + contentScale = ContentScale.FillWidth, + modifier = Modifier.fillMaxWidth() + ) + } + imageComposable?.invoke() + } +} + +@Composable +fun StoriesRevolutionaryWallet() { + StoriesGeneralContent( + titleText = stringResource(id = R.string.story_awe_title), + subtitleText = stringResource(id = R.string.story_awe_description), + imageSource = R.drawable.revolutionary_wallet, + isDarkBackground = true + ) +} + +@Composable +fun StoriesUltraSecureBackup() { + StoriesGeneralContent( + titleText = stringResource(id = R.string.story_backup_title), + subtitleText = stringResource(id = R.string.story_backup_description), + imageSource = R.drawable.floating_cards, + isDarkBackground = false + ) +} + +@Composable +fun StoriesThousandsOfCurrencies() { + StoriesGeneralContent( + titleText = stringResource(id = R.string.story_currencies_title), + subtitleText = stringResource(id = R.string.story_currencies_description), + imageSource = R.drawable.thousands_of_currencies, + isDarkBackground = false + ) +} + +@Composable +fun StoriesWeb3() { + StoriesGeneralContent( + titleText = stringResource(id = R.string.story_web3_title), + subtitleText = stringResource(id = R.string.story_web3_description), + imageSource = R.drawable.web_3, + isDarkBackground = false + ) +} + +@Composable +fun StoriesWalletForEveryone() { + StoriesGeneralContent( + titleText = stringResource(id = R.string.story_finish_title), + subtitleText = stringResource(id = R.string.story_finish_description), + imageSource = R.drawable.wallet_for_everyone, + isDarkBackground = true + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/home/compose/StoriesProgressBar.kt b/app/src/main/java/com/tangem/tap/features/home/compose/StoriesProgressBar.kt new file mode 100644 index 0000000000..b8dd83e070 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/home/compose/StoriesProgressBar.kt @@ -0,0 +1,80 @@ +package com.tangem.tap.features.home.compose + +import androidx.compose.animation.core.Animatable +import androidx.compose.animation.core.LinearEasing +import androidx.compose.animation.core.tween +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp + +@Composable +fun StoriesProgressBar( + steps: Int, + currentStep: Int, + paused: Boolean = false, + stepDuration: Int = 8_000, + onStepFinished: () -> Unit = {}, +) { + val progress = remember(currentStep) { Animatable(0f) } + + LaunchedEffect(paused, currentStep) { + if (paused) { + progress.stop() + } else { + progress.animateTo( + targetValue = 1f, + animationSpec = tween( + durationMillis = (stepDuration * (1f - progress.value)).toInt(), + easing = LinearEasing + ) + ) + progress.snapTo(0f) + onStepFinished() + } + + } + + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier +// .height() + .padding(start = 9.dp, end = 9.dp, top = 16.dp), + ) { + for (index in 1..steps) { + Row( + modifier = Modifier + .height(2.dp) + .weight(1f) + .background(Color.White.copy(alpha = 0.4f)) + ) { + Box( + modifier = Modifier + .background(Color.White) + .fillMaxHeight().let { + when (index) { + currentStep -> it.fillMaxWidth(progress.value) + in 0..currentStep -> it.fillMaxWidth(1f) + else -> it + } + }, + ) {} + } + if (index != steps) { + Spacer(modifier = Modifier.width(4.dp)) + } + } + } +} + +@Preview +@Composable +fun StoriesProgressBarPreview() { + StoriesProgressBar(steps = 3, currentStep = 2, paused = false) { } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt index 14f762f6c4..d14d4cf71b 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt @@ -1,7 +1,6 @@ package com.tangem.tap.features.home.redux import com.tangem.tap.common.entities.IndeterminateProgressButton -import com.tangem.tap.common.redux.navigation.FragmentShareTransition import org.rekotlin.Action sealed class HomeAction : Action { @@ -10,10 +9,9 @@ sealed class HomeAction : Action { object GoToShop : HomeAction() // internal - data class ShouldScanCardOnResume(val shouldScanCard: Boolean):HomeAction() + data class ShouldScanCardOnResume(val shouldScanCard: Boolean) : HomeAction() object Init : HomeAction() - data class SetFragmentShareTransition(val shareTransition: FragmentShareTransition?) : HomeAction() data class SetTermsOfUseState(val isDisclaimerAccepted: Boolean) : HomeAction() data class ChangeScanCardButtonState(val state: IndeterminateProgressButton) : HomeAction() diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt index 95eada77e7..fd80724118 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt @@ -73,14 +73,14 @@ private fun handleReadCard() { if (OnboardingHelper.isOnboardingCase(scanResponse)) { val navigateTo = OnboardingHelper.whereToNavigate(scanResponse) store.dispatch(GlobalAction.Onboarding.Start(scanResponse)) - navigateTo(navigateTo, store.state.homeState.shareTransition) + navigateTo(navigateTo) } else { scope.launch { store.onCardScanned(scanResponse) withMainContext { if (scanResponse.twinsIsTwinned() && !preferencesStorage.wasTwinsOnboardingShown()) { store.dispatch(TwinCardsAction.SetStepOfScreen(TwinCardsStep.WelcomeOnly)) - navigateTo(AppScreen.OnboardingTwins, store.state.homeState.shareTransition) + navigateTo(AppScreen.OnboardingTwins) } else { navigateTo(AppScreen.Wallet, null) } @@ -98,7 +98,7 @@ private fun changeButtonState(state: ButtonState) { store.dispatch(HomeAction.ChangeScanCardButtonState(btnState)) } -private fun navigateTo(screen: AppScreen, transition: FragmentShareTransition?) { +private fun navigateTo(screen: AppScreen, transition: FragmentShareTransition? = null) { post(DELAY_SDK_DIALOG_CLOSE) { changeButtonState(ButtonState.ENABLED) store.dispatch(NavigationAction.NavigateTo(screen, transition)) diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeReducer.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeReducer.kt index d4f11f31f9..f4a7a9d407 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeReducer.kt @@ -15,9 +15,6 @@ private fun internalReduce(action: Action, state: AppState): HomeState { var state = state.homeState when (action) { - is HomeAction.SetFragmentShareTransition -> { - state = state.copy(shareTransition = action.shareTransition) - } is HomeAction.ShouldScanCardOnResume -> { state = state.copy(shouldScanCardOnResume = action.shouldScanCard) } diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeState.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeState.kt index 8c9949cf4c..38b19013d8 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeState.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeState.kt @@ -1,12 +1,10 @@ package com.tangem.tap.features.home.redux import com.tangem.tap.common.entities.IndeterminateProgressButton -import com.tangem.tap.common.redux.navigation.FragmentShareTransition import com.tangem.tap.features.send.redux.states.ButtonState import org.rekotlin.StateType data class HomeState( val shouldScanCardOnResume: Boolean = false, - val shareTransition: FragmentShareTransition? = null, val btnScanState: IndeterminateProgressButton = IndeterminateProgressButton(ButtonState.ENABLED), ) : StateType \ No newline at end of file diff --git a/app/src/main/res/drawable-hdpi/floating_cards.png b/app/src/main/res/drawable-hdpi/floating_cards.png new file mode 100644 index 0000000000..6f8eba908f Binary files /dev/null and b/app/src/main/res/drawable-hdpi/floating_cards.png differ diff --git a/app/src/main/res/drawable-hdpi/meet_tangem.png b/app/src/main/res/drawable-hdpi/meet_tangem.png new file mode 100644 index 0000000000..25f2d5a3ba Binary files /dev/null and b/app/src/main/res/drawable-hdpi/meet_tangem.png differ diff --git a/app/src/main/res/drawable-hdpi/revolutionary_wallet.png b/app/src/main/res/drawable-hdpi/revolutionary_wallet.png new file mode 100644 index 0000000000..f4f384a54d Binary files /dev/null and b/app/src/main/res/drawable-hdpi/revolutionary_wallet.png differ diff --git a/app/src/main/res/drawable-hdpi/thousands_of_currencies.png b/app/src/main/res/drawable-hdpi/thousands_of_currencies.png new file mode 100644 index 0000000000..af3bf1ca51 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/thousands_of_currencies.png differ diff --git a/app/src/main/res/drawable-hdpi/wallet_for_everyone.png b/app/src/main/res/drawable-hdpi/wallet_for_everyone.png new file mode 100644 index 0000000000..6eec2f53dd Binary files /dev/null and b/app/src/main/res/drawable-hdpi/wallet_for_everyone.png differ diff --git a/app/src/main/res/drawable-mdpi/floating_cards.png b/app/src/main/res/drawable-mdpi/floating_cards.png new file mode 100644 index 0000000000..9ff5cb944a Binary files /dev/null and b/app/src/main/res/drawable-mdpi/floating_cards.png differ diff --git a/app/src/main/res/drawable-mdpi/meet_tangem.png b/app/src/main/res/drawable-mdpi/meet_tangem.png new file mode 100644 index 0000000000..ef04e35830 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/meet_tangem.png differ diff --git a/app/src/main/res/drawable-mdpi/revolutionary_wallet.png b/app/src/main/res/drawable-mdpi/revolutionary_wallet.png new file mode 100644 index 0000000000..4dba3bffa4 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/revolutionary_wallet.png differ diff --git a/app/src/main/res/drawable-mdpi/thousands_of_currencies.png b/app/src/main/res/drawable-mdpi/thousands_of_currencies.png new file mode 100644 index 0000000000..4f448c7df8 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/thousands_of_currencies.png differ diff --git a/app/src/main/res/drawable-mdpi/wallet_for_everyone.png b/app/src/main/res/drawable-mdpi/wallet_for_everyone.png new file mode 100644 index 0000000000..9ec8c92210 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/wallet_for_everyone.png differ diff --git a/app/src/main/res/drawable-mdpi/web_3.png b/app/src/main/res/drawable-mdpi/web_3.png new file mode 100644 index 0000000000..df3245ff41 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/web_3.png differ diff --git a/app/src/main/res/drawable-xhdpi/floating_cards.png b/app/src/main/res/drawable-xhdpi/floating_cards.png new file mode 100644 index 0000000000..3445299a6f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/floating_cards.png differ diff --git a/app/src/main/res/drawable-xhdpi/meet_tangem.png b/app/src/main/res/drawable-xhdpi/meet_tangem.png new file mode 100644 index 0000000000..958f83e0a6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/meet_tangem.png differ diff --git a/app/src/main/res/drawable-xhdpi/revolutionary_wallet.png b/app/src/main/res/drawable-xhdpi/revolutionary_wallet.png new file mode 100644 index 0000000000..e72d2ff281 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/revolutionary_wallet.png differ diff --git a/app/src/main/res/drawable-xhdpi/thousands_of_currencies.png b/app/src/main/res/drawable-xhdpi/thousands_of_currencies.png new file mode 100644 index 0000000000..cd226e8bf3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/thousands_of_currencies.png differ diff --git a/app/src/main/res/drawable-xhdpi/wallet_for_everyone.png b/app/src/main/res/drawable-xhdpi/wallet_for_everyone.png new file mode 100644 index 0000000000..773a3bb463 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/wallet_for_everyone.png differ diff --git a/app/src/main/res/drawable-xhdpi/web_3.png b/app/src/main/res/drawable-xhdpi/web_3.png new file mode 100644 index 0000000000..8af4c9c432 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/web_3.png differ diff --git a/app/src/main/res/drawable-xxhdpi/floating_cards.png b/app/src/main/res/drawable-xxhdpi/floating_cards.png new file mode 100644 index 0000000000..000db85171 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/floating_cards.png differ diff --git a/app/src/main/res/drawable-xxhdpi/meet_tangem.png b/app/src/main/res/drawable-xxhdpi/meet_tangem.png new file mode 100644 index 0000000000..4d5144346d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/meet_tangem.png differ diff --git a/app/src/main/res/drawable-xxhdpi/revolutionary_wallet.png b/app/src/main/res/drawable-xxhdpi/revolutionary_wallet.png new file mode 100644 index 0000000000..83a8bc7963 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/revolutionary_wallet.png differ diff --git a/app/src/main/res/drawable-xxhdpi/thousands_of_currencies.png b/app/src/main/res/drawable-xxhdpi/thousands_of_currencies.png new file mode 100644 index 0000000000..572bb12ae8 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/thousands_of_currencies.png differ diff --git a/app/src/main/res/drawable-xxhdpi/wallet_for_everyone.png b/app/src/main/res/drawable-xxhdpi/wallet_for_everyone.png new file mode 100644 index 0000000000..18b099256b Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/wallet_for_everyone.png differ diff --git a/app/src/main/res/drawable-xxhdpi/web_3.png b/app/src/main/res/drawable-xxhdpi/web_3.png new file mode 100644 index 0000000000..8aa6f0b237 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/web_3.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/floating_cards.png b/app/src/main/res/drawable-xxxhdpi/floating_cards.png new file mode 100644 index 0000000000..81dd5e3119 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/floating_cards.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/meet_tangem.png b/app/src/main/res/drawable-xxxhdpi/meet_tangem.png new file mode 100644 index 0000000000..a84bb7b804 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/meet_tangem.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/revolutionary_wallet.png b/app/src/main/res/drawable-xxxhdpi/revolutionary_wallet.png new file mode 100644 index 0000000000..bc0d94be7f Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/revolutionary_wallet.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/thousands_of_currencies.png b/app/src/main/res/drawable-xxxhdpi/thousands_of_currencies.png new file mode 100644 index 0000000000..5e2406e2c7 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/thousands_of_currencies.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/wallet_for_everyone.png b/app/src/main/res/drawable-xxxhdpi/wallet_for_everyone.png new file mode 100644 index 0000000000..1d99d407ab Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/wallet_for_everyone.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/web_3.png b/app/src/main/res/drawable-xxxhdpi/web_3.png new file mode 100644 index 0000000000..988c52d448 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/web_3.png differ diff --git a/app/src/main/res/drawable/ic_overlay.xml b/app/src/main/res/drawable/ic_overlay.xml new file mode 100644 index 0000000000..586397f855 --- /dev/null +++ b/app/src/main/res/drawable/ic_overlay.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml new file mode 100644 index 0000000000..30dfad0768 --- /dev/null +++ b/app/src/main/res/layout/fragment_home.xml @@ -0,0 +1,11 @@ + + + + + + \ 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 a8830f8137..a46713e187 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -21,6 +21,7 @@ Get ready to tap your \ncard to the back of the \nphone. Tap in Scan card + Order card Yes! Scan it. Scan diff --git a/app/src/main/res/values/strings_untranslated.xml b/app/src/main/res/values/strings_untranslated.xml index 88f7606b83..95656ed819 100644 --- a/app/src/main/res/values/strings_untranslated.xml +++ b/app/src/main/res/values/strings_untranslated.xml @@ -329,4 +329,26 @@ Amount to pay: %s Order card Delivery (Free shipping) + + Meet\nTangem + Buy + Store + Send + Pay + Exchange + Lend + Borrow + Stake + Revolutionary Hardware Wallet + Store your crypto assets secure while keeping private keys contained in your card + Ultra Secure Backup + Up to 3 physical cards to one wallet + Thousands of Currencies + A hardware wallet for your Bitcoin, Ethereum and many more currencies simultaneously – all in one card + Web3 Compatible + Exchange, buy NFT’s, make loans and deposits in more than 100 different decentralized services + The Wallet for Everyone + Use it on the go, anywhere, anytime. No wires or batteries. Just tap the card to your phone when you need your crypto. + +