reis-mobile 0.3.6 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +24 -0
  4. package/README.md +175 -168
  5. package/THIRD_PARTY_NOTICES.md +224 -4
  6. package/agents/android-architect.md +89 -0
  7. package/agents/android-performance-engineer.md +92 -0
  8. package/agents/android-test-engineer.md +97 -0
  9. package/agents/flutter-test-engineer.md +2 -0
  10. package/agents/ios-architect.md +93 -0
  11. package/agents/ios-performance-engineer.md +92 -0
  12. package/agents/ios-test-engineer.md +95 -0
  13. package/agents/lead-mobile.md +10 -1
  14. package/agents/mobile-staff-engineer.md +1 -1
  15. package/agents/rn-architect.md +94 -0
  16. package/agents/rn-performance-engineer.md +92 -0
  17. package/agents/rn-test-engineer.md +98 -0
  18. package/bin/reis-mobile.mjs +59 -17
  19. package/commands/debate.md +10 -1
  20. package/commands/debug.md +60 -0
  21. package/commands/reis-mobile.md +7 -2
  22. package/core/config/project.mjs +59 -0
  23. package/core/registry/frontmatter.mjs +15 -4
  24. package/core/registry/registry.mjs +21 -1
  25. package/core/router/intents.mjs +2 -0
  26. package/core/router/router.mjs +10 -5
  27. package/package.json +1 -1
  28. package/skills/android-adaptive/SKILL.md +304 -0
  29. package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/flexbox/container-behavior.md +112 -0
  30. package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/flexbox/get-started.md +69 -0
  31. package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/flexbox/index.md +81 -0
  32. package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/flexbox/item-behavior.md +170 -0
  33. package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/grid/container-properties.md +415 -0
  34. package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/grid/get-started.md +51 -0
  35. package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/grid/index.md +73 -0
  36. package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/grid/item-properties.md +170 -0
  37. package/skills/android-adaptive/references/android/develop/ui/compose/layouts/adaptive/mediaquery/index.md +333 -0
  38. package/skills/android-adaptive/references/android/develop/ui/compose/tooling/debug.md +114 -0
  39. package/skills/android-adaptive/references/android/guide/navigation/navigation-3/recipes/material-listdetail.md +141 -0
  40. package/skills/android-agp-9-upgrade/SKILL.md +106 -0
  41. package/skills/android-agp-9-upgrade/references/android/build/migrate-to-built-in-kotlin.md +416 -0
  42. package/skills/android-agp-9-upgrade/references/android/build/releases/agp-9-0-0-release-notes.md +554 -0
  43. package/skills/android-agp-9-upgrade/references/buildconfig.md +54 -0
  44. package/skills/android-agp-9-upgrade/references/ksp-kapt.md +39 -0
  45. package/skills/android-agp-9-upgrade/references/paparazzi-gradle-9.md +30 -0
  46. package/skills/android-agp-9-upgrade/references/recipes.md +62 -0
  47. package/skills/android-appfunctions/SKILL.md +74 -0
  48. package/skills/android-appfunctions/references/adb-interaction-testing.md +95 -0
  49. package/skills/android-appfunctions/references/context.md +26 -0
  50. package/skills/android-appfunctions/references/feature-discovery-analysis.md +71 -0
  51. package/skills/android-appfunctions/references/implementation-configuration.md +282 -0
  52. package/skills/android-appfunctions/references/kdoc-refinement-optimization.md +75 -0
  53. package/skills/android-appfunctions/references/migrate-to-service-entry-point.md +226 -0
  54. package/skills/android-camerax/SKILL.md +135 -0
  55. package/skills/android-camerax/references/camera1-to-camerax.md +198 -0
  56. package/skills/android-camerax/references/camera2-to-camerax.md +193 -0
  57. package/skills/android-camerax/references/expert-blueprints.md +58 -0
  58. package/skills/android-camerax/references/foldables.md +83 -0
  59. package/skills/android-camerax/references/immutability.md +60 -0
  60. package/skills/android-camerax/references/low-light.md +124 -0
  61. package/skills/android-camerax/references/mlkit-spatial.md +75 -0
  62. package/skills/android-camerax/references/modern-apis.md +42 -0
  63. package/skills/android-camerax/references/testing.md +69 -0
  64. package/skills/android-camerax/references/thermals.md +85 -0
  65. package/skills/android-camerax/references/wear-os.md +76 -0
  66. package/skills/android-camerax/references/xr.md +54 -0
  67. package/skills/android-cli/SKILL.md +474 -0
  68. package/skills/android-cli/references/interact.md +113 -0
  69. package/skills/android-cli/references/journeys.md +120 -0
  70. package/skills/android-code-review/SKILL.md +58 -0
  71. package/skills/android-display-glasses-with-jetpack-compose-glimmer/SKILL.md +340 -0
  72. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/design/ui/ai-glasses/guides/interaction/inputs.md +67 -0
  73. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/access-hardware-projected-context.md +388 -0
  74. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/jetpack-compose-glimmer/buttons.md +139 -0
  75. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/jetpack-compose-glimmer/cards.md +148 -0
  76. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/jetpack-compose-glimmer/focus.md +107 -0
  77. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/jetpack-compose-glimmer/icons.md +90 -0
  78. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/jetpack-compose-glimmer/text.md +69 -0
  79. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/jetpack-compose-glimmer/title-chips.md +82 -0
  80. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/android/develop/xr/jetpack-xr-sdk/request-hardware-permissions.md +213 -0
  81. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/button-samples-source.md +176 -0
  82. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/button-source.md +203 -0
  83. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/card-samples-source.md +296 -0
  84. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/card-source.md +515 -0
  85. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/deptheffect-source.md +224 -0
  86. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/deptheffectlevels-source.md +105 -0
  87. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/glimmersansflextypography-source.md +270 -0
  88. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/glimmertheme-source.md +182 -0
  89. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/icon-source.md +388 -0
  90. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/iconbutton-source.md +126 -0
  91. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/iconsizes-source.md +78 -0
  92. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/list-source.md +27 -0
  93. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/listitem-source.md +272 -0
  94. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/liststate-source.md +427 -0
  95. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/material-hct-source.md +217 -0
  96. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/projectedcontext-source.md +265 -0
  97. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/stack-source.md +368 -0
  98. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/stackitemscope-source.md +440 -0
  99. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/stackstate-source.md +325 -0
  100. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/surface-source.md +1211 -0
  101. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/titlechip-samples-source.md +101 -0
  102. package/skills/android-display-glasses-with-jetpack-compose-glimmer/references/titlechip-source.md +131 -0
  103. package/skills/android-edge-to-edge/SKILL.md +429 -0
  104. package/skills/android-engage-sdk-integration/SKILL.md +130 -0
  105. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/faq.md +439 -0
  106. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/food.md +1149 -0
  107. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/healthandfitness.md +1055 -0
  108. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/listen.md +1050 -0
  109. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/otherverticals.md +1301 -0
  110. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/read.md +910 -0
  111. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/shopping.md +1224 -0
  112. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/social.md +719 -0
  113. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/travel.md +1413 -0
  114. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/tv/continue-watching/index.md +19 -0
  115. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/tv/entitlements.md +353 -0
  116. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/tv/getting-started.md +202 -0
  117. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/tv/recommendations.md +471 -0
  118. package/skills/android-engage-sdk-integration/references/android/guide/playcore/engage/watch.md +1081 -0
  119. package/skills/android-engage-sdk-integration/references/clusters.md +154 -0
  120. package/skills/android-engage-sdk-integration/references/common.md +519 -0
  121. package/skills/android-engage-sdk-integration/references/patterns.md +527 -0
  122. package/skills/android-engage-sdk-integration/references/requests.md +260 -0
  123. package/skills/android-engage-sdk-integration/references/schemas/food.md +509 -0
  124. package/skills/android-engage-sdk-integration/references/schemas/listen.md +842 -0
  125. package/skills/android-engage-sdk-integration/references/schemas/other.md +220 -0
  126. package/skills/android-engage-sdk-integration/references/schemas/read.md +412 -0
  127. package/skills/android-engage-sdk-integration/references/schemas/shopping.md +357 -0
  128. package/skills/android-engage-sdk-integration/references/schemas/social.md +228 -0
  129. package/skills/android-engage-sdk-integration/references/schemas/travel.md +923 -0
  130. package/skills/android-engage-sdk-integration/references/schemas/tv.md +1226 -0
  131. package/skills/android-engage-sdk-integration/references/schemas/watch.md +1137 -0
  132. package/skills/android-engage-sdk-integration/references/troubleshooting.md +39 -0
  133. package/skills/android-gradle-build-debug/SKILL.md +71 -0
  134. package/skills/android-intent-security/SKILL.md +550 -0
  135. package/skills/android-leanback-to-compose-tv-migration/SKILL.md +743 -0
  136. package/skills/android-leanback-to-compose-tv-migration/references/android/training/tv/get-started/navigation.md +372 -0
  137. package/skills/android-leanback-to-compose-tv-migration/references/android/training/tv/playback/compose/browse.md +243 -0
  138. package/skills/android-leanback-to-compose-tv-migration/references/android/training/tv/playback/compose/index.md +153 -0
  139. package/skills/android-media3-cast-integration/SKILL.md +236 -0
  140. package/skills/android-media3-cast-integration/references/android/media/media3/cast/create-castplayer.md +390 -0
  141. package/skills/android-media3-cast-integration/references/android/media/media3/cast/customize-castoptions.md +93 -0
  142. package/skills/android-media3-cast-integration/references/android/media/media3/cast/index.md +21 -0
  143. package/skills/android-migrate-xml-views-to-jetpack-compose/SKILL.md +127 -0
  144. package/skills/android-migrate-xml-views-to-jetpack-compose/references/analysis-of-the-project-and-layout.md +42 -0
  145. package/skills/android-migrate-xml-views-to-jetpack-compose/references/android/develop/ui/compose/designsystems/migrate-xml-theme-to-compose.md +171 -0
  146. package/skills/android-migrate-xml-views-to-jetpack-compose/references/android/develop/ui/compose/migrate/interoperability-apis/compose-in-views.md +299 -0
  147. package/skills/android-migrate-xml-views-to-jetpack-compose/references/android/develop/ui/compose/migrate/interoperability-apis/views-in-compose.md +286 -0
  148. package/skills/android-migrate-xml-views-to-jetpack-compose/references/android/develop/ui/compose/setup-compose-dependencies-and-compiler.md +197 -0
  149. package/skills/android-migrate-xml-views-to-jetpack-compose/references/identify-optimal-xml-candidate.md +31 -0
  150. package/skills/android-migrate-xml-views-to-jetpack-compose/references/xml-layout-migration.md +86 -0
  151. package/skills/android-ml-kit-genai-prompt-api/SKILL.md +124 -0
  152. package/skills/android-ml-kit-genai-prompt-api/references/get-started.md +272 -0
  153. package/skills/android-ml-kit-genai-prompt-api/references/prefix-caching.md +146 -0
  154. package/skills/android-ml-kit-genai-prompt-api/references/prompt-design.md +55 -0
  155. package/skills/android-ml-kit-genai-prompt-api/references/prompt-optimization.md +74 -0
  156. package/skills/android-ml-kit-genai-prompt-api/references/structured-output.md +219 -0
  157. package/skills/android-ml-kit-genai-prompt-api/references/system-instructions.md +71 -0
  158. package/skills/android-navigation-3/SKILL.md +122 -0
  159. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/index.md +51 -0
  160. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/migration-guide.md +670 -0
  161. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/animations.md +147 -0
  162. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/basic.md +89 -0
  163. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/basicdsl.md +85 -0
  164. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/basicsaveable.md +90 -0
  165. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/bottomsheet.md +195 -0
  166. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/common-ui.md +200 -0
  167. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/conditional-transitions.md +182 -0
  168. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/conditional.md +230 -0
  169. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/deeplinks-custommatcher.md +176 -0
  170. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/deeplinks-staticuri.md +140 -0
  171. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/deeplinks-syntheticbackstack.md +184 -0
  172. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/dialog.md +107 -0
  173. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/lifecycle-owner.md +185 -0
  174. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/material-listdetail.md +141 -0
  175. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/material-supportingpane.md +145 -0
  176. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/modular-hilt.md +283 -0
  177. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/modular-koin.md +287 -0
  178. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/multiple-backstacks.md +468 -0
  179. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/passingarguments.md +371 -0
  180. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/results-event.md +273 -0
  181. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/results-state.md +266 -0
  182. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/scenes-listdetail.md +435 -0
  183. package/skills/android-navigation-3/references/android/guide/navigation/navigation-3/recipes/scenes-twopane.md +244 -0
  184. package/skills/android-navigation-3/references/android/guide/navigation/type-safe-destinations.md +129 -0
  185. package/skills/android-navigation-event/SKILL.md +312 -0
  186. package/skills/android-navigation-event/references/android/guide/navigation/navigation-event/dispatcher.md +134 -0
  187. package/skills/android-navigation-event/references/android/guide/navigation/navigation-event/handle-back.md +217 -0
  188. package/skills/android-navigation-event/references/android/guide/navigation/navigation-event/index.md +83 -0
  189. package/skills/android-navigation-event/references/android/guide/navigation/navigation-event/setup.md +32 -0
  190. package/skills/android-play-billing-library-version-upgrade/SKILL.md +96 -0
  191. package/skills/android-play-billing-library-version-upgrade/references/android/google/play/billing/release-notes.md +1240 -0
  192. package/skills/android-play-billing-library-version-upgrade/references/migration-logic.md +78 -0
  193. package/skills/android-play-billing-library-version-upgrade/references/version-checklist.md +54 -0
  194. package/skills/android-play-policy-insights/SKILL.md +172 -0
  195. package/skills/android-play-policy-insights/resources/common_mandates.md +100 -0
  196. package/skills/android-play-policy-insights/resources/compliance_report_template.md +59 -0
  197. package/skills/android-play-policy-insights/resources/critic.md +86 -0
  198. package/skills/android-play-policy-insights/resources/goal_data_safety.md +212 -0
  199. package/skills/android-play-policy-insights/resources/goal_permissions_and_apis.md +459 -0
  200. package/skills/android-play-policy-insights/resources/goal_user_account.md +106 -0
  201. package/skills/android-play-policy-insights/resources/policies.json +321 -0
  202. package/skills/android-play-policy-insights/resources/scanner_config.json +843 -0
  203. package/skills/android-play-policy-insights/scripts/generate_report.py +860 -0
  204. package/skills/android-play-policy-insights/scripts/orchestrator.py +1313 -0
  205. package/skills/android-play-policy-insights/scripts/play_store_scraper.py +410 -0
  206. package/skills/android-play-policy-insights/scripts/scanner.py +261 -0
  207. package/skills/android-play-policy-insights/scripts/template_engine.py +243 -0
  208. package/skills/android-profiler/SKILL.md +60 -0
  209. package/skills/android-profiler/analysis/analysis_orchestrator.md +32 -0
  210. package/skills/android-profiler/analysis/workflows/perfetto-sql/perfetto_sql.md +28 -0
  211. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/perfetto_trace_analysis.md +121 -0
  212. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/guiding_principles.md +51 -0
  213. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/domain_hints_template.md +7 -0
  214. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/subsystems/hints_cpu.md +56 -0
  215. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/subsystems/hints_graphics.md +51 -0
  216. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/subsystems/hints_io.md +46 -0
  217. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/subsystems/hints_ipc.md +41 -0
  218. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/subsystems/hints_memory.md +55 -0
  219. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/hints/subsystems/hints_power.md +33 -0
  220. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/per_candidate_analysis.md +172 -0
  221. package/skills/android-profiler/analysis/workflows/perfetto-trace-analysis/references/triage.md +94 -0
  222. package/skills/android-profiler/recording/recording_orchestrator.md +36 -0
  223. package/skills/android-profiler/recording/workflows/perfetto-trace-recording/perfetto_trace_recording.md +148 -0
  224. package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/app_jank.pftxt +43 -0
  225. package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/cpu_profile.pftxt +35 -0
  226. package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/java_heap_dump.pftxt +21 -0
  227. package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/long_background.pftxt +37 -0
  228. package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/memory_counters.pftxt +45 -0
  229. package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/native_heap.pftxt +21 -0
  230. package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/example-configs/sched_cpu.pftxt +33 -0
  231. package/skills/android-profiler/recording/workflows/perfetto-trace-recording/references/trace_config_reference.md +102 -0
  232. package/skills/android-profiler/references/env_setup.md +15 -0
  233. package/skills/android-profiler/references/perfetto/setup.md +29 -0
  234. package/skills/android-profiler/references/perfetto/sql.md +327 -0
  235. package/skills/android-r8-analyzer/SKILL.md +72 -0
  236. package/skills/android-r8-analyzer/references/CONFIGURATION-ANALYZER.md +287 -0
  237. package/skills/android-r8-analyzer/references/CONFIGURATION.md +44 -0
  238. package/skills/android-r8-analyzer/references/KEEP-RULES-IMPACT-HIERARCHY.md +83 -0
  239. package/skills/android-r8-analyzer/references/REDUNDANT-RULES.md +222 -0
  240. package/skills/android-r8-analyzer/references/REFLECTION-GUIDE.md +139 -0
  241. package/skills/android-r8-analyzer/references/REPORT_FORMAT.md +51 -0
  242. package/skills/android-r8-analyzer/references/android/topic/performance/app-optimization/enable-app-optimization.md +252 -0
  243. package/skills/android-r8-analyzer/references/android/training/testing/other-components/ui-automator.md +312 -0
  244. package/skills/android-restore-credentials/SKILL.md +359 -0
  245. package/skills/android-restore-credentials/references/android/guide/topics/manifest/application-element.md +832 -0
  246. package/skills/android-restore-credentials/references/android/identity/passkeys/create-passkeys.md +327 -0
  247. package/skills/android-restore-credentials/references/android/identity/passkeys/sign-in-with-passkeys.md +219 -0
  248. package/skills/android-styles/SKILL.md +229 -0
  249. package/skills/android-styles/references/android/develop/ui/compose/designsystems/custom.md +459 -0
  250. package/skills/android-styles/references/android/develop/ui/compose/styles/fundamentals.md +421 -0
  251. package/skills/android-styles/references/android/develop/ui/compose/styles/state-animations.md +461 -0
  252. package/skills/android-styles/references/android/develop/ui/compose/styles/styles-vs-modifiers.md +48 -0
  253. package/skills/android-styles/references/android/develop/ui/compose/styles/theming.md +269 -0
  254. package/skills/android-verified-email/SKILL.md +432 -0
  255. package/skills/android-verified-email/references/android/identity/credential-manager/index.md +67 -0
  256. package/skills/android-verified-email/references/android/identity/digital-credentials/credential-verifier.md +166 -0
  257. package/skills/android-verified-email/references/android/identity/digital-credentials/email-verification-implementation.md +313 -0
  258. package/skills/android-verified-email/references/android/identity/digital-credentials/email-verification.md +158 -0
  259. package/skills/android-verified-email/references/android/identity/digital-credentials/index.md +112 -0
  260. package/skills/android-verified-email/references/android/identity/passkeys/create-passkeys.md +327 -0
  261. package/skills/android-verified-email/references/android/identity/sign-in/credential-manager-webview.md +84 -0
  262. package/skills/android-wear-compose-m3/SKILL.md +365 -0
  263. package/skills/android-wear-compose-m3/references/android/training/wearables/compose/migrate-to-material3.md +677 -0
  264. package/skills/android-wear-compose-m3/references/foundation/AmbientModeSample.kt.md +123 -0
  265. package/skills/android-wear-compose-m3/references/foundation/AmbientModeSample.kt.md.txt +123 -0
  266. package/skills/android-wear-compose-m3/references/foundation/CurvedWorldSample.kt.md +430 -0
  267. package/skills/android-wear-compose-m3/references/foundation/CurvedWorldSample.kt.md.txt +430 -0
  268. package/skills/android-wear-compose-m3/references/foundation/ExpandableSample.kt.md +99 -0
  269. package/skills/android-wear-compose-m3/references/foundation/ExpandableSample.kt.md.txt +99 -0
  270. package/skills/android-wear-compose-m3/references/foundation/HierarchicalFocusSample.kt.md +141 -0
  271. package/skills/android-wear-compose-m3/references/foundation/HierarchicalFocusSample.kt.md.txt +141 -0
  272. package/skills/android-wear-compose-m3/references/foundation/PagerSamples.kt.md +56 -0
  273. package/skills/android-wear-compose-m3/references/foundation/PagerSamples.kt.md.txt +56 -0
  274. package/skills/android-wear-compose-m3/references/foundation/RotarySamples.kt.md +153 -0
  275. package/skills/android-wear-compose-m3/references/foundation/RotarySamples.kt.md.txt +153 -0
  276. package/skills/android-wear-compose-m3/references/foundation/ScalingLazyColumnSample.kt.md +131 -0
  277. package/skills/android-wear-compose-m3/references/foundation/ScalingLazyColumnSample.kt.md.txt +131 -0
  278. package/skills/android-wear-compose-m3/references/foundation/SwipeToDismissBoxSample.kt.md +169 -0
  279. package/skills/android-wear-compose-m3/references/foundation/SwipeToDismissBoxSample.kt.md.txt +169 -0
  280. package/skills/android-wear-compose-m3/references/foundation/SwipeToRevealSample.kt.md +282 -0
  281. package/skills/android-wear-compose-m3/references/foundation/SwipeToRevealSample.kt.md.txt +282 -0
  282. package/skills/android-wear-compose-m3/references/foundation/TransformingLazyColumnSample.kt.md +335 -0
  283. package/skills/android-wear-compose-m3/references/foundation/TransformingLazyColumnSample.kt.md.txt +335 -0
  284. package/skills/android-wear-compose-m3/references/material3/AlertDialogSample.kt.md +377 -0
  285. package/skills/android-wear-compose-m3/references/material3/AlertDialogSample.kt.md.txt +377 -0
  286. package/skills/android-wear-compose-m3/references/material3/AnimatedTextSample.kt.md +165 -0
  287. package/skills/android-wear-compose-m3/references/material3/AnimatedTextSample.kt.md.txt +165 -0
  288. package/skills/android-wear-compose-m3/references/material3/ButtonGroupSample.kt.md +91 -0
  289. package/skills/android-wear-compose-m3/references/material3/ButtonGroupSample.kt.md.txt +91 -0
  290. package/skills/android-wear-compose-m3/references/material3/ButtonSample.kt.md +496 -0
  291. package/skills/android-wear-compose-m3/references/material3/ButtonSample.kt.md.txt +496 -0
  292. package/skills/android-wear-compose-m3/references/material3/CardSample.kt.md +470 -0
  293. package/skills/android-wear-compose-m3/references/material3/CardSample.kt.md.txt +470 -0
  294. package/skills/android-wear-compose-m3/references/material3/CheckboxButtonSample.kt.md +67 -0
  295. package/skills/android-wear-compose-m3/references/material3/CheckboxButtonSample.kt.md.txt +67 -0
  296. package/skills/android-wear-compose-m3/references/material3/ConfirmationDialogSample.kt.md +162 -0
  297. package/skills/android-wear-compose-m3/references/material3/ConfirmationDialogSample.kt.md.txt +162 -0
  298. package/skills/android-wear-compose-m3/references/material3/CurvedTextSamples.kt.md +78 -0
  299. package/skills/android-wear-compose-m3/references/material3/CurvedTextSamples.kt.md.txt +78 -0
  300. package/skills/android-wear-compose-m3/references/material3/DatePickerSample.kt.md +131 -0
  301. package/skills/android-wear-compose-m3/references/material3/DatePickerSample.kt.md.txt +131 -0
  302. package/skills/android-wear-compose-m3/references/material3/DynamicColorSchemeSample.kt.md +74 -0
  303. package/skills/android-wear-compose-m3/references/material3/DynamicColorSchemeSample.kt.md.txt +74 -0
  304. package/skills/android-wear-compose-m3/references/material3/EdgeButtonSample.kt.md +63 -0
  305. package/skills/android-wear-compose-m3/references/material3/EdgeButtonSample.kt.md.txt +63 -0
  306. package/skills/android-wear-compose-m3/references/material3/FadingExpandingLabelSample.kt.md +60 -0
  307. package/skills/android-wear-compose-m3/references/material3/FadingExpandingLabelSample.kt.md.txt +60 -0
  308. package/skills/android-wear-compose-m3/references/material3/IconButtonSample.kt.md +125 -0
  309. package/skills/android-wear-compose-m3/references/material3/IconButtonSample.kt.md.txt +125 -0
  310. package/skills/android-wear-compose-m3/references/material3/IconToggleButtonSample.kt.md +116 -0
  311. package/skills/android-wear-compose-m3/references/material3/IconToggleButtonSample.kt.md.txt +116 -0
  312. package/skills/android-wear-compose-m3/references/material3/LevelIndicatorSample.kt.md +68 -0
  313. package/skills/android-wear-compose-m3/references/material3/LevelIndicatorSample.kt.md.txt +68 -0
  314. package/skills/android-wear-compose-m3/references/material3/LinearProgressIndicatorSample.kt.md +50 -0
  315. package/skills/android-wear-compose-m3/references/material3/LinearProgressIndicatorSample.kt.md.txt +50 -0
  316. package/skills/android-wear-compose-m3/references/material3/ListHeaderSample.kt.md +177 -0
  317. package/skills/android-wear-compose-m3/references/material3/ListHeaderSample.kt.md.txt +177 -0
  318. package/skills/android-wear-compose-m3/references/material3/OneHandedGestureSamples.kt.md +651 -0
  319. package/skills/android-wear-compose-m3/references/material3/OneHandedGestureSamples.kt.md.txt +651 -0
  320. package/skills/android-wear-compose-m3/references/material3/OpenOnPhoneDialogSample.kt.md +57 -0
  321. package/skills/android-wear-compose-m3/references/material3/OpenOnPhoneDialogSample.kt.md.txt +57 -0
  322. package/skills/android-wear-compose-m3/references/material3/PageIndicatorSample.kt.md +110 -0
  323. package/skills/android-wear-compose-m3/references/material3/PageIndicatorSample.kt.md.txt +110 -0
  324. package/skills/android-wear-compose-m3/references/material3/PagerScaffoldSample.kt.md +204 -0
  325. package/skills/android-wear-compose-m3/references/material3/PagerScaffoldSample.kt.md.txt +204 -0
  326. package/skills/android-wear-compose-m3/references/material3/PickerGroupSample.kt.md +139 -0
  327. package/skills/android-wear-compose-m3/references/material3/PickerGroupSample.kt.md.txt +139 -0
  328. package/skills/android-wear-compose-m3/references/material3/PickerSample.kt.md +111 -0
  329. package/skills/android-wear-compose-m3/references/material3/PickerSample.kt.md.txt +111 -0
  330. package/skills/android-wear-compose-m3/references/material3/PlaceholderSample.kt.md +184 -0
  331. package/skills/android-wear-compose-m3/references/material3/PlaceholderSample.kt.md.txt +184 -0
  332. package/skills/android-wear-compose-m3/references/material3/ProgressIndicatorSample.kt.md +263 -0
  333. package/skills/android-wear-compose-m3/references/material3/ProgressIndicatorSample.kt.md.txt +263 -0
  334. package/skills/android-wear-compose-m3/references/material3/RadioButtonSample.kt.md +105 -0
  335. package/skills/android-wear-compose-m3/references/material3/RadioButtonSample.kt.md.txt +105 -0
  336. package/skills/android-wear-compose-m3/references/material3/ScaffoldSample.kt.md +146 -0
  337. package/skills/android-wear-compose-m3/references/material3/ScaffoldSample.kt.md.txt +146 -0
  338. package/skills/android-wear-compose-m3/references/material3/ScrollAwaySample.kt.md +97 -0
  339. package/skills/android-wear-compose-m3/references/material3/ScrollAwaySample.kt.md.txt +97 -0
  340. package/skills/android-wear-compose-m3/references/material3/ScrollIndicatorSample.kt.md +66 -0
  341. package/skills/android-wear-compose-m3/references/material3/ScrollIndicatorSample.kt.md.txt +66 -0
  342. package/skills/android-wear-compose-m3/references/material3/SliderSample.kt.md +86 -0
  343. package/skills/android-wear-compose-m3/references/material3/SliderSample.kt.md.txt +86 -0
  344. package/skills/android-wear-compose-m3/references/material3/StepperSample.kt.md +148 -0
  345. package/skills/android-wear-compose-m3/references/material3/StepperSample.kt.md.txt +148 -0
  346. package/skills/android-wear-compose-m3/references/material3/SurfaceTransformationSample.kt.md +166 -0
  347. package/skills/android-wear-compose-m3/references/material3/SurfaceTransformationSample.kt.md.txt +166 -0
  348. package/skills/android-wear-compose-m3/references/material3/SwipeToDismissBoxSample.kt.md +172 -0
  349. package/skills/android-wear-compose-m3/references/material3/SwipeToDismissBoxSample.kt.md.txt +172 -0
  350. package/skills/android-wear-compose-m3/references/material3/SwipeToRevealSample.kt.md +367 -0
  351. package/skills/android-wear-compose-m3/references/material3/SwipeToRevealSample.kt.md.txt +367 -0
  352. package/skills/android-wear-compose-m3/references/material3/SwitchButtonSample.kt.md +66 -0
  353. package/skills/android-wear-compose-m3/references/material3/SwitchButtonSample.kt.md.txt +66 -0
  354. package/skills/android-wear-compose-m3/references/material3/TextButtonSample.kt.md +115 -0
  355. package/skills/android-wear-compose-m3/references/material3/TextButtonSample.kt.md.txt +115 -0
  356. package/skills/android-wear-compose-m3/references/material3/TextToggleButtonSample.kt.md +71 -0
  357. package/skills/android-wear-compose-m3/references/material3/TextToggleButtonSample.kt.md.txt +71 -0
  358. package/skills/android-wear-compose-m3/references/material3/TimePickerSample.kt.md +151 -0
  359. package/skills/android-wear-compose-m3/references/material3/TimePickerSample.kt.md.txt +151 -0
  360. package/skills/android-wear-compose-m3/references/material3/TimeTextSample.kt.md +65 -0
  361. package/skills/android-wear-compose-m3/references/material3/TimeTextSample.kt.md.txt +65 -0
  362. package/skills/android-wear-compose-m3/references/material3/TransformationSpecSample.kt.md +246 -0
  363. package/skills/android-wear-compose-m3/references/material3/TransformationSpecSample.kt.md.txt +246 -0
  364. package/skills/android-wear-compose-m3/references/material3/TransformingLazyColumnNotificationsSample.kt.md +89 -0
  365. package/skills/android-wear-compose-m3/references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt +89 -0
  366. package/skills/android-wear-compose-m3/references/material3/TransformingLazyColumnSample.kt.md +309 -0
  367. package/skills/android-wear-compose-m3/references/material3/TransformingLazyColumnSample.kt.md.txt +309 -0
  368. package/skills/android-wear-compose-m3/references/navigation3/SwipeDismissableSceneStrategySample.kt.md +205 -0
  369. package/skills/android-wear-compose-m3/references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt +205 -0
  370. package/skills/{architecture-feature-first → flutter-architecture-feature-first}/SKILL.md +1 -1
  371. package/skills/{bloc → flutter-bloc}/SKILL.md +1 -1
  372. package/skills/flutter-build-debug/SKILL.md +66 -0
  373. package/skills/{code-review → flutter-code-review}/SKILL.md +1 -1
  374. package/skills/{dart-3-updates → flutter-dart-3-updates}/SKILL.md +1 -1
  375. package/skills/{dart-fix-runtime-errors → flutter-dart-fix-runtime-errors}/SKILL.md +1 -1
  376. package/skills/{dart-resolve-package-conflicts → flutter-dart-resolve-package-conflicts}/SKILL.md +1 -1
  377. package/skills/{dart-run-static-analysis → flutter-dart-run-static-analysis}/SKILL.md +1 -1
  378. package/skills/{dart-use-pattern-matching → flutter-dart-use-pattern-matching}/SKILL.md +1 -1
  379. package/skills/{effective-dart → flutter-effective-dart}/SKILL.md +1 -1
  380. package/skills/{provider → flutter-provider}/SKILL.md +1 -1
  381. package/skills/{riverpod → flutter-riverpod}/SKILL.md +1 -1
  382. package/skills/ios-cocoapods-debug/SKILL.md +65 -0
  383. package/skills/ios-code-review/SKILL.md +56 -0
  384. package/skills/ios-xcode-build-debug/SKILL.md +66 -0
  385. package/skills/{detect-mobile-stack → mobile-detect-stack}/SKILL.md +1 -1
  386. package/skills/mobile-firebase/SKILL.md +54 -0
  387. package/skills/mobile-firebase/references/android/ai-logic.md +31 -0
  388. package/skills/mobile-firebase/references/android/analytics.md +33 -0
  389. package/skills/mobile-firebase/references/android/app-check.md +36 -0
  390. package/skills/mobile-firebase/references/android/auth.md +44 -0
  391. package/skills/mobile-firebase/references/android/crashlytics.md +31 -0
  392. package/skills/mobile-firebase/references/android/firestore.md +44 -0
  393. package/skills/mobile-firebase/references/android/functions.md +33 -0
  394. package/skills/mobile-firebase/references/android/in-app-messaging.md +28 -0
  395. package/skills/mobile-firebase/references/android/messaging.md +41 -0
  396. package/skills/mobile-firebase/references/android/realtime-database.md +50 -0
  397. package/skills/mobile-firebase/references/android/remote-config.md +43 -0
  398. package/skills/mobile-firebase/references/android/sql-connect.md +31 -0
  399. package/skills/mobile-firebase/references/android/storage.md +39 -0
  400. package/skills/mobile-firebase/references/android.md +30 -0
  401. package/skills/{firebase-ai/SKILL.md → mobile-firebase/references/flutter/ai-logic.md} +2 -8
  402. package/skills/{firebase-analytics/SKILL.md → mobile-firebase/references/flutter/analytics.md} +2 -8
  403. package/skills/{firebase-app-check/SKILL.md → mobile-firebase/references/flutter/app-check.md} +2 -8
  404. package/skills/{firebase-auth/SKILL.md → mobile-firebase/references/flutter/auth.md} +2 -8
  405. package/skills/{firebase-crashlytics/SKILL.md → mobile-firebase/references/flutter/crashlytics.md} +2 -8
  406. package/skills/{firebase-cloud-firestore/SKILL.md → mobile-firebase/references/flutter/firestore.md} +2 -8
  407. package/skills/{firebase-cloud-functions/SKILL.md → mobile-firebase/references/flutter/functions.md} +2 -8
  408. package/skills/{firebase-in-app-messaging/SKILL.md → mobile-firebase/references/flutter/in-app-messaging.md} +2 -8
  409. package/skills/{firebase-messaging/SKILL.md → mobile-firebase/references/flutter/messaging.md} +2 -8
  410. package/skills/{firebase-database/SKILL.md → mobile-firebase/references/flutter/realtime-database.md} +2 -8
  411. package/skills/{firebase-remote-config/SKILL.md → mobile-firebase/references/flutter/remote-config.md} +2 -8
  412. package/skills/{flutterfire-configure/SKILL.md → mobile-firebase/references/flutter/setup-flutterfire.md} +1 -8
  413. package/skills/{firebase-data-connect/SKILL.md → mobile-firebase/references/flutter/sql-connect.md} +2 -8
  414. package/skills/{firebase-storage/SKILL.md → mobile-firebase/references/flutter/storage.md} +2 -8
  415. package/skills/mobile-firebase/references/flutter.md +36 -0
  416. package/skills/mobile-firebase/references/ios/ai-logic.md +30 -0
  417. package/skills/mobile-firebase/references/ios/analytics.md +33 -0
  418. package/skills/mobile-firebase/references/ios/app-check.md +36 -0
  419. package/skills/mobile-firebase/references/ios/auth.md +48 -0
  420. package/skills/mobile-firebase/references/ios/crashlytics.md +34 -0
  421. package/skills/mobile-firebase/references/ios/firestore.md +53 -0
  422. package/skills/mobile-firebase/references/ios/functions.md +35 -0
  423. package/skills/mobile-firebase/references/ios/in-app-messaging.md +26 -0
  424. package/skills/mobile-firebase/references/ios/messaging.md +45 -0
  425. package/skills/mobile-firebase/references/ios/realtime-database.md +49 -0
  426. package/skills/mobile-firebase/references/ios/remote-config.md +44 -0
  427. package/skills/mobile-firebase/references/ios/sql-connect.md +33 -0
  428. package/skills/mobile-firebase/references/ios/storage.md +36 -0
  429. package/skills/mobile-firebase/references/ios.md +28 -0
  430. package/skills/mobile-firebase/references/react-native/ai-logic.md +32 -0
  431. package/skills/mobile-firebase/references/react-native/analytics.md +43 -0
  432. package/skills/mobile-firebase/references/react-native/app-check.md +35 -0
  433. package/skills/mobile-firebase/references/react-native/auth.md +50 -0
  434. package/skills/mobile-firebase/references/react-native/crashlytics.md +36 -0
  435. package/skills/mobile-firebase/references/react-native/firestore.md +45 -0
  436. package/skills/mobile-firebase/references/react-native/functions.md +28 -0
  437. package/skills/mobile-firebase/references/react-native/in-app-messaging.md +27 -0
  438. package/skills/mobile-firebase/references/react-native/messaging.md +46 -0
  439. package/skills/mobile-firebase/references/react-native/realtime-database.md +46 -0
  440. package/skills/mobile-firebase/references/react-native/remote-config.md +32 -0
  441. package/skills/mobile-firebase/references/react-native/sql-connect.md +11 -0
  442. package/skills/mobile-firebase/references/react-native/storage.md +30 -0
  443. package/skills/mobile-firebase/references/react-native.md +29 -0
  444. package/skills/mobile-test/SKILL.md +63 -0
  445. package/skills/mobile-test/references/android/setup/GUIDE.md +183 -0
  446. package/skills/mobile-test/references/android/setup/references/android/develop/ui/compose/testing/common-patterns.md +181 -0
  447. package/skills/mobile-test/references/android/setup/references/android/studio/preview/compose-screenshot-testing.md +255 -0
  448. package/skills/mobile-test/references/android/setup/references/android/training/dependency-injection/hilt-testing.md +447 -0
  449. package/skills/mobile-test/references/android.md +83 -0
  450. package/skills/{dart-collect-coverage/SKILL.md → mobile-test/references/flutter/coverage.md} +2 -11
  451. package/skills/{dart-generate-test-mocks/SKILL.md → mobile-test/references/flutter/generate-mocks.md} +2 -11
  452. package/skills/{flutter-add-integration-test/SKILL.md → mobile-test/references/flutter/integration-tests.md} +2 -11
  453. package/skills/{dart-migrate-to-checks-package/SKILL.md → mobile-test/references/flutter/migrate-to-checks.md} +2 -13
  454. package/skills/{mockito/SKILL.md → mobile-test/references/flutter/mockito.md} +1 -8
  455. package/skills/{mocktail/SKILL.md → mobile-test/references/flutter/mocktail.md} +1 -8
  456. package/skills/{patrol-e2e-testing/SKILL.md → mobile-test/references/flutter/patrol.md} +1 -8
  457. package/skills/{testing/SKILL.md → mobile-test/references/flutter/testing-guidelines.md} +1 -8
  458. package/skills/{dart-add-unit-test/SKILL.md → mobile-test/references/flutter/unit-tests.md} +2 -11
  459. package/skills/{flutter-add-widget-test/SKILL.md → mobile-test/references/flutter/widget-tests.md} +2 -11
  460. package/skills/mobile-test/references/flutter.md +44 -0
  461. package/skills/mobile-test/references/ios.md +79 -0
  462. package/skills/mobile-test/references/react-native.md +62 -0
  463. /package/skills/{dart-use-pattern-matching → flutter-dart-use-pattern-matching}/examples/json_patterns.dart +0 -0
