fix(android): tolerate overlapping order navigation labels (#307)

This commit is contained in:
QiuSW
2026-09-18 11:05:16 +08:00
parent f15a390e20
commit 981b3d43f2
3 changed files with 30 additions and 3 deletions
@@ -205,7 +205,7 @@ class GoAutoAccessibilityService : AccessibilityService(), UiDriver, PddCollecto
BackfillPagePolicy.expansion(page)?.path == fresh.path ||
(fresh.label == "全部" && page.nodes.any { it.label in setOf("我的订单", "全部订单") })
if (allTab && !fresh.clickable) return dispatchCenterTap(Rect(fresh.bounds.left, fresh.bounds.top, fresh.bounds.right, fresh.bounds.bottom))
if (!allowed || !BackfillPagePolicy.safe(page, fresh)) return false
if (!allowed || (!allTab && !BackfillPagePolicy.safe(page, fresh))) return false
val root = rootInActiveWindow ?: return false
if (root.packageName?.toString() != BackfillPagePolicy.PDD) return false
var node = root
@@ -27,8 +27,15 @@ object BackfillPagePolicy {
val tab = page.nodes.filter { it.visible && it.enabled && it.label == "全部" }.singleOrNull() ?: return null
val peers = page.nodes.filter { it.visible && it.label in setOf("待付款", "待分享", "待发货", "待收货", "待评价") &&
it.bounds.top < tab.bounds.bottom && it.bounds.bottom > tab.bounds.top }
if (peers.map { it.label }.distinct().size < 2 || peers.any { it.bounds.left < tab.bounds.right }) return null
return tab.takeIf { safe(page, it.copy(clickable = true)) }
val centerX = tab.bounds.left.toLong() + tab.bounds.width / 2
if (peers.map { it.label }.distinct().size < 2 || peers.any {
it.bounds.width <= 0 || it.bounds.left.toLong() + it.bounds.width / 2 <= centerX ||
centerX >= it.bounds.left && centerX < it.bounds.right
}) return null
// WebView navigation labels can overlap by a few pixels. Exclude only
// these verified peers (e.g. 待付款), not actual payment/action nodes.
val navigationPage = page.copy(nodes = page.nodes.filter { it !in peers })
return tab.takeIf { safe(navigationPage, it.copy(clickable = true)) }
}
fun confirmedList(page: UiSnapshot, tabConfirmed: Boolean): Boolean = list(page) ||
@@ -275,6 +275,26 @@ class OrderBackfillTest {
assertNull(BackfillPagePolicy.allTab(p.copy(nodes = p.nodes + p.nodes[1].copy(path = "0/9", text = "去支付"))))
}
@Test fun `real navigation bounds tolerate three pixel overlap but never payment actions`() {
val p = page(
node("0/0", "我的订单").copy(bounds = NodeBounds(438, 120, 642, 258)),
node("0/1", "全部").copy(clickable = false, bounds = NodeBounds(0, 258, 201, 372)),
node("0/2", "待付款").copy(clickable = false, bounds = NodeBounds(198, 258, 399, 372)),
node("0/3", "待分享").copy(clickable = false, bounds = NodeBounds(396, 258, 597, 372)),
node("0/4", "待发货").copy(clickable = false, bounds = NodeBounds(594, 258, 795, 372)))
assertEquals(p.nodes[1], BackfillPagePolicy.allTab(p))
assertTrue(BackfillPagePolicy.confirmedList(p, true))
assertFalse(BackfillPagePolicy.confirmedList(p, false))
assertNull(BackfillPagePolicy.allTab(p.copy(nodes = p.nodes +
node("0/9", "去支付").copy(bounds = NodeBounds(198, 258, 399, 372)))))
assertNull(BackfillPagePolicy.allTab(p.copy(nodes = p.nodes.map {
if (it.label == "待付款") it.copy(bounds = NodeBounds(90, 258, 399, 372)) else it
})))
assertNull(BackfillPagePolicy.allTab(p.copy(nodes = p.nodes.map {
if (it.label == "待付款") it.copy(bounds = NodeBounds(-100, 258, 90, 372)) else it
})))
}
@Test fun `scanner waits for stable list and taps only all when selected is missing`() {
var reads = 0
var clicks = 0