Fix scope id usage for tooltip

commit_hash:2442e8fc849d7b20dee2ec327ccc5fbe675a8d30
This commit is contained in:
grechka62
2026-06-05 16:13:46 +03:00
parent 6a69c2042a
commit 83f642a1db
2 changed files with 30 additions and 22 deletions
@@ -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<DivTooltip, View>? {
private fun View.findChildWithTooltip(tooltipId: String): Pair<DivTooltip, View>? {
@Suppress("UNCHECKED_CAST")
(view.getTag(R.id.div_tooltips_tag) as? List<DivTooltip>)?.let { tooltips ->
tooltips.forEach {
if (it.id == tooltipId) {
return it to view
}
}
val tooltips = getTag(R.id.div_tooltips_tag) as? List<DivTooltip>
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
}
@@ -11,11 +11,19 @@ internal object ViewLocator {
@JvmStatic
fun findSingleViewWithTag(view: Div2View, tag: String): View? = view.findSingleViewWithTag<View>(tag).getOrNull()
inline fun <reified T> findSingleViewWithTag(view: Div2View, tag: String, scopeId: String?): Result<T> {
scopeId ?: return view.findSingleViewWithTag<T>(tag)
inline fun <reified T> findSingleViewWithTag(view: Div2View, tag: String, scopeId: String?): Result<T> =
findSingleViewWithTag(view, tag, scopeId) { id, inScope -> findSingleViewWithTag(id, inScope = inScope) }
inline fun <reified T> findSingleViewWithTag(
view: Div2View,
tag: String,
scopeId: String?,
findTargetView: View.(id: String, inScope: Boolean) -> Result<T>,
): Result<T> {
scopeId ?: return view.findTargetView(tag, false)
val scopeError = view.findSingleViewWithTag<View>(scopeId, isScope = true)
.onSuccess { return it.findSingleViewWithTag<T>(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<T>(tag)
return view.findTargetView(tag, false)
.onSuccess { view.logWarning(scopeError) }
.onFailure { if (it is DuplicateTarget) return Result.failure(scopeError) }
}