@@ -0,0 +1,265 @@
1
+ When using a Projected Context to launch the Glasses Projected activity on the
2
+ Projected Device, refer to the following source code in `ProjectedContext.kt`:
3
+
4
+
5
+ ```kotlin
6
+ /*
7
+ * Copyright 2025 The Android Open Source Project
8
+ *
9
+ * Licensed under the Apache License, Version 2.0 (the "License");
10
+ * you may not use this file except in compliance with the License.
11
+ * You may obtain a copy of the License at
12
+ *
13
+ * http://www.apache.org/licenses/LICENSE-2.0
14
+ *
15
+ * Unless required by applicable law or agreed to in writing, software
16
+ * distributed under the License is distributed on an "AS IS" BASIS,
17
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ * See the License for the specific language governing permissions and
19
+ * limitations under the License.
20
+ */
21
+
22
+ package androidx.xr.projected
23
+
24
+ import android.app.ActivityOptions
25
+ import android.companion.virtual.VirtualDeviceManager
26
+ import android.content.Context
27
+ import android.hardware.display.DisplayManager
28
+ import android.hardware.display.DisplayManager.EVENT_TYPE_DISPLAY_ADDED
29
+ import android.hardware.display.DisplayManager.EVENT_TYPE_DISPLAY_CHANGED
30
+ import android.hardware.display.DisplayManager.EVENT_TYPE_DISPLAY_REMOVED
31
+ import android.os.Build
32
+ import androidx.annotation.RequiresApi
33
+ import androidx.annotation.VisibleForTesting
34
+ import androidx.xr.projected.experimental.ExperimentalProjectedApi
35
+ import kotlin.coroutines.CoroutineContext
36
+ import kotlinx.coroutines.CoroutineDispatcher
37
+ import kotlinx.coroutines.asExecutor
38
+ import kotlinx.coroutines.channels.awaitClose
39
+ import kotlinx.coroutines.flow.Flow
40
+ import kotlinx.coroutines.flow.callbackFlow
41
+ import kotlinx.coroutines.flow.distinctUntilChanged
42
+
43
+ /**
44
+ * Helper for accessing Projected device [Context] and its features.
45
+ *
46
+ * Projected device is an XR device connected to an Android device (host). Host can project the
47
+ * application content to the Projected device and let users interact with it.
48
+ *
49
+ * The Projected device context will ensure Projected device system services are returned, when
50
+ * queried for system services from this object.
51
+ *
52
+ * Note: The application context's deviceId can switch between the Projected and host deviceId
53
+ * depending on which activity was most recently in the foreground. Prefer using the Activity
54
+ * context to minimize the risk of running into this problem.
55
+ */
56
+ @ExperimentalProjectedApi
57
+ public object ProjectedContext {
58
+
59
+ private const val TAG = "ProjectedContext"
60
+
61
+ @VisibleForTesting internal const val PROJECTED_DEVICE_NAME = "ProjectionDevice"
62
+ @VisibleForTesting internal const val PROJECTED_DISPLAY_NAME = "ProjectionDisplay"
63
+
64
+ /**
65
+ * Explicitly create the Projected device context from any context object.
66
+ *
67
+ * @throws IllegalStateException if the projected device was not found.
68
+ */
69
+ @JvmStatic
70
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
71
+ public fun createProjectedDeviceContext(context: Context): Context {
72
+ val deviceId =
73
+ getProjectedDeviceId(context)
74
+ ?: throw IllegalStateException("Projected device not found.")
75
+ return context.createDeviceContext(deviceId)
76
+ }
77
+
78
+ /**
79
+ * Explicitly create the host device context from any context object. The host is the device
80
+ * that connects to a Projected device.
81
+ *
82
+ * If an application is using a Projected device context and it wants to use system services
83
+ * from the host (e.g. phone), it needs to use the host device context.
84
+ */
85
+ @JvmStatic
86
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
87
+ public fun createHostDeviceContext(context: Context): Context =
88
+ context.createDeviceContext(Context.DEVICE_ID_DEFAULT)
89
+
90
+ /**
91
+ * Returns the name of the Projected device or null if either virtual device wasn't found or the
92
+ * name of the virtual device wasn't set.
93
+ *
94
+ * @throws IllegalArgumentException If another context is used (e.g. the host context).
95
+ */
96
+ @JvmStatic
97
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
98
+ public fun getProjectedDeviceName(context: Context): String? =
99
+ // TODO: b/424812882 - Turn this into a lint check with an annotation.
100
+ if (isProjectedDeviceContext(context)) {
101
+ getVirtualDevice(context)?.name
102
+ } else {
103
+ throw IllegalArgumentException(
104
+ "Provided context is not the Projected device context. Can't get the device name."
105
+ )
106
+ }
107
+
108
+ /** Returns whether the provided context is the Projected device context. */
109
+ @JvmStatic
110
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
111
+ public fun isProjectedDeviceContext(context: Context): Boolean =
112
+ getVirtualDevice(context)?.name?.startsWith(PROJECTED_DEVICE_NAME) == true
113
+
114
+ /**
115
+ * Creates [ActivityOptions] that should be used to start an activity on the Projected device.
116
+ *
117
+ * @param context any [Context] object. If the provided context is not a Projected device
118
+ * context, a Projected device context will be created automatically and used to create
119
+ * Projected [ActivityOptions].
120
+ * @throws IllegalStateException if the projected display was not found or if the Projected
121
+ * device doesn't have any displays.
122
+ */
123
+ @JvmStatic
124
+ @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
125
+ public fun createProjectedActivityOptions(context: Context): ActivityOptions {
126
+ val projectedDeviceContext =
127
+ if (isProjectedDeviceContext(context)) {
128
+ context
129
+ } else {
130
+ createProjectedDeviceContext(context)
131
+ }
132
+
133
+ val projectedDisplayIds = getProjectedDisplayIds(projectedDeviceContext)
134
+
135
+ check(projectedDisplayIds.isNotEmpty()) { "Projected device doesn't have any displays." }
136
+
137
+ val projectedDisplay =
138
+ context.getSystemService(DisplayManager::class.java).displays.find {
139
+ it.name == PROJECTED_DISPLAY_NAME && projectedDisplayIds.contains(it.displayId)
140
+ } ?: throw IllegalStateException("No projected display found.")
141
+
142
+ return ActivityOptions.makeBasic().setLaunchDisplayId(projectedDisplay.displayId)
143
+ }
144
+
145
+ /**
146
+ * Observe whether a Projected device is connected to the host.
147
+ *
148
+ * @param context The context used to access the [VirtualDeviceManager]. It can be any context
149
+ * object.
150
+ * @param coroutineContext The CoroutineContext that includes CoroutineDispatcher which is where
151
+ * the Projected device connectivity observer is executed on.
152
+ * @throws IllegalArgumentException if provided coroutineContext doesn't include
153
+ * CoroutineDispatcher.
154
+ */
155
+ @JvmStatic
156
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
157
+ public fun isProjectedDeviceConnected(
158
+ context: Context,
159
+ coroutineContext: CoroutineContext,
160
+ ): Flow<Boolean> {
161
+ val hostContext = createHostDeviceContext(context)
162
+ return callbackFlow {
163
+ @OptIn(ExperimentalStdlibApi::class)
164
+ val coroutineDispatcher =
165
+ coroutineContext[CoroutineDispatcher]
166
+ ?: throw IllegalArgumentException(
167
+ "CoroutineContext must contain a CoroutineDispatcher."
168
+ )
169
+
170
+ fun checkAndSend() {
171
+ trySend(isProjectedDisplayAvailable(hostContext))
172
+ }
173
+
174
+ val virtualDeviceListener =
175
+ object : VirtualDeviceManager.VirtualDeviceListener {
176
+ override fun onVirtualDeviceCreated(deviceId: Int) {
177
+ checkAndSend()
178
+ }
179
+
180
+ override fun onVirtualDeviceClosed(deviceId: Int) {
181
+ checkAndSend()
182
+ }
183
+ }
184
+
185
+ val displayListener =
186
+ object : DisplayManager.DisplayListener {
187
+ override fun onDisplayAdded(displayId: Int) {
188
+ checkAndSend()
189
+ }
190
+
191
+ override fun onDisplayChanged(displayId: Int) {
192
+ checkAndSend()
193
+ }
194
+
195
+ override fun onDisplayRemoved(displayId: Int) {
196
+ checkAndSend()
197
+ }
198
+ }
199
+
200
+ checkAndSend()
201
+
202
+ val virtualDeviceManager =
203
+ hostContext.getSystemService(VirtualDeviceManager::class.java)
204
+ virtualDeviceManager.registerVirtualDeviceListener(
205
+ coroutineDispatcher.asExecutor(),
206
+ virtualDeviceListener,
207
+ )
208
+
209
+ val displayManager = hostContext.getSystemService(DisplayManager::class.java)
210
+ val eventFilter =
211
+ EVENT_TYPE_DISPLAY_ADDED or EVENT_TYPE_DISPLAY_CHANGED or EVENT_TYPE_DISPLAY_REMOVED
212
+ displayManager.registerDisplayListener(
213
+ coroutineDispatcher.asExecutor(),
214
+ eventFilter,
215
+ displayListener,
216
+ )
217
+
218
+ awaitClose {
219
+ virtualDeviceManager.unregisterVirtualDeviceListener(virtualDeviceListener)
220
+ displayManager.unregisterDisplayListener(displayListener)
221
+ }
222
+ }
223
+ .distinctUntilChanged()
224
+ }
225
+
226
+ @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
227
+ private fun isProjectedDisplayAvailable(context: Context): Boolean {
228
+ val projectedDeviceContext =
229
+ try {
230
+ createProjectedDeviceContext(context)
231
+ } catch (e: IllegalStateException) {
232
+ return false
233
+ }
234
+ val projectedDisplayIds = getProjectedDisplayIds(projectedDeviceContext)
235
+ if (projectedDisplayIds.isEmpty()) {
236
+ return false
237
+ }
238
+ val displayManager = context.getSystemService(DisplayManager::class.java)
239
+ return displayManager.displays.any {
240
+ it.name == PROJECTED_DISPLAY_NAME && projectedDisplayIds.contains(it.displayId)
241
+ }
242
+ }
243
+
244
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
245
+ private fun getProjectedDeviceId(context: Context) =
246
+ context
247
+ .getSystemService(VirtualDeviceManager::class.java)
248
+ .virtualDevices
249
+ // TODO: b/424824481 - Replace the name matching with a better method.
250
+ .find { it.name?.startsWith(PROJECTED_DEVICE_NAME) ?: false }
251
+ ?.deviceId
252
+
253
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
254
+ private fun getVirtualDevice(context: Context) =
255
+ context.getSystemService(VirtualDeviceManager::class.java).virtualDevices.find {
256
+ it.deviceId == context.deviceId
257
+ }
258
+
259
+ @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
260
+ private fun getProjectedDisplayIds(context: Context) =
261
+ getVirtualDevice(context)?.displayIds ?: IntArray(size = 0)
262
+ }
263
+ ```
264
+
265
+ <br />
@@ -0,0 +1,368 @@
1
+ When creating a Glimmer Stack component, refer to the following source code in
2
+ `Stack.kt`:
3
+
4
+
5
+ ```kotlin
6
+ /*
7
+ * Copyright 2025 The Android Open Source Project
8
+ *
9
+ * Licensed under the Apache License, Version 2.0 (the "License");
10
+ * you may not use this file except in compliance with the License.
11
+ * You may obtain a copy of the License at
12
+ *
13
+ * http://www.apache.org/licenses/LICENSE-2.0
14
+ *
15
+ * Unless required by applicable law or agreed to in writing, software
16
+ * distributed under the License is distributed on an "AS IS" BASIS,
17
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ * See the License for the specific language governing permissions and
19
+ * limitations under the License.
20
+ */
21
+
22
+ package androidx.xr.glimmer.stack
23
+
24
+ import androidx.compose.animation.core.VisibilityThreshold
25
+ import androidx.compose.animation.core.spring
26
+ import androidx.compose.foundation.layout.PaddingValues
27
+ import androidx.compose.foundation.pager.PagerDefaults
28
+ import androidx.compose.foundation.pager.PagerSnapDistance
29
+ import androidx.compose.foundation.pager.PagerState
30
+ import androidx.compose.foundation.pager.VerticalPager
31
+ import androidx.compose.runtime.Composable
32
+ import androidx.compose.runtime.derivedStateOf
33
+ import androidx.compose.runtime.referentialEqualityPolicy
34
+ import androidx.compose.runtime.remember
35
+ import androidx.compose.runtime.rememberUpdatedState
36
+ import androidx.compose.ui.Modifier
37
+ import androidx.compose.ui.draw.drawWithContent
38
+ import androidx.compose.ui.focus.FocusRequester
39
+ import androidx.compose.ui.focus.focusRequester
40
+ import androidx.compose.ui.focus.onFocusChanged
41
+ import androidx.compose.ui.geometry.Offset
42
+ import androidx.compose.ui.geometry.Size
43
+ import androidx.compose.ui.graphics.BlendMode
44
+ import androidx.compose.ui.graphics.Color
45
+ import androidx.compose.ui.input.nestedscroll.nestedScroll
46
+ import androidx.compose.ui.layout.Layout
47
+ import androidx.compose.ui.layout.onPlaced
48
+ import androidx.compose.ui.unit.dp
49
+ import androidx.compose.ui.util.fastFirstOrNull
50
+ import androidx.compose.ui.util.fastForEach
51
+ import androidx.compose.ui.util.fastMap
52
+ import androidx.compose.ui.util.lerp
53
+ import androidx.compose.ui.zIndex
54
+ import androidx.xr.glimmer.internal.SingleItemScrollConstraintConnection
55
+ import kotlin.math.roundToInt
56
+
57
+ /**
58
+ * [VerticalStack] is a lazy, vertically scrollable layout that arranges its items in a visually
59
+ * overlapping, three-dimensional sequence, which resembles a deck of cards. The primary item is
60
+ * prominently displayed in the foreground. Subsequent items are positioned behind the primary item
61
+ * along the z-axis with a small portion of the next item revealed to indicate depth and upcoming
62
+ * content.
63
+ *
64
+ * As the user scrolls vertically, the active foreground item transitions out of view, allowing the
65
+ * item immediately beneath it to slide into the prominent foreground position. Items always
66
+ * snap-animate into the foreground position after the user's gesture ends.
67
+ *
68
+ * Note: When displaying text within a [VerticalStack], it is strongly recommended to set
69
+ * [androidx.compose.ui.text.TextStyle.textMotion] to
70
+ * [androidx.compose.ui.text.style.TextMotion.Animated]. This ensures smooth rendering during layout
71
+ * animations or scaling transitions, preventing pixel-snapping artifacts.
72
+ *
73
+ * @sample androidx.xr.glimmer.samples.VerticalStackSample
74
+ * @param modifier the modifier to apply to this layout.
75
+ * @param state the state of the stack.
76
+ * @param content a block that describes the content. Inside this block you can use methods like
77
+ * [StackScope.item] to add a single item or [StackScope.items] to add a collection of items.
78
+ */
79
+ @Composable
80
+ public fun VerticalStack(
81
+ modifier: Modifier = Modifier,
82
+ state: StackState = rememberStackState(),
83
+ content: StackScope.() -> Unit,
84
+ ) {
85
+ val latestContent = rememberUpdatedState(content)
86
+ val stackItemHolderState =
87
+ remember(state) {
88
+ // Re-run the DSL to parse items only when the content lambda instance changes.
89
+ derivedStateOf(referentialEqualityPolicy()) {
90
+ StackItemHolder(state, latestContent.value).also {
91
+ // Set the item count on the StackState immediately when the derived state
92
+ // re-evaluates (i.e., when content changes), even before recomposition.
93
+ state.itemCount = it.itemCount
94
+ }
95
+ }
96
+ .also {
97
+ // This second assignment is necessary to force the derivedStateOf lambda above
98
+ // (which is executed lazily) to execute synchronously inside this block.
99
+ state.itemCount = it.value.itemCount
100
+ }
101
+ }
102
+
103
+ val singleItemScrollConstraintConnection =
104
+ remember(state.pagerState) { SingleItemScrollConstraintConnection(state.pagerState) }
105
+
106
+ VerticalPager(
107
+ state = state.pagerState,
108
+ modifier =
109
+ modifier
110
+ .then(StackInitialFocusElement(state))
111
+ .stackScrim()
112
+ .nestedScroll(singleItemScrollConstraintConnection),
113
+ contentPadding = PaddingValues(bottom = RevealAreaSize),
114
+ key = { page -> stackItemHolderState.value.getKey(page) },
115
+ beyondViewportPageCount = MaxNextVisibleItemCount,
116
+ flingBehavior =
117
+ PagerDefaults.flingBehavior(
118
+ state = state.pagerState,
119
+ pagerSnapDistance = PagerSnapDistance.atMost(1),
120
+ snapAnimationSpec = SnapAnimationSpec,
121
+ ),
122
+ ) { page ->
123
+ val stackItemHolder = stackItemHolderState.value
124
+ stackItemHolder.withInterval(page) { localIndex, itemInterval ->
125
+ val key =
126
+ itemInterval.getKeyOrDefault(globalIndex = page, localIntervalIndex = localIndex)
127
+ val itemScope = itemInterval.getOrCreateItemScope(key)
128
+ itemScope.index = page
129
+ StackItemLayout(page = page, state = state, itemScope = itemScope) {
130
+ itemInterval.item(itemScope, localIndex)
131
+ }
132
+ }
133
+ }
134
+ }
135
+
136
+ @Composable
137
+ private fun StackItemLayout(
138
+ page: Int,
139
+ state: StackState,
140
+ itemScope: StackItemScopeImpl,
141
+ modifier: Modifier = Modifier,
142
+ content: @Composable () -> Unit,
143
+ ) {
144
+ val focusRequester = remember { FocusRequester() }
145
+ Layout(
146
+ content = content,
147
+ modifier =
148
+ modifier
149
+ .zIndex(-page.toFloat())
150
+ .onPlaced { itemScope.coordinates = it }
151
+ .maskItemsBelow(state, itemScope)
152
+ .focusRequester(focusRequester)
153
+ .onFocusChanged { state.onItemFocusChanged(page, it) },
154
+ ) { measurables, constraints ->
155
+ var maxWidth = 0
156
+ var maxHeight = 0
157
+ val placeables = measurables.fastMap {
158
+ it.measure(constraints).also { placeable ->
159
+ maxWidth = maxOf(maxWidth, placeable.width)
160
+ maxHeight = maxOf(maxHeight, placeable.height)
161
+ }
162
+ }
163
+
164
+ if (!isLookingAhead) {
165
+ state.layoutInfoInternal.updateMeasuredHeight(index = page, height = maxHeight)
166
+ }
167
+
168
+ layout(maxWidth, maxHeight) {
169
+ placeables.fastForEach { placeable ->
170
+ placeable.placeRelativeWithLayer(x = 0, y = 0) {
171
+ val revealHeight = RevealAreaSize.roundToPx()
172
+ val topItem = state.topItem
173
+ when {
174
+ page.isTopItem(topItem = topItem) -> {
175
+ translationY =
176
+ state.topItemTranslationY(
177
+ revealHeight = revealHeight,
178
+ topItemHeight = placeable.height,
179
+ )
180
+
181
+ state.notifyAutoFocus(page, focusRequester)
182
+ }
183
+
184
+ page.isNextItem(topItem = topItem) -> {
185
+ translationY =
186
+ state.nextItemTranslationY(
187
+ revealHeight = revealHeight,
188
+ topItem = topItem,
189
+ nextItemHeight = placeable.height,
190
+ )
191
+ val scale = state.nextItemScale()
192
+ scaleX = scale
193
+ scaleY = scale
194
+
195
+ state.notifyAutoFocus(page, focusRequester)
196
+ }
197
+
198
+ page.isNextNextItem(topItem = topItem) -> {
199
+ translationY =
200
+ state.nextNextItemTranslationY(
201
+ revealHeight = revealHeight,
202
+ topItem = topItem,
203
+ nextNextItemHeight = placeable.height,
204
+ )
205
+ scaleX = NextItemMinScale
206
+ scaleY = NextItemMinScale
207
+ }
208
+ }
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Masks the items following the current item (items that are below the current item on Z-axis) if
217
+ * the item's decoration fills the viewport width.
218
+ */
219
+ private fun Modifier.maskItemsBelow(state: StackState, itemScope: StackItemScopeImpl): Modifier =
220
+ this.drawWithContent {
221
+ val viewportSize = state.layoutInfoInternal.viewportSize
222
+ val viewportWidth = viewportSize.width.toFloat()
223
+
224
+ if (itemScope.maskWidth >= (viewportWidth - DecorationWidthNoiseThresholdPx)) {
225
+ // Only apply the mask to the items below (Z-axis) if the mask fills the viewport width.
226
+ val viewportHeight = viewportSize.height.toFloat()
227
+ drawRect(
228
+ Color.Black,
229
+ blendMode = BlendMode.DstOut,
230
+ // The coordinate space here is for the item's layout, which changes position in the
231
+ // stack viewport depending on the scroll position. We need to deduct the viewport
232
+ // height to make the starting Y offset negative, so that the mask region extends
233
+ // upwards to the top of the stack viewport.
234
+ topLeft = Offset(x = 0f, y = itemScope.maskBottomY - viewportHeight),
235
+ size = Size(width = viewportWidth, height = viewportHeight),
236
+ )
237
+ }
238
+
239
+ drawContent()
240
+ }
241
+
242
+ /**
243
+ * The translation Y of the top item in pixels, which is always equal to the snapped position
244
+ * offset.
245
+ */
246
+ private fun StackState.topItemTranslationY(revealHeight: Int, topItemHeight: Int) =
247
+ calculateTopPositionOffset(topItemHeight, revealHeight)
248
+
249
+ /** The current translation Y of the next item in pixels. */
250
+ private fun StackState.nextItemTranslationY(
251
+ revealHeight: Int,
252
+ topItem: Int,
253
+ nextItemHeight: Int,
254
+ ): Float {
255
+ val nextPageOffset = pagerState.pageOffset(topItem + 1)
256
+ val progress = topItemOffsetFraction
257
+ val topItemHeight = layoutInfoInternal.measuredTopItemHeight
258
+
259
+ val topPageTopPositionOffset = calculateTopPositionOffset(topItemHeight, revealHeight)
260
+ val nextPageTopPositionOffset = calculateTopPositionOffset(nextItemHeight, revealHeight)
261
+
262
+ val topItemBottom = topPageTopPositionOffset + topItemHeight
263
+ // startOffset is the initial offset of the next item when it's revealed below the top item.
264
+ val startOffset =
265
+ calculateInitialBehindPosition(
266
+ itemAboveBottom = topItemBottom + revealHeight,
267
+ itemBehindHeight = nextItemHeight,
268
+ )
269
+
270
+ val currentOffset =
271
+ lerp(start = startOffset, stop = nextPageTopPositionOffset, fraction = progress)
272
+
273
+ return currentOffset - nextPageOffset
274
+ }
275
+
276
+ /** The current scale of the next item. */
277
+ private fun StackState.nextItemScale(): Float {
278
+ val progress = topItemOffsetFraction
279
+ return lerp(start = NextItemMinScale, stop = 1f, fraction = progress)
280
+ }
281
+
282
+ /** The current translation Y of the next-next item in pixels. */
283
+ private fun StackState.nextNextItemTranslationY(
284
+ revealHeight: Int,
285
+ topItem: Int,
286
+ nextNextItemHeight: Int,
287
+ ): Float {
288
+ val nextNextPageOffset = pagerState.pageOffset(topItem + 2)
289
+ val nextItemHeight = layoutInfoInternal.measuredNextItemHeight
290
+
291
+ // Calculate where the next item *would* be if it were currently the top item.
292
+ val nextItemTopPositionOffset = calculateTopPositionOffset(nextItemHeight, revealHeight)
293
+ val nextItemTopPositionBottom = nextItemTopPositionOffset + nextItemHeight
294
+
295
+ // Calculate the static target position the next-next item.
296
+ // We add revealHeight to nextItemBottom to ensure the item waits at the exact position
297
+ // where it will need to be when it transitions to being the next item.
298
+ val offset =
299
+ calculateInitialBehindPosition(
300
+ itemAboveBottom = nextItemTopPositionBottom + revealHeight,
301
+ itemBehindHeight = nextNextItemHeight,
302
+ )
303
+
304
+ return offset - nextNextPageOffset
305
+ }
306
+
307
+ /**
308
+ * Calculates the offset from the top of the viewport for an item of a given height for the item's
309
+ * top snapped position. Items are aligned to the bottom of the stack layout.
310
+ */
311
+ private fun StackState.calculateTopPositionOffset(itemHeight: Int, revealHeight: Int): Float {
312
+ val viewportHeight = layoutInfoInternal.viewportSize.height
313
+ return (viewportHeight - itemHeight - revealHeight).coerceAtLeast(0).toFloat()
314
+ }
315
+
316
+ /** Calculates the initial offset for an item when it is positioned behind the item above it. */
317
+ private fun calculateInitialBehindPosition(itemAboveBottom: Float, itemBehindHeight: Int): Float =
318
+ itemAboveBottom - itemBehindHeight * NextItemPositioningScale
319
+
320
+ /**
321
+ * The main axis offset of the item in pixels from the top of the viewport.
322
+ *
323
+ * If the page is in the visible list (inside the viewport), we return its exact offset. If it's not
324
+ * in the list but is composed (due to beyondViewportPageCount), we calculate where it *should* be
325
+ * based on the current page and offset fraction.
326
+ *
327
+ * Note: this method assumes that the Pager's layoutInfo is already available.
328
+ */
329
+ private fun PagerState.pageOffset(page: Int): Int {
330
+ val layoutInfo = layoutInfo
331
+
332
+ // First check if the page is already visible.
333
+ val visiblePage = layoutInfo.visiblePagesInfo.fastFirstOrNull { it.index == page }
334
+ if (visiblePage != null) return visiblePage.offset
335
+
336
+ // Calculate the distance in "pages" from the current snap position.
337
+ // (page - currentPage) gives the index distance.
338
+ // (- currentPageOffsetFraction) accounts for the sub-page scroll.
339
+ val offsetFromCurrentPage = page - currentPage - currentPageOffsetFraction
340
+ val stride = layoutInfo.pageSize + layoutInfo.pageSpacing
341
+ return (offsetFromCurrentPage * stride).roundToInt()
342
+ }
343
+
344
+ /** The size of the area where the items beneath the top of the stack item are revealed. */
345
+ internal val RevealAreaSize = 18.dp
346
+
347
+ /** The maximum number of items that can be visible at the same time in addition to the top item. */
348
+ private const val MaxNextVisibleItemCount = 2
349
+
350
+ /**
351
+ * The scale of the next item when it is fully behind the top item, and the default scale of the
352
+ * item behind it (the next-next item).
353
+ */
354
+ private const val NextItemMinScale = 0.94f
355
+
356
+ /** The scale factor that's between 1.0 and [NextItemMinScale], which is used in positioning. */
357
+ private const val NextItemPositioningScale = 0.97f // (1f + NextItemMinScale) / 2f
358
+
359
+ /** The animation spec used for snapping stack items. */
360
+ private val SnapAnimationSpec =
361
+ spring(
362
+ dampingRatio = 0.56f,
363
+ stiffness = 118f,
364
+ visibilityThreshold = Int.VisibilityThreshold.toFloat(),
365
+ )
366
+ ```
367
+
368
+ <br />