From b5dde35172c335b77babcb1f0e6eb050a1f95fec Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 26 Jun 2023 20:00:37 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../presentation/Learn2earnRouter.kt | 11 +- .../presentation/Learn2earnViewModel.kt | 168 +++++++++++++++--- .../ui/{GetBonusAlert.kt => GetBonusView.kt} | 56 ++++-- .../presentation/ui/Learn2earnDialogs.kt | 85 +++++++++ .../ui/Learn2earnMainPageScreen.kt | 21 +++ ...esScreen.kt => Learn2earnStoriesScreen.kt} | 7 +- .../presentation/ui/state/Learn2earnState.kt | 68 +++++++ .../presentation/ui/state/StateBuilder.kt | 93 ++++++++++ .../Learn2earnWebViewActivity.kt | 43 ++--- .../webView/Learn2earnWebViewClient.kt | 31 ++++ .../presentation/webView/WebViewViewModel.kt | 38 ++++ .../src/main/res/layout/activity_web_view.xml | 1 + 12 files changed, 545 insertions(+), 77 deletions(-) rename features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/{GetBonusAlert.kt => GetBonusView.kt} (66%) create mode 100644 features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/Learn2earnDialogs.kt create mode 100644 features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/Learn2earnMainPageScreen.kt rename features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/{StoriesScreen.kt => Learn2earnStoriesScreen.kt} (95%) create mode 100644 features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/Learn2earnState.kt create mode 100644 features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/StateBuilder.kt rename features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/{ => webView}/Learn2earnWebViewActivity.kt (55%) create mode 100644 features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewClient.kt create mode 100644 features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/WebViewViewModel.kt diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnRouter.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnRouter.kt index a02d4be651..c845f2a50e 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnRouter.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnRouter.kt @@ -2,6 +2,8 @@ package com.tangem.feature.learn2earn.presentation import android.content.Context import android.content.Intent +import android.net.Uri +import com.tangem.feature.learn2earn.presentation.webView.Learn2earnWebViewActivity /** [REDACTED_AUTHOR] @@ -10,7 +12,12 @@ class Learn2earnRouter( private val context: Context, ) { - fun openWebView() { - context.startActivity(Intent(context, Learn2earnWebViewActivity::class.java)) + fun openWebView(uri: Uri, rawHeaders: ArrayList) { + val intent = Intent(context, Learn2earnWebViewActivity::class.java) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + .putExtra(Learn2earnWebViewActivity.EXTRA_WEB_URI, uri.toString()) + .putStringArrayListExtra(Learn2earnWebViewActivity.EXTRA_WEB_HEADERS, rawHeaders) + + context.startActivity(intent) } } \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt index f39aee6032..8cd6e4536c 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt @@ -1,11 +1,16 @@ package com.tangem.feature.learn2earn.presentation -import android.net.Uri +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.tangem.feature.learn2earn.domain.api.Learn2earnInteractor -import com.tangem.feature.learn2earn.domain.models.RedirectConsequences -import com.tangem.feature.learn2earn.domain.models.WebViewHelper +import com.tangem.feature.learn2earn.domain.api.WebViewResult +import com.tangem.feature.learn2earn.domain.api.WebViewResultHandler +import com.tangem.feature.learn2earn.domain.models.PromotionError +import com.tangem.feature.learn2earn.presentation.ui.state.* +import com.tangem.lib.crypto.models.errors.UserCancelledException import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch @@ -20,39 +25,156 @@ class Learn2earnViewModel @Inject constructor( private val interactor: Learn2earnInteractor, private val router: Learn2earnRouter, private val dispatchers: AppCoroutineDispatcherProvider, -) : ViewModel(), WebViewHelper { +) : ViewModel() { - var webViewUri: Uri = Uri.parse("https://localhost") + var uiState: Learn2earnState by mutableStateOf( + Learn2earnState.init( + uiActions = UiActions( + buttonStoryClick = ::buttonStoryClick, + buttonMainClick = ::buttonMainClick, + ), + ), + ) private set - fun isNeedToShowViewOnStoriesScreen(): Boolean = interactor.isNeedToShowViewOnStoriesScreen() - - fun onStoriesClick() { - webViewUri = interactor.buildUriForStories() - router.openWebView() + init { + uiState = uiState.updateStoriesVisibility(interactor.isNeedToShowViewOnStoriesScreen()) } - fun isNeedToShowViewOnWalletScreen(walletId: String, callback: (Boolean) -> Unit) { + fun onMainScreenCreated() { + updateMainScreenViews() + } + + private fun updateMainScreenViews() { viewModelScope.launch(dispatchers.io) { - val isNeedToShow = interactor.isNeedToShowViewOnWalletScreen(walletId) - withContext(dispatchers.main) { - callback(isNeedToShow) + if (interactor.isNeedToShowViewOnMainScreen()) { + updateUi { + uiState.changeGetBounsDescription(getBonusDescription()) + .updateGetBonusVisibility(isVisible = true) + } + } else { + updateUi { uiState.updateGetBonusVisibility(isVisible = false) } } } } - fun onMainPageClick(walletId: String, cardId: String, cardPubKey: String) { - webViewUri = interactor.buildUriForMainPage(walletId, cardId, cardPubKey) - router.openWebView() + private fun buttonStoryClick() { + router.openWebView(interactor.buildUriForNewUser(), interactor.getBasicAuthHeaders()) } - // region WebViewHelper - override fun handleWebViewRedirect(uri: Uri): RedirectConsequences { - return interactor.handleWebViewRedirect(uri) + private fun buttonMainClick() { + if (!interactor.isUserHadPromoCode() && !interactor.isUserRegisteredInPromotion()) { + subscribeToWebViewResultEvents() + router.openWebView(interactor.buildUriForOldUser(), interactor.getBasicAuthHeaders()) + return + } + + viewModelScope.launch(dispatchers.io) { + updateUi { uiState.updateProgress(showProgress = true) } + + runCatching { interactor.requestAward() } + .onSuccess { requestAwardResult -> + requestAwardResult.fold( + onSuccess = { + val onHideDialog = { + uiState = uiState.updateGetBonusVisibility(isVisible = false) + .hideDialog() + } + val successDialog = MainScreenState.Dialog.Claimed( + onOk = onHideDialog, + onDismissRequest = onHideDialog, + ) + updateUi { uiState.showDialog(successDialog) } + }, + onFailure = { + val errorDialog = createErrorDialog(it.toDomainError()) + updateUi { + uiState.updateProgress(showProgress = false) + .showDialog(errorDialog) + } + }, + ) + } + .onFailure { exception -> + updateUi { uiState.updateProgress(showProgress = false) } + if (exception is UserCancelledException) return@launch + + val errorDialog = createErrorDialog(exception.toDomainError()) + updateUi { uiState.showDialog(errorDialog) } + } + } } - override fun getWebViewHeaders(): Map { - return interactor.getBasicAuthHeaders() + private fun getBonusDescription(): MainScreenState.Description { + return if (interactor.isUserRegisteredInPromotion()) { + MainScreenState.Description.GetBonus + } else { + MainScreenState.Description.Learn(interactor.getAwardAmount()) + } } - // endregion WebViewHelper + + private fun createErrorDialog(error: PromotionError): MainScreenState.Dialog { + return when (error) { + is PromotionError.CodeWasNotAppliedInShop -> { + val onHideDialog = { uiState = uiState.hideDialog() } + MainScreenState.Dialog.PromoCodeNotRegistered( + onOk = { + uiState = uiState.hideDialog() + subscribeToWebViewResultEvents() + router.openWebView(interactor.buildUriForNewUser(), interactor.getBasicAuthHeaders()) + }, + onCancel = onHideDialog, + onDismissRequest = onHideDialog, + ) + } + is PromotionError.CodeNotFound, + is PromotionError.CodeWasAlreadyUsed, + is PromotionError.CardAlreadyHasAward, + is PromotionError.WalletAlreadyHasAward, + is PromotionError.ProgramNotFound, + is PromotionError.ProgramWasEnd, + -> { + val onHideDialog = { + uiState = uiState.hideDialog() + .updateGetBonusVisibility(isVisible = false) + } + MainScreenState.Dialog.Error( + error = error, + onOk = onHideDialog, + onDismissRequest = onHideDialog, + ) + } + is PromotionError.UnknownError, PromotionError.NetworkUnreachable -> { + val onHideDialog = { uiState = uiState.hideDialog() } + MainScreenState.Dialog.Error( + error = error, + onOk = onHideDialog, + onDismissRequest = onHideDialog, + ) + } + } + } + + private fun subscribeToWebViewResultEvents() { + interactor.webViewResultHandler = object : WebViewResultHandler { + override fun handleResult(result: WebViewResult) { + interactor.webViewResultHandler = null + when (result) { + WebViewResult.ReadyForAward -> updateMainScreenViews() + WebViewResult.PromoCodeReceived -> Unit + } + } + } + } + + private suspend fun updateUi(updateBlock: suspend () -> Learn2earnState) { + withContext(dispatchers.io) { + val newState = updateBlock.invoke() + withContext(dispatchers.main) { uiState = newState } + } + } +} + +private fun Throwable.toDomainError(): PromotionError { + return this as? PromotionError ?: PromotionError.UnknownError(message ?: "Unknown error") } \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/GetBonusAlert.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/GetBonusView.kt similarity index 66% rename from features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/GetBonusAlert.kt rename to features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/GetBonusView.kt index 0079c24f11..25cd356f7d 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/GetBonusAlert.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/GetBonusView.kt @@ -4,6 +4,7 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* +import androidx.compose.material.CircularProgressIndicator import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -13,22 +14,27 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.Shape import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.tangem.core.ui.components.SpacerH4 +import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemTypography import com.tangem.feature.learn2earn.impl.R import com.tangem.feature.learn2earn.presentation.ui.component.GradientCircle +import com.tangem.feature.learn2earn.presentation.ui.state.MainScreenState /** [REDACTED_AUTHOR] */ @Composable -fun GetBonusAlert(onClick: () -> Unit, modifier: Modifier = Modifier) { +internal fun GetBonusView(state: MainScreenState, modifier: Modifier = Modifier) { + if (!state.isVisible) return + val shape = TangemTheme.shapes.roundedCornersMedium Box( modifier = modifier + .clickable(onClick = state.onClick) .height(TangemTheme.dimens.size96) .background( color = TangemTheme.colors.background.action, @@ -40,21 +46,33 @@ fun GetBonusAlert(onClick: () -> Unit, modifier: Modifier = Modifier) { modifier = Modifier.fillMaxHeight(), verticalAlignment = Alignment.CenterVertically, ) { - Image( - modifier = Modifier.padding(horizontal = TangemTheme.dimens.size16), - painter = painterResource(id = R.drawable.img_1inch_logo_42_40), - contentDescription = null, - ) + Box(modifier = Modifier.padding(horizontal = TangemTheme.dimens.size16)) { + Image( + painter = painterResource(id = R.drawable.img_1inch_logo_42_40), + alpha = state.logoAlphaValue, + contentDescription = null, + ) + if (state.showProgress) { + CircularProgressIndicator( + modifier = Modifier + .align(Alignment.Center) + .size(size = TangemTheme.dimens.size28), + color = Color.White, + strokeWidth = TangemTheme.dimens.size2, + ) + } + } Column( modifier = Modifier.padding(end = TangemTheme.dimens.size40), ) { Text( - text = stringResource(id = R.string.main_learn_title), + text = state.description.title.resolveReference(), style = TangemTypography.body1, color = TangemTheme.colors.text.primary2, ) + SpacerH4() Text( - text = stringResource(id = R.string.main_learn_subtitle), + text = state.description.subtitle.resolveReference(), style = TangemTypography.caption, color = TangemTheme.colors.text.secondary, ) @@ -64,8 +82,7 @@ fun GetBonusAlert(onClick: () -> Unit, modifier: Modifier = Modifier) { modifier = Modifier .size(TangemTheme.dimens.size40) .padding(end = TangemTheme.dimens.size16) - .align(Alignment.CenterEnd) - .clickable(onClick = onClick), + .align(Alignment.CenterEnd), painter = painterResource(id = R.drawable.ic_chevron_right_24), contentDescription = null, colorFilter = ColorFilter.tint(Color.Gray), @@ -112,9 +129,7 @@ private fun OneInchStoriesContentPreview_Light() { TangemTheme( isDark = false, ) { - GetBonusAlert( - onClick = {}, - ) + GetBonusView(makePreviewState()) } } @@ -124,8 +139,13 @@ private fun OneInchStoriesContentPreview_Dark() { TangemTheme( isDark = true, ) { - GetBonusAlert( - onClick = {}, - ) + GetBonusView(makePreviewState()) } -} \ No newline at end of file +} + +private fun makePreviewState(): MainScreenState = MainScreenState( + isVisible = true, + onClick = {}, + description = MainScreenState.Description.Learn("0"), + showProgress = false, +) \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/Learn2earnDialogs.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/Learn2earnDialogs.kt new file mode 100644 index 0000000000..2f752ea0fd --- /dev/null +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/Learn2earnDialogs.kt @@ -0,0 +1,85 @@ +package com.tangem.feature.learn2earn.presentation.ui + +import androidx.compose.material.AlertDialog +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import com.tangem.core.ui.components.TextButton +import com.tangem.feature.learn2earn.impl.R +import com.tangem.feature.learn2earn.presentation.ui.state.MainScreenState + +/** +[REDACTED_AUTHOR] + */ +@Composable +internal fun Learn2earnDialogs(dialog: MainScreenState.Dialog?) { + when (dialog) { + is MainScreenState.Dialog.Claimed -> ClaimedDialog(dialog) + is MainScreenState.Dialog.PromoCodeNotRegistered -> PromoCodeNotRegisteredDialog(dialog) + is MainScreenState.Dialog.Error -> ErrorDialog(dialog) + else -> Unit + } +} + +@Composable +private fun ClaimedDialog(dialog: MainScreenState.Dialog.Claimed) { + AlertDialog( + title = { + Text(text = stringResource(id = R.string.common_success)) + }, + text = { + Text(text = stringResource(id = R.string.main_promotion_credited)) + }, + confirmButton = { + TextButton( + text = stringResource(id = R.string.common_ok), + onClick = dialog.onOk, + ) + }, + onDismissRequest = dialog.onDismissRequest, + ) +} + +@Composable +private fun PromoCodeNotRegisteredDialog(dialog: MainScreenState.Dialog.PromoCodeNotRegistered) { + AlertDialog( + title = { + Text(text = stringResource(id = R.string.common_error)) + }, + text = { + Text(text = stringResource(id = R.string.main_promotion_no_purchase)) + }, + dismissButton = { + TextButton( + text = stringResource(id = R.string.common_cancel), + onClick = dialog.onCancel, + ) + }, + confirmButton = { + TextButton( + text = stringResource(id = R.string.common_buy), + onClick = dialog.onOk, + ) + }, + onDismissRequest = dialog.onDismissRequest, + ) +} + +@Composable +private fun ErrorDialog(dialog: MainScreenState.Dialog.Error) { + AlertDialog( + title = { + Text(text = stringResource(id = R.string.common_error)) + }, + text = { + Text(text = dialog.error.description) + }, + confirmButton = { + TextButton( + text = stringResource(id = R.string.common_ok), + onClick = dialog.onOk, + ) + }, + onDismissRequest = dialog.onDismissRequest, + ) +} \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/Learn2earnMainPageScreen.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/Learn2earnMainPageScreen.kt new file mode 100644 index 0000000000..e7dceb659e --- /dev/null +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/Learn2earnMainPageScreen.kt @@ -0,0 +1,21 @@ +package com.tangem.feature.learn2earn.presentation.ui + +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.tangem.core.ui.res.TangemTheme +import com.tangem.feature.learn2earn.presentation.Learn2earnViewModel + +/** +[REDACTED_AUTHOR] + */ +@Composable +fun Learn2earnMainPageScreen(viewModel: Learn2earnViewModel, modifier: Modifier = Modifier) { + GetBonusView( + state = viewModel.uiState.mainScreenState, + modifier = modifier + .padding(horizontal = TangemTheme.dimens.size16) + .padding(vertical = TangemTheme.dimens.size8), + ) + Learn2earnDialogs(viewModel.uiState.mainScreenState.dialog) +} \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/StoriesScreen.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/Learn2earnStoriesScreen.kt similarity index 95% rename from features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/StoriesScreen.kt rename to features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/Learn2earnStoriesScreen.kt index 74f3584e6b..0090991f43 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/StoriesScreen.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/Learn2earnStoriesScreen.kt @@ -24,9 +24,8 @@ import com.tangem.feature.learn2earn.presentation.ui.component.GradientCircle /** [REDACTED_AUTHOR] */ -// TODO: 1inch: make function as internal after adding feature interface @Composable -fun StoriesScreen(onLearnClick: () -> Unit, modifier: Modifier = Modifier) { +fun Learn2earnStoriesScreen(onLearnClick: () -> Unit, modifier: Modifier = Modifier) { Box(modifier = modifier.fillMaxSize()) { ContentBackground( modifier = Modifier @@ -111,7 +110,7 @@ private fun OneInchStoriesContentPreview_Light() { TangemTheme( isDark = false, ) { - StoriesScreen( + Learn2earnStoriesScreen( onLearnClick = {}, ) } @@ -123,7 +122,7 @@ private fun OneInchStoriesContentPreview_Dark() { TangemTheme( isDark = true, ) { - StoriesScreen( + Learn2earnStoriesScreen( onLearnClick = {}, ) } diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/Learn2earnState.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/Learn2earnState.kt new file mode 100644 index 0000000000..7e970ee675 --- /dev/null +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/Learn2earnState.kt @@ -0,0 +1,68 @@ +package com.tangem.feature.learn2earn.presentation.ui.state + +import com.tangem.core.ui.extensions.TextReference +import com.tangem.feature.learn2earn.domain.models.PromotionError +import com.tangem.feature.learn2earn.impl.R + +/** +[REDACTED_AUTHOR] + */ +data class Learn2earnState( + val storyScreenState: StoryScreenState, + val mainScreenState: MainScreenState, +) { + companion object +} + +data class StoryScreenState( + val isVisible: Boolean, + val onClick: () -> Unit, +) + +data class MainScreenState( + val isVisible: Boolean, + val onClick: () -> Unit, + val description: Description, + val showProgress: Boolean, + val logoAlphaValue: Float = 1f, + val dialog: Dialog? = null, +) { + + sealed class Description(val title: TextReference, val subtitle: TextReference) { + + class Learn(awardAmount: String) : Description( + TextReference.Res(R.string.main_learn_title), + TextReference.Res(R.string.main_learn_subtitle, listOf(awardAmount)), + ) + + object GetBonus : Description( + TextReference.Res(R.string.main_get_bonus_title), + TextReference.Res(R.string.main_get_bonus_subtitle), + ) + } + + sealed class Dialog { + + data class Claimed( + val onOk: () -> Unit, + val onDismissRequest: () -> Unit, + ) : Dialog() + + data class PromoCodeNotRegistered( + val onOk: () -> Unit, + val onCancel: () -> Unit, + val onDismissRequest: () -> Unit, + ) : Dialog() + + data class Error( + val error: PromotionError, + val onOk: () -> Unit, + val onDismissRequest: () -> Unit, + ) : Dialog() + } +} + +class UiActions( + val buttonStoryClick: () -> Unit, + val buttonMainClick: () -> Unit, +) \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/StateBuilder.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/StateBuilder.kt new file mode 100644 index 0000000000..a0d3929569 --- /dev/null +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/StateBuilder.kt @@ -0,0 +1,93 @@ +package com.tangem.feature.learn2earn.presentation.ui.state + +/** +[REDACTED_AUTHOR] + */ +internal fun Learn2earnState.Companion.init(uiActions: UiActions): Learn2earnState { + return Learn2earnState( + storyScreenState = StoryScreenState( + isVisible = false, + onClick = uiActions.buttonStoryClick, + ), + mainScreenState = MainScreenState( + isVisible = false, + onClick = uiActions.buttonMainClick, + description = MainScreenState.Description.Learn("0"), + showProgress = false, + ), + ) +} + +internal fun Learn2earnState.updateStoriesVisibility(isVisible: Boolean): Learn2earnState { + return if (storyScreenState.isVisible == isVisible) { + this + } else { + copy( + storyScreenState = storyScreenState.copy( + isVisible = isVisible, + ), + ) + } +} + +internal fun Learn2earnState.updateGetBonusVisibility(isVisible: Boolean): Learn2earnState { + return if (mainScreenState.isVisible == isVisible) { + this + } else { + copy( + mainScreenState = mainScreenState.copy( + isVisible = isVisible, + ), + ) + } +} + +internal fun Learn2earnState.changeGetBounsDescription(description: MainScreenState.Description,): Learn2earnState { + return if (mainScreenState.description == description) { + this + } else { + copy( + mainScreenState = mainScreenState.copy( + description = description, + ), + ) + } +} + +internal fun Learn2earnState.showDialog(dialog: MainScreenState.Dialog): Learn2earnState { + return if (mainScreenState.dialog == dialog) { + this + } else { + copy( + mainScreenState = mainScreenState.copy( + dialog = dialog, + ), + ) + } +} + +internal fun Learn2earnState.hideDialog(): Learn2earnState { + return if (mainScreenState.dialog == null) { + this + } else { + copy( + mainScreenState = mainScreenState.copy( + dialog = null, + ), + ) + } +} + +@Suppress("MagicNumber") +internal fun Learn2earnState.updateProgress(showProgress: Boolean): Learn2earnState { + return if (mainScreenState.showProgress == showProgress) { + this + } else { + copy( + mainScreenState = mainScreenState.copy( + showProgress = showProgress, + logoAlphaValue = if (showProgress) 0.2f else 1f, + ), + ) + } +} \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnWebViewActivity.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewActivity.kt similarity index 55% rename from features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnWebViewActivity.kt rename to features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewActivity.kt index c054b21ef0..cea693607e 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnWebViewActivity.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewActivity.kt @@ -1,15 +1,11 @@ -package com.tangem.feature.learn2earn.presentation +package com.tangem.feature.learn2earn.presentation.webView import android.os.Bundle import android.view.MenuItem -import android.webkit.WebResourceRequest import android.webkit.WebView -import android.webkit.WebViewClient import androidx.activity.viewModels import androidx.appcompat.app.ActionBar import androidx.appcompat.app.AppCompatActivity -import com.tangem.feature.learn2earn.domain.models.RedirectConsequences -import com.tangem.feature.learn2earn.domain.models.WebViewHelper import com.tangem.feature.learn2earn.impl.R import dagger.hilt.android.AndroidEntryPoint @@ -19,7 +15,7 @@ import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint class Learn2earnWebViewActivity : AppCompatActivity() { - private val learn2earnViewModel by viewModels() + private val viewModel by viewModels() private lateinit var actionBar: ActionBar private lateinit var webView: WebView @@ -28,24 +24,27 @@ class Learn2earnWebViewActivity : AppCompatActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_web_view) + val webViewData = viewModel.extractData(intent) + setSupportActionBar(findViewById(R.id.toolbar)) actionBar = supportActionBar!! actionBar.setDisplayHomeAsUpEnabled(true) actionBar.setDisplayShowHomeEnabled(true) - actionBar.title = learn2earnViewModel.webViewUri.authority - + actionBar.title = webViewData.uri.authority webView = findViewById(R.id.web_view) + webView.settings.javaScriptEnabled = true webView.settings.domStorageEnabled = true webView.settings.loadsImagesAutomatically = true webView.webViewClient = Learn2earnWebViewClient( - helper = learn2earnViewModel, + helper = viewModel, + headers = webViewData.headers, finishSessionHandler = { finish() }, ) webView.loadUrl( - learn2earnViewModel.webViewUri.toString(), - learn2earnViewModel.getWebViewHeaders(), + webViewData.uri.toString(), + webViewData.headers, ) } @@ -66,25 +65,9 @@ class Learn2earnWebViewActivity : AppCompatActivity() { super.onDestroy() } -} -private class Learn2earnWebViewClient( - private val helper: WebViewHelper, - private val finishSessionHandler: () -> Unit, -) : WebViewClient() { - - override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean { - when (helper.handleWebViewRedirect(request.url)) { - RedirectConsequences.NOTHING -> Unit - RedirectConsequences.PROCEED -> { - val headers = helper.getWebViewHeaders().toMutableMap() - request.requestHeaders?.let { headers.putAll(it) } - view.loadUrl(request.url.toString(), headers) - } - RedirectConsequences.FINISH_SESSION -> { - finishSessionHandler.invoke() - } - } - return true + companion object { + const val EXTRA_WEB_URI = "webViewUri" + const val EXTRA_WEB_HEADERS = "webViewHeaders" } } \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewClient.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewClient.kt new file mode 100644 index 0000000000..5957d80a32 --- /dev/null +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewClient.kt @@ -0,0 +1,31 @@ +package com.tangem.feature.learn2earn.presentation.webView + +import android.webkit.WebResourceRequest +import android.webkit.WebView +import android.webkit.WebViewClient +import com.tangem.feature.learn2earn.domain.api.RedirectConsequences +import com.tangem.feature.learn2earn.domain.api.WebViewRedirectHandler +import timber.log.Timber + +internal class Learn2earnWebViewClient( + private val helper: WebViewRedirectHandler, + private val headers: Map, + private val finishSessionHandler: () -> Unit, +) : WebViewClient() { + + override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean { + Timber.d("url: ${request.url}") + when (helper.handleRedirect(request.url)) { + RedirectConsequences.PROCEED -> { + val mergedHeaders = headers.toMutableMap() + request.requestHeaders?.let { mergedHeaders.putAll(it) } + view.loadUrl(request.url.toString(), mergedHeaders) + } + RedirectConsequences.FINISH_SESSION -> { + finishSessionHandler.invoke() + } + else -> Unit + } + return true + } +} \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/WebViewViewModel.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/WebViewViewModel.kt new file mode 100644 index 0000000000..3c473657de --- /dev/null +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/WebViewViewModel.kt @@ -0,0 +1,38 @@ +package com.tangem.feature.learn2earn.presentation.webView + +import android.content.Intent +import android.net.Uri +import androidx.lifecycle.ViewModel +import com.tangem.feature.learn2earn.domain.HeadersConverter +import com.tangem.feature.learn2earn.domain.api.RedirectConsequences +import com.tangem.feature.learn2earn.domain.api.WebViewRedirectHandler +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +/** +[REDACTED_AUTHOR] + */ +@HiltViewModel +class WebViewViewModel @Inject constructor( + private val handler: WebViewRedirectHandler, +) : ViewModel(), WebViewRedirectHandler { + + override fun handleRedirect(uri: Uri): RedirectConsequences { + return handler.handleRedirect(uri) + } + + fun extractData(intent: Intent): WebViewData { + val uriString = intent.getStringExtra(Learn2earnWebViewActivity.EXTRA_WEB_URI)!! + val rawHeaders = intent.getStringArrayListExtra(Learn2earnWebViewActivity.EXTRA_WEB_HEADERS) ?: ArrayList() + + return WebViewData( + uri = Uri.parse(uriString), + headers = HeadersConverter().convertBack(rawHeaders), + ) + } +} + +data class WebViewData( + val uri: Uri, + val headers: Map, +) \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/res/layout/activity_web_view.xml b/features/learn2earn/impl/src/main/res/layout/activity_web_view.xml index 46968b0a14..d4020201c8 100644 --- a/features/learn2earn/impl/src/main/res/layout/activity_web_view.xml +++ b/features/learn2earn/impl/src/main/res/layout/activity_web_view.xml @@ -10,6 +10,7 @@ android:id="@+id/app_bar" style="@style/Widget.MaterialComponents.Toolbar.Surface" android:layout_width="match_parent" + app:liftOnScroll="true" android:layout_height="wrap_content">