ReviewOS

also looking at this

craft-native/craft

fix(mobile): preserve native editing, navigation, and durable media requests

#369
Merged chris wants to merge codex/native-vertical-scroll-tab-swipes into main
36 files +864 -185
packages/android/fixtures/native-navigation/NativeNavigationTest.ktmodified+27-5
Changes to packages/android/fixtures/native-navigation/NativeNavigationTest.kt
@@ -783,6 +783,19 @@ class NativeNavigationTest {
783783 throw AssertionError("The native accessibility tree did not expose STX testID $id")
784784 }
785785 try {
786 awaitView(activity, "home-title")
787 val homeTab = node("craft-tab-/")
788 assertEquals("Home", homeTab.contentDescription.toString())
789 assertEquals(Button::class.java.name, homeTab.className.toString())
790 assertTrue(homeTab.isSelected)
791 val detailsTab = node("craft-tab-/details")
792 assertEquals("Details", detailsTab.contentDescription.toString())
793 assertFalse(detailsTab.isSelected)
794 assertTrue("The native tab did not accept its accessibility click",
795 detailsTab.performAction(AccessibilityNodeInfo.ACTION_CLICK))
796 awaitView(activity, "details-title")
797 assertTrue(node("craft-tab-/details").isSelected)
798 assertTrue(node("craft-tab-/").performAction(AccessibilityNodeInfo.ACTION_CLICK))
786799 awaitView(activity, "home-title")
787800 val title = node("home-title")
788801 assertEquals("Home", title.text.toString())
@@ -1113,7 +1126,7 @@ class NativeNavigationTest {
11131126 val templateFirst = awaitView(activity, "grid-template-rows-first")
11141127 val templateThird = awaitView(activity, "grid-template-rows-third")
11151128 assertEquals(templateFirst.height, templateThird.height)
1116 assertTrue("explicit grid rows did not fill the definite height", templateThird.top - templateFirst.top > (30 * density).toInt())
1129 assertEquals("explicit grid rows did not fill the definite height", 44.0 * density, (templateThird.top - templateFirst.top).toDouble(), 1.0)
11171130 val fractionalGrid = awaitView(activity, "grid-fractional-wrap")
11181131 val fractionalFirst = awaitView(activity, "grid-fractional-first")
11191132 val fractionalSecond = awaitView(activity, "grid-fractional-second")
@@ -1883,10 +1896,19 @@ class NativeNavigationTest {
18831896 people.scrollTo(0, (peopleContent?.height ?: 0) - people.height)
18841897 }
18851898 SystemClock.sleep(150)
1886 assertTrue(
1887 "ScrollView sticky header did not remain pinned",
1888 screenTop(peopleHeader) >= screenTop(people) + (8 * density).toInt() - 1,
1889 )
1899 instrumentation.runOnMainSync {
1900 // Sticky headers stay at the native host's effective viewport
1901 // edge, including its authored content inset.
1902 val headerTop = screenTop(peopleHeader)
1903 val viewportTop = screenTop(people) + peopleContent.paddingTop
1904 val firstChild = (peopleContent as? ViewGroup)?.getChildAt(0)
1905 val layout = "scrollY=${people.scrollY} headerTop=${peopleHeader.top} translationY=${peopleHeader.translationY} contentHeight=${peopleContent.height} viewportHeight=${people.height} firstChild=${firstChild?.tag} firstTranslation=${firstChild?.translationY} headerIsDirectChild=${peopleHeader.parent === peopleContent} focus=${activity.currentFocus?.tag} refreshing=${peopleHost.isRefreshing}"
1906 assertTrue("ScrollView did not retain the requested scroll: $layout", people.scrollY > 0)
1907 assertTrue(
1908 "ScrollView sticky header did not remain pinned: header=$headerTop viewport=$viewportTop $layout",
1909 kotlin.math.abs(headerTop - viewportTop) <= 1,
1910 )
1911 }
18901912 val peopleLayouts = awaitView(activity, "people-layout-status") as TextView
18911913 val initialRowLayouts = peopleLayouts.text.toString().substringAfterLast(": ").toInt()
18921914 assertTrue("ScrollView rows did not report layout", initialRowLayouts > 0)