From 83f642a1db02be7eabca439dfd57b02e4b300b8d Mon Sep 17 00:00:00 2001 From: grechka62 Date: Fri, 5 Jun 2026 16:13:46 +0300 Subject: [PATCH] Fix scope id usage for tooltip commit_hash:2442e8fc849d7b20dee2ec327ccc5fbe675a8d30 --- .../div/core/tooltip/DivTooltipController.kt | 36 +++++++++---------- .../com/yandex/div/core/view2/ViewLocator.kt | 16 ++++++--- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/client/android/div/src/main/java/com/yandex/div/core/tooltip/DivTooltipController.kt b/client/android/div/src/main/java/com/yandex/div/core/tooltip/DivTooltipController.kt index 573431391..cd8998856 100644 --- a/client/android/div/src/main/java/com/yandex/div/core/tooltip/DivTooltipController.kt +++ b/client/android/div/src/main/java/com/yandex/div/core/tooltip/DivTooltipController.kt @@ -21,6 +21,7 @@ import com.yandex.div.R import com.yandex.div.core.DivActionHandler import com.yandex.div.core.DivPreloader import com.yandex.div.core.DivTooltipRestrictor +import com.yandex.div.core.actions.logActionError import com.yandex.div.core.annotations.Mockable import com.yandex.div.core.dagger.DivScope import com.yandex.div.core.util.AccessibilityStateProvider @@ -31,17 +32,18 @@ import com.yandex.div.core.util.toLayoutParamsSize import com.yandex.div.core.view2.BindingContext import com.yandex.div.core.view2.Div2View import com.yandex.div.core.view2.DivVisibilityActionTracker +import com.yandex.div.core.view2.ViewLocator import com.yandex.div.core.view2.divs.toPx import com.yandex.div.core.view2.errors.ErrorCollectors import com.yandex.div.internal.Assert import com.yandex.div.json.expressions.ExpressionResolver import com.yandex.div2.Div import com.yandex.div2.DivAction +import com.yandex.div2.DivActionShowTooltip import com.yandex.div2.DivTooltip import com.yandex.div2.DivTooltipMode import javax.inject.Inject - internal typealias CreatePopupCall = (contentView: View, width: Int, height: Int) -> SafePopupWindow private const val CANT_FIND_ON_BACKPRESS_DISPATCHER = @@ -78,11 +80,13 @@ internal class DivTooltipController @VisibleForTesting constructor( { c: View, w: Int, h: Int -> DivTooltipWindow(c, w, h) }) fun showTooltip(tooltipId: String, context: BindingContext, multiple: Boolean = false, scopeId: String? = null) { - findChildWithTooltip(tooltipId, context.divView)?.let { (divTooltip, anchor) -> + ViewLocator.findSingleViewWithTag(context.divView, tooltipId, scopeId) { tooltipId, _ -> + findChildWithTooltip(tooltipId)?.let { Result.success(it) } + ?: Result.failure(IllegalStateException("Unable to find view for tooltip '$tooltipId'")) + }.onSuccess { (divTooltip, anchor) -> showTooltip(context, divTooltip, anchor, multiple, scopeId) - } ?: run { - context.divView.logError(IllegalStateException( - "Unable to find view for tooltip '$tooltipId'")) + }.onFailure { + context.divView.logActionError(DivActionShowTooltip.TYPE, it) } } @@ -458,21 +462,17 @@ private class PopupWindowTouchListener( } } -private fun findChildWithTooltip(tooltipId: String, view: View): Pair? { +private fun View.findChildWithTooltip(tooltipId: String): Pair? { @Suppress("UNCHECKED_CAST") - (view.getTag(R.id.div_tooltips_tag) as? List)?.let { tooltips -> - tooltips.forEach { - if (it.id == tooltipId) { - return it to view - } - } + val tooltips = getTag(R.id.div_tooltips_tag) as? List + tooltips?.forEach { + if (it.id == tooltipId) return it to this } - if (view is ViewGroup) { - view.children.forEach { child -> - findChildWithTooltip(tooltipId, child)?.let { - return it - } - } + + if (this !is ViewGroup) return null + + children.forEach { child -> + child.findChildWithTooltip(tooltipId)?.let { return it } } return null } diff --git a/client/android/div/src/main/java/com/yandex/div/core/view2/ViewLocator.kt b/client/android/div/src/main/java/com/yandex/div/core/view2/ViewLocator.kt index b46c4202f..bb212ac99 100644 --- a/client/android/div/src/main/java/com/yandex/div/core/view2/ViewLocator.kt +++ b/client/android/div/src/main/java/com/yandex/div/core/view2/ViewLocator.kt @@ -11,11 +11,19 @@ internal object ViewLocator { @JvmStatic fun findSingleViewWithTag(view: Div2View, tag: String): View? = view.findSingleViewWithTag(tag).getOrNull() - inline fun findSingleViewWithTag(view: Div2View, tag: String, scopeId: String?): Result { - scopeId ?: return view.findSingleViewWithTag(tag) + inline fun findSingleViewWithTag(view: Div2View, tag: String, scopeId: String?): Result = + findSingleViewWithTag(view, tag, scopeId) { id, inScope -> findSingleViewWithTag(id, inScope = inScope) } + + inline fun findSingleViewWithTag( + view: Div2View, + tag: String, + scopeId: String?, + findTargetView: View.(id: String, inScope: Boolean) -> Result, + ): Result { + scopeId ?: return view.findTargetView(tag, false) val scopeError = view.findSingleViewWithTag(scopeId, isScope = true) - .onSuccess { return it.findSingleViewWithTag(tag, inScope = true) } + .onSuccess { return it.findTargetView(tag, true) } .exceptionOrNull() if (scopeError !is MissingTarget) { @@ -26,7 +34,7 @@ internal object ViewLocator { return Result.failure(error) } - return view.findSingleViewWithTag(tag) + return view.findTargetView(tag, false) .onSuccess { view.logWarning(scopeError) } .onFailure { if (it is DuplicateTarget) return Result.failure(scopeError) } }