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,200 @@
1
+ # Common UI Recipe
2
+
3
+ This recipe demonstrates how to implement a common navigation UI pattern with a bottom navigation bar and multiple back stacks, where each tab in the navigation bar has its own navigation history.
4
+
5
+ ## How it works
6
+
7
+ This example has three top-level destinations: `Home`, `ChatList`, and `Camera`. The `ChatList` destination also has a sub-route, `ChatDetail`.
8
+
9
+ ### `TopLevelBackStack`
10
+
11
+ The core of this recipe is the `TopLevelBackStack` class, which is responsible for managing the navigation state. It works as follows:
12
+
13
+ - It maintains a separate back stack for each top-level destination (tab).
14
+ - It keeps track of the currently selected top-level destination.
15
+ - It provides a single, flattened back stack that can be used by the `NavDisplay` composable. This flattened back stack is a combination of the individual back stacks of all the tabs.
16
+
17
+ ### UI Structure
18
+
19
+ The UI is built using a `Scaffold` composable, with a `NavigationBar` as the `bottomBar`.
20
+
21
+ - The `NavigationBar` displays an item for each top-level destination. When an item is clicked, it calls `topLevelBackStack.addTopLevel` to switch to the corresponding tab, preserving the navigation history of each tab.
22
+ - The `NavDisplay` composable is placed in the content area of the `Scaffold`. It is responsible for displaying the current screen based on the flattened back stack provided by `TopLevelBackStack`.
23
+
24
+ This approach allows for a common navigation pattern where users can switch between different sections of the app, and each section maintains its own navigation history.
25
+
26
+ ### State Preservation
27
+
28
+ It's important to note how the navigation state is managed in this recipe. When a user navigates away from a top-level destination (e.g., by pressing the back button until they return to a previous tab), the entire navigation history for that destination is cleared. The state is not saved. When the user returns to that tab later, they will start from its initial screen.
29
+
30
+ **Note** : In this example, the `Home` route can move above the `ChatList` and `Camera` routes, meaning navigating back from `Home` doesn't necessarily leave the app. The app will exit when the user goes back from a single remaining top level route in the back stack.
31
+ [![](https://developer.android.com/static/images/picto-icons/code.svg) Explore View the full recipe on GitHub.](https://github.com/android/nav3-recipes/tree/main/app/src/main/java/com/example/nav3recipes/commonui)
32
+
33
+ ```
34
+ /*
35
+ * Copyright 2025 The Android Open Source Project
36
+ *
37
+ * Licensed under the Apache License, Version 2.0 (the "License");
38
+ * you may not use this file except in compliance with the License.
39
+ * You may obtain a copy of the License at
40
+ *
41
+ * http://www.apache.org/licenses/LICENSE-2.0
42
+ *
43
+ * Unless required by applicable law or agreed to in writing, software
44
+ * distributed under the License is distributed on an "AS IS" BASIS,
45
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
46
+ * See the License for the specific language governing permissions and
47
+ * limitations under the License.
48
+ */
49
+
50
+ package com.example.nav3recipes.commonui
51
+
52
+ import android.os.Bundle
53
+ import androidx.activity.ComponentActivity
54
+ import androidx.activity.compose.setContent
55
+ import androidx.compose.material.icons.Icons
56
+ import androidx.compose.material.icons.filled.Face
57
+ import androidx.compose.material.icons.filled.Home
58
+ import androidx.compose.material.icons.filled.PlayArrow
59
+ import androidx.compose.material3.Button
60
+ import androidx.compose.material3.Icon
61
+ import androidx.compose.material3.NavigationBar
62
+ import androidx.compose.material3.NavigationBarItem
63
+ import androidx.compose.material3.Scaffold
64
+ import androidx.compose.material3.Text
65
+ import androidx.compose.runtime.getValue
66
+ import androidx.compose.runtime.mutableStateListOf
67
+ import androidx.compose.runtime.mutableStateOf
68
+ import androidx.compose.runtime.remember
69
+ import androidx.compose.runtime.setValue
70
+ import androidx.compose.runtime.snapshots.SnapshotStateList
71
+ import androidx.compose.ui.graphics.vector.ImageVector
72
+ import androidx.lifecycle.compose.dropUnlessResumed
73
+ import androidx.navigation3.runtime.entryProvider
74
+ import androidx.navigation3.ui.NavDisplay
75
+ import com.example.nav3recipes.content.ContentBlue
76
+ import com.example.nav3recipes.content.ContentGreen
77
+ import com.example.nav3recipes.content.ContentPurple
78
+ import com.example.nav3recipes.content.ContentRed
79
+ import com.example.nav3recipes.ui.setEdgeToEdgeConfig
80
+
81
+ private sealed interface TopLevelRoute {
82
+ val icon: ImageVector
83
+ }
84
+ private data object Home : TopLevelRoute { override val icon = Icons.Default.Home }
85
+ private data object ChatList : TopLevelRoute { override val icon = Icons.Default.Face }
86
+ private data object ChatDetail
87
+ private data object Camera : TopLevelRoute { override val icon = Icons.Default.PlayArrow }
88
+
89
+ private val TOP_LEVEL_ROUTES : List<TopLevelRoute> = listOf(Home, ChatList, Camera)
90
+
91
+ class CommonUiActivity : ComponentActivity() {
92
+ override fun onCreate(savedInstanceState: Bundle?) {
93
+ setEdgeToEdgeConfig()
94
+ super.onCreate(savedInstanceState)
95
+ setContent {
96
+ val topLevelBackStack = remember { TopLevelBackStack<Any>(Home) }
97
+
98
+ Scaffold(
99
+ bottomBar = {
100
+ NavigationBar {
101
+ TOP_LEVEL_ROUTES.forEach { topLevelRoute ->
102
+
103
+ val isSelected = topLevelRoute == topLevelBackStack.topLevelKey
104
+ NavigationBarItem(
105
+ selected = isSelected,
106
+ onClick = {
107
+ topLevelBackStack.addTopLevel(topLevelRoute)
108
+ },
109
+ icon = {
110
+ Icon(
111
+ imageVector = topLevelRoute.icon,
112
+ contentDescription = null
113
+ )
114
+ }
115
+ )
116
+ }
117
+ }
118
+ }
119
+ ) { _ ->
120
+ NavDisplay(
121
+ backStack = topLevelBackStack.backStack,
122
+ onBack = { topLevelBackStack.removeLast() },
123
+ entryProvider = entryProvider {
124
+ entry<Home>{
125
+ ContentRed("Home screen")
126
+ }
127
+ entry<ChatList>{
128
+ ContentGreen("Chat list screen"){
129
+ Button(onClick = dropUnlessResumed {
130
+ topLevelBackStack.add(ChatDetail)
131
+ }) {
132
+ Text("Go to conversation")
133
+ }
134
+ }
135
+ }
136
+ entry<ChatDetail>{
137
+ ContentBlue("Chat detail screen")
138
+ }
139
+ entry<Camera>{
140
+ ContentPurple("Camera screen")
141
+ }
142
+ },
143
+ )
144
+ }
145
+ }
146
+ }
147
+ }
148
+
149
+ class TopLevelBackStack<T: Any>(startKey: T) {
150
+
151
+ // Maintain a stack for each top level route
152
+ private var topLevelStacks : LinkedHashMap<T, SnapshotStateList<T>> = linkedMapOf(
153
+ startKey to mutableStateListOf(startKey)
154
+ )
155
+
156
+ // Expose the current top level route for consumers
157
+ var topLevelKey by mutableStateOf(startKey)
158
+ private set
159
+
160
+ // Expose the back stack so it can be rendered by the NavDisplay
161
+ val backStack = mutableStateListOf(startKey)
162
+
163
+ private fun updateBackStack() =
164
+ backStack.apply {
165
+ clear()
166
+ addAll(topLevelStacks.flatMap { it.value })
167
+ }
168
+
169
+ fun addTopLevel(key: T){
170
+
171
+ // If the top level doesn't exist, add it
172
+ if (topLevelStacks[key] == null){
173
+ topLevelStacks.put(key, mutableStateListOf(key))
174
+ } else {
175
+ // Otherwise just move it to the end of the stacks
176
+ topLevelStacks.apply {
177
+ remove(key)?.let {
178
+ put(key, it)
179
+ }
180
+ }
181
+ }
182
+ topLevelKey = key
183
+ updateBackStack()
184
+ }
185
+
186
+ fun add(key: T){
187
+ topLevelStacks[topLevelKey]?.add(key)
188
+ updateBackStack()
189
+ }
190
+
191
+ fun removeLast(){
192
+ val removedKey = topLevelStacks[topLevelKey]?.removeLastOrNull()
193
+ // If the removed key was a top level key, remove the associated top level stack
194
+ topLevelStacks.remove(removedKey)
195
+ topLevelKey = topLevelStacks.keys.last()
196
+ updateBackStack()
197
+ }
198
+ }
199
+
200
+ ```
@@ -0,0 +1,182 @@
1
+ # Conditional Transitions Recipe
2
+
3
+ This recipe demonstrates how to create route-dependent screen transitions in Navigation 3 using `transitionSpec` and `popTransitionSpec`. The slide directions (right, left, bottom, top) are conditionally selected based on pairs of `initialState` and `targetState` navigation keys.
4
+
5
+ ## How it works
6
+
7
+ - **Route Definitions** : Navigation destinations (`Step1`, `Step2`, `Step3`, `Step4`) are defined using a sealed class hierarchy implementing `NavKey` and marked with `@Serializable`.
8
+ - **Conditional Forward Transitions (`transitionSpec`)** : Matches pairs of `(initialKey to targetKey)` to determine the direction of the slide animation:
9
+ - `Step1` $\\rightarrow$ `Step2`: Swipes to the left
10
+ - `Step2` $\\rightarrow$ `Step3`: Swipes to the up
11
+ - `Step3` $\\rightarrow$ `Step4`: Swipes to the right
12
+ - `Step4` $\\rightarrow$ `Step1`: Slides to the bottom (restarts flow)
13
+ - **Conditional Pop Transitions (`popTransitionSpec`)**: Handles reverse slide directions when navigating back or when clearing the backstack.
14
+ - **Backstack Control** : Demonstrates clearing the navigation stack on the final step (`backStack.clear()` \& `backStack.add(Step1)`) while executing a seamless top-slide transition.
15
+
16
+ [![](https://developer.android.com/static/images/picto-icons/code.svg) Explore View the full recipe on GitHub.](https://github.com/android/nav3-recipes/tree/main/app/src/main/java/com/example/nav3recipes/conditionaltransitions)
17
+
18
+ ```
19
+ package com.example.nav3recipes.conditionaltransitions
20
+
21
+ import android.os.Bundle
22
+ import androidx.activity.ComponentActivity
23
+ import androidx.activity.compose.setContent
24
+ import androidx.compose.animation.ContentTransform
25
+ import androidx.compose.animation.slideInHorizontally
26
+ import androidx.compose.animation.slideInVertically
27
+ import androidx.compose.animation.slideOutHorizontally
28
+ import androidx.compose.animation.slideOutVertically
29
+ import androidx.compose.animation.togetherWith
30
+ import androidx.compose.foundation.layout.Arrangement
31
+ import androidx.compose.foundation.layout.Column
32
+ import androidx.compose.foundation.layout.Row
33
+ import androidx.compose.foundation.layout.fillMaxSize
34
+ import androidx.compose.foundation.layout.fillMaxWidth
35
+ import androidx.compose.foundation.layout.padding
36
+ import androidx.compose.material3.ElevatedButton
37
+ import androidx.compose.material3.Scaffold
38
+ import androidx.compose.material3.Text
39
+ import androidx.compose.runtime.Composable
40
+ import androidx.compose.ui.Alignment
41
+ import androidx.compose.ui.Modifier
42
+ import androidx.navigation3.runtime.NavKey
43
+ import androidx.navigation3.runtime.entryProvider
44
+ import androidx.navigation3.runtime.rememberNavBackStack
45
+ import androidx.navigation3.ui.NavDisplay
46
+ import com.example.nav3recipes.content.ContentGreen
47
+ import com.example.nav3recipes.content.ContentOrange
48
+ import com.example.nav3recipes.content.ContentPurple
49
+ import com.example.nav3recipes.content.ContentRed
50
+ import com.example.nav3recipes.sharedviewmodel.toContentKey
51
+ import com.example.nav3recipes.ui.setEdgeToEdgeConfig
52
+ import dagger.hilt.android.AndroidEntryPoint
53
+ import kotlinx.serialization.Serializable
54
+
55
+ @Serializable
56
+ sealed class Step(val firstButtonTitle: String, val secondButtonTitle: String) : NavKey
57
+
58
+ @Serializable
59
+ data object Step1 : Step("Home", "Swipe left")
60
+
61
+ @Serializable
62
+ data object Step2 : Step("Swipe right", "Swipe up")
63
+
64
+ @Serializable
65
+ data object Step3 : Step("Swipe down", "Swipe right")
66
+
67
+ @Serializable
68
+ data object Step4 : Step("Swipe left", "Swipe down")
69
+
70
+ @AndroidEntryPoint
71
+ class ConditionalTransitionsActivity : ComponentActivity() {
72
+
73
+ override fun onCreate(savedInstanceState: Bundle?) {
74
+ super.onCreate(savedInstanceState)
75
+ setEdgeToEdgeConfig()
76
+
77
+ setContent {
78
+ Scaffold { paddingValues ->
79
+ val backStack = rememberNavBackStack(Step1)
80
+
81
+ NavDisplay(
82
+ backStack = backStack,
83
+ modifier = Modifier.padding(paddingValues),
84
+ onBack = backStack::removeLastOrNull,
85
+ entryProvider = entryProvider {
86
+ entry<Step1> {
87
+ ContentGreen(title = "Screen 1") {
88
+ StepContent(
89
+ step = it,
90
+ onNext = { backStack += Step2 },
91
+ onBack = ::finish, // closing the activity
92
+ )
93
+ }
94
+
95
+ }
96
+ entry<Step2> {
97
+ ContentRed(title = "Screen 2") {
98
+ StepContent(
99
+ step = it,
100
+ onNext = { backStack += Step3 },
101
+ onBack = backStack::removeLastOrNull,
102
+ )
103
+ }
104
+ }
105
+ entry<Step3> {
106
+ ContentOrange(title = "Screen 3") {
107
+ StepContent(
108
+ step = it,
109
+ onNext = { backStack += Step4 },
110
+ onBack = backStack::removeLastOrNull,
111
+ )
112
+ }
113
+ }
114
+ entry<Step4> {
115
+ ContentPurple(title = "Screen 4") {
116
+ StepContent(
117
+ step = it,
118
+ onNext = {
119
+ backStack.clear()
120
+ backStack.add(Step1)
121
+ },
122
+ onBack = backStack::removeLastOrNull,
123
+ )
124
+ }
125
+ }
126
+ },
127
+ transitionSpec = {
128
+ val initialKey = initialState.entries.lastOrNull()?.contentKey
129
+ val targetKey = targetState.entries.lastOrNull()?.contentKey
130
+
131
+ when (initialKey to targetKey) {
132
+ Step1.toContentKey() to Step2.toContentKey() -> swipeLeft()
133
+ Step2.toContentKey() to Step3.toContentKey() -> swipeUp()
134
+ Step3.toContentKey() to Step4.toContentKey() -> swipeRight()
135
+ Step4.toContentKey() to Step1.toContentKey() -> swipeDown()
136
+ else -> swipeRight()
137
+ }
138
+ },
139
+ popTransitionSpec = {
140
+ val initialKey = initialState.entries.lastOrNull()?.contentKey
141
+ val targetKey = targetState.entries.lastOrNull()?.contentKey
142
+
143
+ when (initialKey to targetKey) {
144
+ Step4.toContentKey() to Step1.toContentKey() -> swipeDown() // via backstack clearing
145
+ Step2.toContentKey() to Step1.toContentKey() -> swipeRight()
146
+ Step3.toContentKey() to Step2.toContentKey() -> swipeDown()
147
+ Step4.toContentKey() to Step3.toContentKey() -> swipeLeft()
148
+ else -> swipeLeft()
149
+ }
150
+ },
151
+ )
152
+ }
153
+ }
154
+ }
155
+ }
156
+
157
+ @Composable
158
+ fun StepContent(step: Step, onNext: () -> Unit, onBack: () -> Unit) {
159
+ Column(
160
+ verticalArrangement = Arrangement.SpaceEvenly,
161
+ horizontalAlignment = Alignment.CenterHorizontally,
162
+ modifier = Modifier.fillMaxSize()
163
+ ) {
164
+ Row(horizontalArrangement = Arrangement.SpaceEvenly, modifier = Modifier.fillMaxWidth()) {
165
+ ElevatedButton(onBack) { Text(text = step.firstButtonTitle) }
166
+ ElevatedButton(onNext) { Text(text = step.secondButtonTitle) }
167
+ }
168
+ }
169
+ }
170
+
171
+ private fun swipeLeft(): ContentTransform =
172
+ slideInHorizontally(initialOffsetX = { it }) togetherWith slideOutHorizontally(targetOffsetX = { -it })
173
+
174
+ private fun swipeUp(): ContentTransform =
175
+ slideInVertically(initialOffsetY = { it }) togetherWith slideOutVertically(targetOffsetY = { -it })
176
+
177
+ private fun swipeRight(): ContentTransform =
178
+ slideInHorizontally(initialOffsetX = { -it }) togetherWith slideOutHorizontally(targetOffsetX = { it })
179
+
180
+ private fun swipeDown(): ContentTransform =
181
+ slideInVertically(initialOffsetY = { -it }) togetherWith slideOutVertically(targetOffsetY = { it })
182
+ ```
@@ -0,0 +1,230 @@
1
+ # Conditional Navigation Recipe
2
+
3
+ This recipe demonstrates how to implement conditional navigation, where certain destinations are only accessible if a condition is met (in this case, if the user is logged in).
4
+
5
+ ## How it works
6
+
7
+ This example has a `Profile` destination that requires the user to be logged in. If the user is not logged in and attempts to navigate to `Profile`, they are redirected to a `Login` screen. After a successful login, they are automatically navigated to the `Profile` screen.
8
+
9
+ ### `AppBackStack`
10
+
11
+ The core of this recipe is the custom `AppBackStack` class, which encapsulates the logic for conditional navigation.
12
+
13
+ - **`RequiresLogin` interface** : A marker interface, `RequiresLogin`, is used to identify destinations that require the user to be logged in. The `Profile` destination implements this interface.
14
+
15
+ - **Redirecting to Login** : When the `add` function is called with a destination that implements `RequiresLogin` and the user is not logged in, `AppBackStack` stores the intended destination and adds the `Login` route to the back stack instead.
16
+
17
+ - **Handling Login** : When the `login` function is called, it sets the user's status to logged in. If there is a stored destination that the user was trying to access, it adds that destination to the back stack and removes the `Login` screen.
18
+
19
+ - **Handling Logout** : When the `logout` function is called, it sets the user's status to logged out and removes any destinations from the back stack that require the user to be logged in.
20
+
21
+ This approach provides a clean way to handle conditional navigation by centralizing the logic in a custom back stack implementation.
22
+ [![](https://developer.android.com/static/images/picto-icons/code.svg) Explore View the full recipe on GitHub.](https://github.com/android/nav3-recipes/tree/main/app/src/main/java/com/example/nav3recipes/conditional)
23
+
24
+ ```
25
+ /*
26
+ * Copyright 2025 The Android Open Source Project
27
+ *
28
+ * Licensed under the Apache License, Version 2.0 (the "License");
29
+ * you may not use this file except in compliance with the License.
30
+ * You may obtain a copy of the License at
31
+ *
32
+ * http://www.apache.org/licenses/LICENSE-2.0
33
+ *
34
+ * Unless required by applicable law or agreed to in writing, software
35
+ * distributed under the License is distributed on an "AS IS" BASIS,
36
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
37
+ * See the License for the specific language governing permissions and
38
+ * limitations under the License.
39
+ */
40
+
41
+ package com.example.nav3recipes.conditional
42
+
43
+ import android.os.Bundle
44
+ import androidx.activity.ComponentActivity
45
+ import androidx.activity.compose.setContent
46
+ import androidx.compose.foundation.layout.Column
47
+ import androidx.compose.material3.Button
48
+ import androidx.compose.material3.Text
49
+ import androidx.compose.runtime.Composable
50
+ import androidx.compose.runtime.getValue
51
+ import androidx.compose.runtime.mutableStateOf
52
+ import androidx.compose.runtime.remember
53
+ import androidx.compose.runtime.saveable.rememberSaveable
54
+ import androidx.compose.runtime.saveable.rememberSerializable
55
+ import androidx.compose.runtime.setValue
56
+ import androidx.lifecycle.compose.dropUnlessResumed
57
+ import androidx.navigation3.runtime.NavBackStack
58
+ import androidx.navigation3.runtime.NavKey
59
+ import androidx.navigation3.runtime.entryProvider
60
+ import androidx.navigation3.runtime.serialization.NavBackStackSerializer
61
+ import androidx.navigation3.runtime.serialization.NavKeySerializer
62
+ import androidx.navigation3.ui.NavDisplay
63
+ import com.example.nav3recipes.content.ContentBlue
64
+ import com.example.nav3recipes.content.ContentGreen
65
+ import com.example.nav3recipes.content.ContentYellow
66
+ import com.example.nav3recipes.ui.setEdgeToEdgeConfig
67
+ import kotlinx.serialization.Serializable
68
+
69
+
70
+ /**
71
+ * Class for representing navigation keys in the app.
72
+ *
73
+ * Note: We use a sealed class because KotlinX Serialization handles
74
+ * polymorphic serialization of sealed classes automatically.
75
+ *
76
+ * @param requiresLogin - true if the navigation key requires that the user is logged in
77
+ * to navigate to it
78
+ */
79
+ @Serializable
80
+ sealed class ConditionalNavKey(val requiresLogin: Boolean = false) : NavKey
81
+
82
+ /**
83
+ * Key representing home screen
84
+ */
85
+ @Serializable
86
+ private data object Home : ConditionalNavKey()
87
+
88
+ /**
89
+ * Key representing profile screen that is only accessible once the user has logged in
90
+ */
91
+ @Serializable
92
+ private data object Profile : ConditionalNavKey(requiresLogin = true)
93
+
94
+ /**
95
+ * Key representing login screen
96
+ *
97
+ * @param redirectToKey - navigation key to redirect to after successful login
98
+ */
99
+ @Serializable
100
+ private data class Login(
101
+ val redirectToKey: ConditionalNavKey? = null
102
+ ) : ConditionalNavKey()
103
+
104
+ class ConditionalActivity : ComponentActivity() {
105
+
106
+ override fun onCreate(savedInstanceState: Bundle?) {
107
+ setEdgeToEdgeConfig()
108
+ super.onCreate(savedInstanceState)
109
+ setContent {
110
+
111
+ val backStack = rememberNavBackStack<ConditionalNavKey>(Home)
112
+ var isLoggedIn by rememberSaveable {
113
+ mutableStateOf(false)
114
+ }
115
+ val navigator = remember {
116
+ Navigator(
117
+ backStack = backStack,
118
+ onNavigateToRestrictedKey = { redirectToKey -> Login(redirectToKey) },
119
+ isLoggedIn = { isLoggedIn }
120
+ )
121
+ }
122
+
123
+ NavDisplay(
124
+ backStack = backStack,
125
+ onBack = { navigator.goBack() },
126
+ entryProvider = entryProvider {
127
+ entry<Home> {
128
+ ContentGreen("Welcome to Nav3. Logged in? ${isLoggedIn}") {
129
+ Column {
130
+ Button(onClick = dropUnlessResumed { navigator.navigate(Profile) }) {
131
+ Text("Profile")
132
+ }
133
+ Button(onClick = dropUnlessResumed { navigator.navigate(Login()) }) {
134
+ Text("Login")
135
+ }
136
+ }
137
+ }
138
+ }
139
+ entry<Profile> {
140
+ ContentBlue("Profile screen (only accessible once logged in)") {
141
+ Button(onClick = dropUnlessResumed {
142
+ isLoggedIn = false
143
+ navigator.navigate(Home)
144
+ }) {
145
+ Text("Logout")
146
+ }
147
+ }
148
+ }
149
+ entry<Login> { key ->
150
+ ContentYellow("Login screen. Logged in? $isLoggedIn") {
151
+ Button(onClick = dropUnlessResumed {
152
+ isLoggedIn = true
153
+ key.redirectToKey?.let { targetKey ->
154
+ backStack.remove(key)
155
+ navigator.navigate(targetKey)
156
+ }
157
+ }) {
158
+ Text("Login")
159
+ }
160
+ }
161
+ }
162
+ }
163
+ )
164
+ }
165
+ }
166
+ }
167
+
168
+
169
+ // An overload of `rememberNavBackStack` that returns a subtype of `NavKey`.
170
+ // See https://issuetracker.google.com/issues/463382671 for a discussion of this function
171
+ @Composable
172
+ fun <T : NavKey> rememberNavBackStack(vararg elements: T): NavBackStack<T> {
173
+ return rememberSerializable(
174
+ serializer = NavBackStackSerializer(elementSerializer = NavKeySerializer())
175
+ ) {
176
+ NavBackStack(*elements)
177
+ }
178
+ }
179
+ ```
180
+
181
+ ```
182
+ /*
183
+ * Copyright 2025 The Android Open Source Project
184
+ *
185
+ * Licensed under the Apache License, Version 2.0 (the "License");
186
+ * you may not use this file except in compliance with the License.
187
+ * You may obtain a copy of the License at
188
+ *
189
+ * http://www.apache.org/licenses/LICENSE-2.0
190
+ *
191
+ * Unless required by applicable law or agreed to in writing, software
192
+ * distributed under the License is distributed on an "AS IS" BASIS,
193
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
194
+ * See the License for the specific language governing permissions and
195
+ * limitations under the License.
196
+ */
197
+
198
+ package com.example.nav3recipes.conditional
199
+
200
+ import androidx.navigation3.runtime.NavBackStack
201
+
202
+ /**
203
+ * Provides navigation events with built-in support for conditional access. If the user attempts to
204
+ * navigate to a [ConditionalNavKey] that requires login ([ConditionalNavKey.requiresLogin] is true)
205
+ * but is not currently logged in, the Navigator will redirect the user to a login key.
206
+ *
207
+ * @property backStack The back stack that is modified by this class
208
+ * @property onNavigateToRestrictedKey A lambda that is called when the user attempts to navigate
209
+ * to a key that requires login. This should return the key that represents the login screen. The
210
+ * user's target key is supplied as a parameter so that after successful login the user can be
211
+ * redirected to their target destination.
212
+ * @property isLoggedIn A lambda that returns whether the user is logged in.
213
+ */
214
+ class Navigator(
215
+ private val< backStack: NavBa>ckStackConditionalNavKey,
216
+ private val onNavigateToRestrictedKey: (targetKe>y: ConditionalNavKey?) - ConditionalNavKey,
217
+ priv>ate val isLoggedIn: () - Boolean,
218
+ ) {
219
+ fun navigate(key: ConditionalNavKey) {
220
+ && if (key.requiresLogin !isLoggedIn()) {
221
+ val loginKey = onNavigateToRestrictedKey(key)
222
+ backStack.add(loginKey)
223
+ } else {
224
+ backStack.add(key)
225
+ }
226
+ }
227
+
228
+ fun goBack() = backStstOrNull()
229
+ }Navigator.kt
230
+ ```