diff --git a/vending-app/src/main/java/org/microg/vending/billing/core/ui/UIParser.kt b/vending-app/src/main/java/org/microg/vending/billing/core/ui/UIParser.kt index 7521ae3dcb..edd5076a80 100644 --- a/vending-app/src/main/java/org/microg/vending/billing/core/ui/UIParser.kt +++ b/vending-app/src/main/java/org/microg/vending/billing/core/ui/UIParser.kt @@ -98,7 +98,10 @@ private fun parseAction(action: Action?, result: BAction): Boolean { } action.viewClickAction?.let { viewClickAction -> if (viewClickAction.uiInfo != null) { - result.uiInfo = parseUIInfo(viewClickAction.uiInfo!!) + val parsedUiInfo = parseUIInfo(viewClickAction.uiInfo!!) + if (parsedUiInfo.uiType != UIType.UNKNOWN) { + result.uiInfo = parsedUiInfo + } } return parseAction(viewClickAction.action, result) } @@ -676,4 +679,4 @@ private fun extractPurchaseItemFromScreens( ) } return mapOf("RESPONSE_CODE" to 0, "DEBUG_MESSAGE" to "") to null -} \ No newline at end of file +} diff --git a/vending-app/src/main/java/org/microg/vending/billing/ui/logic/BillingScreenHistory.kt b/vending-app/src/main/java/org/microg/vending/billing/ui/logic/BillingScreenHistory.kt new file mode 100644 index 0000000000..d00c4f18f0 --- /dev/null +++ b/vending-app/src/main/java/org/microg/vending/billing/ui/logic/BillingScreenHistory.kt @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2026 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.vending.billing.ui.logic + +internal class BillingScreenHistory { + private companion object { + const val MAX_SIZE = 32 + } + + private val screenIds = mutableListOf() + + fun recordTransition(fromScreenId: String?, toScreenId: String?): Boolean { + if (fromScreenId == null || toScreenId == null || fromScreenId == toScreenId) return false + + val targetIndex = screenIds.lastIndexOf(toScreenId) + if (targetIndex >= 0) { + screenIds.subList(targetIndex, screenIds.size).clear() + return true + } + + if (screenIds.lastOrNull() == fromScreenId) return false + screenIds.add(fromScreenId) + if (screenIds.size > MAX_SIZE) screenIds.removeAt(0) + return true + } + + fun popPrevious(currentScreenId: String?, isAvailable: (String) -> Boolean): String? { + while (screenIds.isNotEmpty()) { + val screenId = screenIds.removeAt(screenIds.lastIndex) + if (screenId != currentScreenId && isAvailable(screenId)) return screenId + } + return null + } +} diff --git a/vending-app/src/main/java/org/microg/vending/billing/ui/logic/InAppBillingViewModel.kt b/vending-app/src/main/java/org/microg/vending/billing/ui/logic/InAppBillingViewModel.kt index 063d011c98..07f20ed4bf 100644 --- a/vending-app/src/main/java/org/microg/vending/billing/ui/logic/InAppBillingViewModel.kt +++ b/vending-app/src/main/java/org/microg/vending/billing/ui/logic/InAppBillingViewModel.kt @@ -75,6 +75,8 @@ class InAppBillingViewModel : ViewModel() { ) ) private lateinit var lastBuyFlowResult: BuyFlowResult + private val screenHistory = BillingScreenHistory() + private var currentScreenId: String? = null private fun finishWithResult(result: Bundle) { viewModelScope.launch { @@ -268,14 +270,36 @@ class InAppBillingViewModel : ViewModel() { } } + UIType.BILLING_PROFILE_SCREEN_ABANDON -> { + if (showPreviousScreen()) return + finishWithResult(billingUiViewState.result) + } + else -> finishWithResult(billingUiViewState.result) } } } } - private fun showScreen(screenId: String): Boolean { + private fun showPreviousScreen(): Boolean { + val previousScreenId = screenHistory.popPrevious( + currentScreenId, + billingUiViewState.screenMap::containsKey + ) + return previousScreenId != null && showScreen( + previousScreenId, + recordHistory = false + ) + } + + private fun showScreen( + screenId: String, + recordHistory: Boolean = true + ): Boolean { + val previousScreenId = currentScreenId val showScreen = billingUiViewState.screenMap[screenId] ?: return false + if (recordHistory) screenHistory.recordTransition(previousScreenId, screenId) + currentScreenId = screenId billingUiViewState = billingUiViewState.copy( showScreen = showScreen, visible = true @@ -300,11 +324,15 @@ class InAppBillingViewModel : ViewModel() { } val action = buyFlowResult.acquireResult?.action ?: return failAction() val screenMap = buyFlowResult.acquireResult.screenMap - val showScreen = screenMap[action.screenId] ?: return failAction() + val targetScreenId = action.screenId ?: return failAction() + val showScreen = screenMap[targetScreenId] ?: return failAction() if (Log.isLoggable(TAG, Log.DEBUG)) Log.d(TAG, "handleAcquireResult, showScreen:$showScreen result:${buyFlowResult.acquireResult}") if (action.type != ActionType.SHOW) return failAction() lastBuyFlowResult = buyFlowResult + val previousScreenId = currentScreenId billingUiViewState.screenMap.putAll(screenMap) + screenHistory.recordTransition(previousScreenId, targetScreenId) + currentScreenId = targetScreenId billingUiViewState = billingUiViewState.copy( showScreen = showScreen, result = buyFlowResult.result, @@ -400,4 +428,4 @@ class InAppBillingViewModel : ViewModel() { resultBundle(BillingClient.BillingResponseCode.USER_CANCELED, "") finishWithResult(result) } -} \ No newline at end of file +}