Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
253 commits
Select commit Hold shift + click to select a range
97f4c52
feat(permission): implement storage permission handling using Activit…
rosuH Sep 2, 2024
a03fa5d
feat(permission): refactor storage permission handling methods and in…
rosuH Sep 2, 2024
39f2293
fix(gradle): update patch version to 3
rosuH Sep 2, 2024
a287fd4
refactor: Migrate to Jetpack Compose.
rosuH Sep 4, 2024
315c247
refactor: migrate dependency injection from Hilt to Koin
rosuH Apr 13, 2025
e328b55
refactor: enhance dialog animations and refactor AboutViewModel initi…
rosuH Apr 13, 2025
fc67357
feat: integrate system photo picker for media selection
rosuH Apr 13, 2025
6cf2b73
chore: update dependencies to latest versions
rosuH Aug 20, 2025
2918732
refactor(EditorScreen): enhance tab animation logic
rosuH Aug 20, 2025
c20e12f
refactor(ui): update layout rendering and bottom sheet handling for c…
rosuH Aug 24, 2025
2d21169
Merge branch 'master' into feat/migrate_to_compose
rosuH Aug 30, 2025
d3427ac
Merge branch 'master' into feat/migrate_to_compose
rosuH Aug 30, 2025
a4b0b9c
Merge branch 'master' into feat/migrate_to_compose
rosuH Aug 30, 2025
8dac890
feat: enable edge-to-edge display and remove BottomSurface
rosuH Aug 30, 2025
0426ecd
refactor(ui): update state management to remember option list and sta…
rosuH Aug 30, 2025
58fcb6f
refactor(ui): simplify EditorScreen layout and clean up obsolete stat…
rosuH Aug 31, 2025
100998e
chore(android): bump dependencies and migrate deprecated apis
rosuH Apr 17, 2026
ab0f891
**feat(ui): add navigation to About screen in main activity**
rosuH Apr 18, 2026
f7a0608
feat(compose): add callback to pick more images
rosuH Apr 19, 2026
ccf3c2e
docs: CMP migration plan, ADRs, parity backlog, AI-friendly repo scaf…
rosuH Jun 13, 2026
19fedd0
feat(compose): align UI with production v2.10.0
rosuH Jun 13, 2026
8f10667
feat(compose): migrate About/OpenSource screens + consolidate ACTION_…
rosuH Jun 13, 2026
7f0ff69
chore: pre-existing working-tree changes (engine/export WIP)
rosuH Jun 13, 2026
2c64e4e
feat(compose): port crash-recovery screen to Compose + fix share-in r…
rosuH Jun 13, 2026
e7432f4
docs: record crash-recovery real-device verification + PR #377; corre…
rosuH Jun 13, 2026
eed74af
feat(compose): migrate watermark-template surface to Compose (Templat…
rosuH Jun 13, 2026
b7dca76
docs: template migration done + full legacy-deletion map; migration f…
rosuH Jun 13, 2026
5248985
refactor(compose): retire legacy View/Fragment/Activity stack (ADR-0016)
rosuH Jun 13, 2026
066a125
docs: mark View→Compose migration complete (ADR-0016 Implemented, CLA…
rosuH Jun 13, 2026
4b6d9f8
chore(res): remove 22 orphaned legacy layout XMLs
rosuH Jun 13, 2026
3ccc264
chore(res): remove 8 unreferenced legacy anim XMLs (ADR-0016 follow-up)
rosuH Jun 13, 2026
f5e9038
feat(nav): typed @Serializable routes (CMP plan C1.2 / D3)
rosuH Jun 13, 2026
d07e03d
refactor(model): platform-neutral ImageFormat enum (CMP plan D7)
rosuH Jun 13, 2026
175f201
docs(progress): record XML cleanup done + first 3 CMP foundations (C1…
rosuH Jun 13, 2026
0a53e6c
refactor(about): AboutViewModel LiveData -> StateFlow (CMP plan C1.1)
rosuH Jun 13, 2026
f7f8d68
docs(parity): record compress + bg-palette as un-migrated feature gap…
rosuH Jun 13, 2026
3969414
feat(kmp): introduce :shared Kotlin Multiplatform module (commonMain …
rosuH Jun 13, 2026
57320f7
refactor(kmp): move Result + JobState to :shared/commonMain
rosuH Jun 13, 2026
ad16ce7
docs: record :shared KMP module landed (CLAUDE.md current-state, prog…
rosuH Jun 13, 2026
82b9635
feat(kmp): add iOS targets to :shared — now compiles Android + JVM + iOS
rosuH Jun 13, 2026
7657c3a
docs: :shared now compiles Android + JVM + iOS (CLAUDE.md, progress)
rosuH Jun 13, 2026
cf2bd54
test(kmp): commonTest harness in :shared — multiplatform tests for sh…
rosuH Jun 13, 2026
42d944b
fix(test): repair SharedModelTest jobState assertion (=== on distinct…
rosuH Jun 13, 2026
1b88403
ci: run :shared multiplatform tests (JVM) on PR (CMP plan C1.8)
rosuH Jun 13, 2026
288f33e
feat(kmp): watermark cell geometry -> :shared/commonMain (CMP plan C2…
rosuH Jun 13, 2026
16c5893
feat(kmp): runnable :desktopApp — shared engine core RUNS on Desktop …
rosuH Jun 13, 2026
85c031c
docs: record geometry core + runnable :desktopApp (CLAUDE.md, progress)
rosuH Jun 13, 2026
334bd91
feat(kmp): add corrected export scale rule to commonMain portable cor…
rosuH Jun 13, 2026
81c515e
test(golden): validate Robolectric NATIVE JVM rasterization — C1.7 gr…
rosuH Jun 13, 2026
9a4db8c
test(golden): JVM watermark-cell golden + commonMain geometry equival…
rosuH Jun 13, 2026
e09ff00
fix(golden)+ci: plain test Application (no Koin double-start) + run a…
rosuH Jun 13, 2026
bd3a59a
docs: C1.7 golden foundation landed; C2a wiring reverted (dimension-g…
rosuH Jun 13, 2026
efa722b
test(golden): upgrade to PIXEL-level golden — composite tiled cell + …
rosuH Jun 13, 2026
133da5f
test(golden): pin Robolectric emoji+rotation rendering gap (C1.7 find…
rosuH Jun 13, 2026
2aef9ac
docs: record Robolectric emoji/rotation golden gap → C1.7 needs instr…
rosuH Jun 13, 2026
7f0da28
fix(golden): correct sampling (size to cell dims) — emoji/rotation DO…
rosuH Jun 13, 2026
ff5461e
docs: correct the Robolectric emoji finding (was my sampling bug); bo…
rosuH Jun 13, 2026
8f4f117
docs: correct C2a verdict to UNDETERMINED — 'wiring broke preview' wa…
rosuH Jun 13, 2026
9f9eb6e
feat(c2a): wire live renderer to commonMain WatermarkGeometry — engin…
rosuH Jun 13, 2026
60d5312
docs: C2a RESOLVED (done+verified); root cause was lost READ_MEDIA_IM…
rosuH Jun 13, 2026
f8aa6d6
feat(c2a): wire icon-cell sizing to commonMain too + remove the now-d…
rosuH Jun 13, 2026
d780c2b
docs: C2a cell-sizing done (text+icon, both preview+export paths) wir…
rosuH Jun 13, 2026
b18c643
test: add watermark migration safety gates
rosuH Jun 14, 2026
934cd15
Merge pull request #377 from rosuH/feat/compose-about-share-parity
rosuH Jun 14, 2026
04fd6bb
refactor: extract Android watermark renderer seam
rosuH Jun 14, 2026
6df5864
Merge pull request #378 from rosuH/codex/s2a-watermark-renderer-extra…
rosuH Jun 14, 2026
0115f18
Implement image-space text sizing
rosuH Jun 14, 2026
7d80926
Merge pull request #379 from rosuH/codex/s3a-image-space-textsize
rosuH Jun 14, 2026
eac461f
Adopt TextMeasurer for watermark text measurement
rosuH Jun 14, 2026
62db7b2
Merge pull request #380 from rosuH/codex/s3b-textmeasurer-cjk-baseline
rosuH Jun 14, 2026
fc411b0
Decouple export from preview ViewInfo
rosuH Jun 15, 2026
a81dc7f
Merge pull request #381 from rosuH/codex/s3c1-export-viewinfo-decouple
rosuH Jun 15, 2026
6fb31ea
Replace watermark preview with Compose canvas
rosuH Jun 15, 2026
30898dd
Fix compose preview shader draw guard
rosuH Jun 15, 2026
fc3cdce
Merge pull request #382 from rosuH/codex/s3c2-compose-canvas-preview
rosuH Jun 15, 2026
c8b07ef
Document repo agent skill configuration
rosuH Jun 15, 2026
d9cc3e4
Retire legacy watermark preview
rosuH Jun 15, 2026
86fa73e
Polish compose preview interactions
rosuH Jun 16, 2026
dc5359d
Refresh migration planning state
rosuH Jun 16, 2026
5f0c1ee
Document agent workflow loop
rosuH Jun 16, 2026
3ae6c20
Document tmux worker routing
rosuH Jun 16, 2026
a13d259
Document bounded worker polling
rosuH Jun 16, 2026
9b70170
Add strict renderer golden gate
rosuH Jun 16, 2026
ea31b40
Document compose lineage blocker
rosuH Jun 16, 2026
2055265
Document C4.3 lineage plan
rosuH Jun 16, 2026
393c951
Unify compose dependency lineage
rosuH Jun 16, 2026
5837db6
Add commonMain watermark cell composer
rosuH Jun 16, 2026
0a8efa6
Add commonMain watermark text raster bootstrap
rosuH Jun 17, 2026
d13c7f1
Add commonMain icon raster bootstrap
rosuH Jun 17, 2026
ef1da72
Add renderer parity gate for commonMain cells
rosuH Jun 17, 2026
60289af
Advance KMP renderer and iOS migration
rosuH Jun 26, 2026
1623241
Move watermark config model to shared
rosuH Jun 26, 2026
7c9b37b
Extract watermark config rules to shared
rosuH Jun 26, 2026
3af3f28
Record S4d-62 state boundary decision
rosuH Jun 26, 2026
a9f9a0e
Retire duplicate watermark LiveData wrappers
rosuH Jun 26, 2026
42813af
Convert save result to StateFlow
rosuH Jun 26, 2026
4fac98a
Convert compressed result to StateFlow
rosuH Jun 26, 2026
112fe77
Convert save process to StateFlow
rosuH Jun 26, 2026
a2f529c
Remove dead save image uri state
rosuH Jun 26, 2026
9e85741
Retire image list LiveData wrapper
rosuH Jun 26, 2026
10fcb86
Convert gallery picked state to StateFlow
rosuH Jun 26, 2026
62855fd
Record S4d-70 migration readiness
rosuH Jun 26, 2026
35e2ff0
Move ImageInfo to commonMain
rosuH Jun 26, 2026
f9b38c0
Share watermark config commands
rosuH Jun 26, 2026
59eb6e0
Add shared DataStore creation helper
rosuH Jun 26, 2026
bcebf2b
Document shared DataStore creation seam
rosuH Jun 26, 2026
94aaf90
Move user preferences model to shared
rosuH Jun 26, 2026
e8e861e
Move user config repository to shared
rosuH Jun 26, 2026
f8759b6
Document shared user config migration
rosuH Jun 26, 2026
258ace1
Add desktop and iOS DataStore creators
rosuH Jun 26, 2026
1e023e7
Document desktop and iOS DataStore stores
rosuH Jun 26, 2026
3daa7c4
Wire desktop user config repository
rosuH Jun 26, 2026
675bde2
Document desktop user config wiring
rosuH Jun 26, 2026
6408a27
Add iOS user config bridge
rosuH Jun 26, 2026
c3d22f7
Document iOS user config bridge
rosuH Jun 26, 2026
98e13d9
Retain iOS user config bridge in Swift
rosuH Jun 26, 2026
ee3fcb9
Document iOS Swift user config bridge retention
rosuH Jun 26, 2026
a69d314
Decouple WaterMarkRepository trivial Android edges
rosuH Jun 26, 2026
4c7ed69
Use okio IOException in WaterMarkRepository
rosuH Jun 26, 2026
16884b3
Inject WaterMarkRepository default text provider
rosuH Jun 27, 2026
1489d70
Inject WaterMarkRepository tile mode mapper
rosuH Jun 27, 2026
54636cf
Inject WaterMarkRepository log callback
rosuH Jun 27, 2026
f23bf5d
Move WaterMarkRepository to shared
rosuH Jun 27, 2026
14a947d
Document WaterMarkRepository shared migration
rosuH Jun 27, 2026
93db510
Prove shared Room KMP toolchain
rosuH Jun 27, 2026
8d245d9
Move template Room path to shared
rosuH Jun 27, 2026
73b902f
Document Room templates commonMain move
rosuH Jun 27, 2026
7ee7e77
Extract watermark config editor use case
rosuH Jun 27, 2026
8892009
Document watermark config editor use case
rosuH Jun 27, 2026
ec9317c
Extract output prefs editor use case
rosuH Jun 27, 2026
b1fd665
Document output prefs editor use case
rosuH Jun 27, 2026
d26c95b
Extract template editor use case
rosuH Jun 27, 2026
b7da43c
Document template editor use case
rosuH Jun 27, 2026
f73abef
Document lifecycle ViewModel readiness decision
rosuH Jun 27, 2026
b700588
Add iOS persisted watermark text bridge
rosuH Jun 27, 2026
f77dc66
Document iOS watermark text editor closeout
rosuH Jun 27, 2026
a6090b5
Wire iOS watermark degree editor
rosuH Jun 27, 2026
bf7551b
Wire iOS watermark tile mode editor
rosuH Jun 27, 2026
e34508a
Wire iOS watermark alpha editor
rosuH Jun 27, 2026
8fedfcb
Document iOS watermark editor fields
rosuH Jun 27, 2026
9da981a
Wire iOS watermark text color
rosuH Jun 27, 2026
61a931e
Document iOS render default decision
rosuH Jun 27, 2026
6761ab7
Wire iOS watermark text size
rosuH Jun 27, 2026
419aa19
Wire iOS watermark gaps
rosuH Jun 27, 2026
2f83950
Document iOS renderer capability decision
rosuH Jun 27, 2026
60460e8
Honor iOS watermark typeface
rosuH Jun 27, 2026
6f55fbe
Document iOS typeface honoring
rosuH Jun 27, 2026
8e42680
Honor iOS watermark text style
rosuH Jun 27, 2026
4b0f24f
Document iOS text style honoring
rosuH Jun 27, 2026
054636b
Document iOS icon markMode readiness
rosuH Jun 27, 2026
d8e71bb
Add iOS icon render path
rosuH Jun 27, 2026
e2f240d
Document iOS icon render path
rosuH Jun 27, 2026
676b741
Add iOS icon persistence
rosuH Jun 27, 2026
87da34f
Document iOS icon persistence
rosuH Jun 27, 2026
5c3afc8
Add iOS mark mode render branch
rosuH Jun 27, 2026
76f2308
Document iOS mark mode render branch
rosuH Jun 27, 2026
02beb95
Add iOS icon picker UI
rosuH Jun 27, 2026
4e56dcf
Document iOS icon picker UI
rosuH Jun 27, 2026
7583099
Add Desktop headless save flow
rosuH Jun 27, 2026
bf4e7a4
Document Desktop headless save flow
rosuH Jun 27, 2026
6c4ffdd
Add Desktop minimal window
rosuH Jun 27, 2026
411ccb7
Document Desktop minimal window
rosuH Jun 27, 2026
4e4d928
Add Desktop text color parity
rosuH Jun 27, 2026
bc0b53b
Document Desktop text color parity
rosuH Jun 27, 2026
2ec876d
Honor shared text draw style
rosuH Jun 27, 2026
299ff5f
Document shared text draw style honoring
rosuH Jun 27, 2026
822a448
Add Desktop image file picker
rosuH Jun 27, 2026
a0986b9
Add Desktop format-aware encoder
rosuH Jun 27, 2026
b354452
Wire Desktop output prefs into save flow
rosuH Jun 27, 2026
b2fae70
Add Desktop output preference presets
rosuH Jun 27, 2026
202f74f
Add Desktop icon composition primitive
rosuH Jun 27, 2026
3bc2b82
Add Desktop icon save flow branch
rosuH Jun 27, 2026
b58fd4b
Add Desktop icon picker control
rosuH Jun 27, 2026
eafc683
Add Desktop text mode toggle
rosuH Jun 27, 2026
0e4e2cc
Add Desktop current image memory
rosuH Jun 27, 2026
6d2dce9
Document Desktop product readiness map
rosuH Jun 27, 2026
c078b7f
Add Desktop save decision seam
rosuH Jun 27, 2026
7905fee
Add Desktop save-as destination
rosuH Jun 27, 2026
ed9e38e
Add Desktop template database builder
rosuH Jun 27, 2026
07ac7b6
Add Desktop templates headless witness
rosuH Jun 27, 2026
0333c76
Document Desktop templates persistence
rosuH Jun 27, 2026
e62cf2a
Add Desktop custom watermark text input
rosuH Jun 27, 2026
ef3a6ae
Add Desktop manual preview
rosuH Jun 27, 2026
05a6dba
Add Desktop degree control
rosuH Jun 27, 2026
f68a2de
Add Desktop text color control
rosuH Jun 27, 2026
52a765e
Add Desktop opacity control
rosuH Jun 27, 2026
209d2fb
Add Desktop gap controls
rosuH Jun 27, 2026
81f4a90
Add Desktop text size control
rosuH Jun 27, 2026
a869095
Add Desktop tile mode toggle
rosuH Jun 27, 2026
9d87d3f
Add Desktop text enum controls
rosuH Jun 27, 2026
5bc2c49
Make Desktop window scrollable
rosuH Jun 27, 2026
6c239b0
Add Desktop share substitute
rosuH Jun 27, 2026
18c84f8
Add Desktop drag-drop input
rosuH Jun 27, 2026
66f6e08
Add Desktop templates UI
rosuH Jun 27, 2026
4f2d335
Record Desktop templates UI closeout
rosuH Jun 27, 2026
bb5e770
Polish Desktop release hygiene
rosuH Jun 27, 2026
ccc9f3f
Add Desktop packaging proof
rosuH Jun 27, 2026
343b86d
Record Desktop packaging closeout
rosuH Jun 27, 2026
789c794
Add Desktop CI packaging workflow
rosuH Jun 27, 2026
264e552
Merge origin/master into feat/migrate_to_compose (S4d-169: resolve PR…
rosuH Jun 28, 2026
572f4c7
test: harden desktop CJK renderer golden
rosuH Jun 28, 2026
7f5ef49
ci: drop strict pinned golden from PR checks
rosuH Jun 28, 2026
055b574
docs: record PR checks unblock
rosuH Jun 28, 2026
ccda193
desktop: use app version for package
rosuH Jun 28, 2026
8d36d9f
build: single-source app version
rosuH Jun 28, 2026
fd380a9
shared: dedupe image format extensions
rosuH Jun 28, 2026
78d8425
shared: dedupe alpha percent display
rosuH Jun 28, 2026
7da3f8a
shared: centralize watermark font sizing
rosuH Jun 28, 2026
e91587b
android: use shared watermark font sizing
rosuH Jun 28, 2026
69023b0
android: reuse shared icon scale constant
rosuH Jun 28, 2026
08455b7
Single-source watermark default fallbacks
rosuH Jun 28, 2026
81d36f5
Document sizing and default single-sourcing
rosuH Jun 28, 2026
ee8ba5f
Delete dead renderer REF_WIDTH
rosuH Jun 28, 2026
07e6670
Document Android composition no-go
rosuH Jun 28, 2026
e281c57
Document MainViewModel IO no-go
rosuH Jun 28, 2026
f09c6e2
Add iOS renderer perceptual gate
rosuH Jun 28, 2026
1d4915f
Add iOS composition perceptual gate
rosuH Jun 28, 2026
9493eff
Consolidate Compose text style mappings
rosuH Jun 28, 2026
1f0019b
Add Desktop reactive preview refresh
rosuH Jun 28, 2026
56a39fa
Document Desktop reactive preview closeout
rosuH Jun 28, 2026
7fa34b9
Fix Desktop renderer stale KDoc
rosuH Jun 28, 2026
3c7b586
fix: align about cluster with production parity
rosuH Jun 28, 2026
84bdbaf
Document watermark density closeout
rosuH Jun 28, 2026
873dbcb
Route Desktop window state to user data dir
rosuH Jun 28, 2026
685a0bd
Document Desktop window persistence closeout
rosuH Jun 28, 2026
ce677bb
Route Desktop saves to user output dir
rosuH Jun 28, 2026
557dc35
Document Desktop user save output
rosuH Jun 28, 2026
97baa9d
Persist Desktop icons in app storage
rosuH Jun 28, 2026
7e0a05e
Record Desktop icon persistence docs
rosuH Jun 28, 2026
1fe8ab9
Test Desktop icon persistence helper
rosuH Jun 28, 2026
8678fe1
Record Desktop icon helper docs
rosuH Jun 28, 2026
0eaafdd
Avoid Desktop save overwrites
rosuH Jun 28, 2026
ebe5378
Record Desktop save collision docs
rosuH Jun 28, 2026
c7959d0
Seed Desktop template database
rosuH Jun 28, 2026
ba76272
Record Desktop template seed docs
rosuH Jun 28, 2026
875b105
Add Desktop locale-aware template seed
rosuH Jun 28, 2026
9ddcef5
Record Desktop locale-aware seed docs
rosuH Jun 28, 2026
6717d3c
Clean up Desktop locale seed docs
rosuH Jun 28, 2026
1fa945f
Add Desktop template update action
rosuH Jun 28, 2026
5ec8009
Document Desktop template update action
rosuH Jun 28, 2026
c833aea
Add Desktop multi-file drop batch save
rosuH Jun 29, 2026
a54e1b9
Document Desktop multi-file drop batch
rosuH Jun 29, 2026
4c895aa
Add Desktop Open image multi-select
rosuH Jun 29, 2026
b37a76f
Document Desktop Open image multi-select
rosuH Jun 29, 2026
278d585
Add iOS template Room builder
rosuH Jun 29, 2026
1a9463f
Document iOS template Room builder
rosuH Jun 29, 2026
44be9f7
Add iOS template seed packaging
rosuH Jun 29, 2026
fb4f78b
Document iOS template seed packaging
rosuH Jun 29, 2026
86e28f8
Add iOS template bridge UI
rosuH Jun 29, 2026
e54f7c4
Document iOS template bridge UI
rosuH Jun 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
301 changes: 301 additions & 0 deletions .claude/skills/adaptive/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,301 @@
---
name: adaptive
description: Instructions to make or update an app's UI so that it adapts to different
Android devices including phones, tablets, foldables, laptops, desktop, TV, Auto
and XR. It includes how to handle different window sizes, pointing devices (such
as mouse) and text entry devices (such as keyboard) using the Compose MediaQuery
API. It also covers multi-pane layouts using Navigation3 Scenes, adaptive UI components
(such as buttons) with varying target sizes, and adaptive layouts (including navigation
areas - nav rails and nav bars) using the Compose Grid and FlexBox APIs.
license: Complete terms in LICENSE.txt
metadata:
author: Google LLC
last-updated: '2026-05-20'
keywords:
- android
- ui
- adaptive
- Grid
- FlexBox
- MediaQuery
- navigation
---

## Prerequisites

The app must:

- Use Compose for all screens. If it's still using Fragments or Views, suggest using the XML to Compose skill to migrate those screens.
- Use Jetpack Navigation 3. If it doesn't, suggest the Navigation 3 skill to migrate the app.

## Workflow to make an app adaptive

To make an app adaptive, follow these steps or a subset of them adapting to the
task.

- Step 1: Verify current UI
- Step 2: Make the navigation bar adaptive
- Step 3: Add multi-pane layouts
- Step 4: Make vertical lists adaptive by changing the number of columns
- Step 5: Hide app bars when scrolling

## Step 1. Verify current UI

Ensure that screenshot tests exist to verify the current UI on different form
factors. If they don't exist, add the [Compose Preview Screenshot Testing
tool](references/android/develop/ui/compose/tooling/debug.md). Use the following annotation to create previews for all the major form
factors. For example:


```kotlin
@Preview(name = "Phone", device = Devices.PHONE, showBackground = true)
@Preview(name = "Foldable", device = Devices.FOLDABLE, showBackground = true)
@Preview(name = "Tablet", device = Devices.TABLET, showBackground = true)
@Preview(name = "Desktop", device = Devices.DESKTOP, showBackground = true)
annotation class FormFactorPreviews

@PreviewTest
@FormFactorPreviews
@Composable
fun FeedScreenPreview() {
SnippetsTheme {
Box {
Text("My Screen")
}
}
}
```

<br />

## Step 2. Make the navigation bar adaptive

Bottom navigation bars are optimized for touch input when the user is holding a
phone in portrait mode. On larger screen hand-held devices, like tablets and
unfolded foldables, the navigation area must be accessible from the edge of the
screen (navigation rail).

If you need to provide more screen real state for the content, hide the
navigation area. Examples of this include:

- Hiding the navigation bar when the user scrolls down and showing it again when the user scrolls up. The assumption is that when the user is scrolling down, they are consuming content but when scrolling up they are trying to navigate away from that content.
- Hiding the navigation area when its content is distracting. For example, in camera previews or when the content is best displayed in full screen (such as a single photo screen).

When the detail screen is displayed full-screen on mobile, full-screen mode must
be deactivated on larger screens.

Steps to migrate:

- Locate the existing navigation bar.
- Convert each item to a `NavigationSuiteItem`.
- Identify whether the navigation bar's visibility changes. For example, if it is wrapped with an `AnimatedContent` or `AnimatedVisibility` composable. If so, follow the guidance in the "Control navigation area visibility".
- Replace the container that held the navigation bar (often a `Scaffold`) with `NavigationSuiteScaffold` from the Material 3 adaptive layouts library.
- Supply the navigation items using the `navigationItems` parameter of `NavigationSuiteScaffold`.

### Step 2.1. Control navigation area visibility

If the navigation bar's visibility changes - it is hidden under certain
scenarios or on certain screens - this behavior must be maintained with the
adaptive navigation area. This is done using `NavigationSuiteScaffold`'s `state`
parameter.

Steps to migrate:

- Identify the scenarios under which the navigation bar is hidden. This is usually done with a boolean variable for the visibility. It could be named something like `isNavBarVisible` or `shouldShowNavBar`.
- Create an instance of `NavigationSuiteScaffoldState` using `rememberNavigationSuiteScaffoldState()` and pass it to `NavigationSuiteScaffold`.
- When the navigation area visibility changes, use a `LaunchedEffect` to call `show` or `hide` on the `NavigationSuiteScaffoldState`.

For example:


```kotlin
// Pass this variable to any composable that needs to control the navigation area visibility
var isNavBarVisible by remember { mutableStateOf(true) }
val scaffoldVisibilityState = rememberNavigationSuiteScaffoldState()

NavigationSuiteScaffold(
navigationSuiteItems = navItems,
state = scaffoldVisibilityState
) {
// Main content
}

LaunchedEffect(isNavBarVisible){
if (isNavBarVisible) {
scaffoldVisibilityState.show()
} else {
scaffoldVisibilityState.hide()
}
}
```

<br />

## Step 3. Add multi-pane layouts using Navigation 3 Scenes

Analyze the codebase looking for related screens - tapping on something in one
screen opens another screen that shows information related to the first. There
are two canonical screen relationships: list-detail and supporting pane.

IMPORTANT: You must use the Navigation 3 `SceneStrategy` approach to implement
multi-pane layouts. Do not use `ListDetailPaneScaffold` or
`SupportingPaneScaffold`.

### Step 3.1. List-detail

#### Identify the list and detail screens

List-detail layouts display a list of items (this is the list screen) and
clicking on an item opens a new screen that shows more details about that item
(the detail screen).

Typical usage includes productivity apps like email, notes, and messaging.

Unless requested explicitly, avoid this pattern when the detail content requires
substantial screen space (e.g., images or media that benefits from a full-screen
presentation).

#### Add a Material list-detail SceneStrategy

- Add the `androidx.compose.material3.adaptive:adaptive-navigation3` library
- Create an `androidx.compose.material3.adaptive.navigation3.ListDetailSceneStrategy` using `rememberListDetailSceneStrategy`
- Pass the `ListDetailSceneStrategy` to `NavDisplay` using its `sceneStrategies` parameter

#### Use metadata to identify the list and detail screens

- Add metadata using `entry(metadata = ...)` or `NavEntry(metadata = ...)` to the list entry using `ListDetailSceneStrategy.listPane(detailPlaceholder = {
<placeholder composable> })`.
- Use the `detailPlaceholder` parameter to add a placeholder on the detail screen when no list items are selected.
- Add metadata to the detail entry using `ListDetailSceneStrategy.detailPane()`.

#### Important considerations

- When a detail screen displays its content full-screen on mobile (content fills the entire screen, bars or rails are hidden), full-screen mode must be deactivated if it's part of a list-detail layout.
- Detail screens must not show a back arrow when on a list-detail layout.

For a reference implementation, check the [Nav3 **Material** List Detail
recipe](references/android/guide/navigation/navigation-3/recipes/material-listdetail.md).

### Step 3.2. Supporting pane

Identify supporting pane screens where a main screen displays a single item, and
selecting it opens a "supporting screen" with more details. The supporting
screen complements the main screen and is shown in a supporting pane.

#### Add a Material supporting pane `SceneStrategy`

- If you haven't already, add the `androidx.compose.material3.adaptive:adaptive-navigation3` library
- Create an `androidx.compose.material3.adaptive.navigation3.SupportingPaneSceneStrategy` using `rememberSupportingPaneSceneStrategy`
- Pass the `SupportingPaneSceneStrategy` to `NavDisplay` using its `sceneStrategies` parameter

#### Use metadata to identify the main and supporting screens

- Add metadata using `entry(metadata = ...)` or `NavEntry(metadata = ...)` to the main entry using `SupportingPaneSceneStrategy.mainPane()`
- Add metadata to the supporting entry using `SupportingPaneSceneStrategy.supportingPane()`

### Step 3.3. Run screenshot tests

If you have made changes, record new reference files. Ask the user to visually
verify that the new layouts are correct.

## Step 4. Make vertical lists adaptive by changing the number of columns

### Step 4.1. Make lazy lists adaptive

Look for the following vertical list composables: `LazyColumn`,
`LazyVerticalGrid`, `LazyVerticalStaggeredGrid`.

Steps to migrate:

- Choose a suitable minimum width in dp for the column. It should be large enough so that item is clearly visible to the user.
- For `LazyColumn`: change to a `LazyVerticalGrid` and follow the instruction below
- For `LazyVerticalGrid`: change the `columns` parameter to use `GridCells.Adaptive(<width>.dp)`
- For `LazyVerticalStaggeredGrid`: change the `columns` parameter to use `StaggeredGridCells.Adaptive(<width>.dp)`

### Step 4.2. Migrate non-lazy lists to Grid

WARNING: Grid is an experimental API available from Compose 1.11.0-beta01.
Confirm with the user that they are happy to use an experimental API in their
codebase.

Look for any `Column` that contains multiple items of the same type and replace
it with `Grid`. Do not replace it with `LazyVerticalGrid` or any other lazy
layout. Do not place `Grid` inside the existing `Column`. Completely replace it.

`Grid` is configured by supplying a lambda (an extension function on
`GridConfigurationScope`) to its `config` parameter. Inside the lambda,
`constraints` provides the minimum and maximum dimensions of the grid container
and can be used to change the number of rows and columns based on the available
size. For example, the following code configures `Grid` such that when the
available width is:

- less than 800dp, a 2x4 grid is used
- 800dp or more, a 4x2 grid is used


```kotlin
Grid(
config = {
val maxWidthDp = constraints.maxWidth.toDp()
val (cols, rows) = if (maxWidthDp < 800.dp){
2 to 4
} else{
4 to 2
}

val gapSizeDp = 8.dp
val cellSize = ((maxWidthDp - (gapSizeDp * (cols - 1))) / cols).coerceAtLeast(0.dp)
repeat(cols) { column(cellSize) }
repeat(rows) { row(cellSize) }
gap(gapSizeDp)
}
) { /** items **/ }
```

<br />

`Grid` is an experimental API so add the `@OptIn(ExperimentalGridApi::class)`
annotation to any function that uses it.

## Step 5: Hide App Bars when scrolling

In an app with multiple top-level destinations, each screen must manage its own
app bar state independently. There are two main scroll behaviors:

- `exitUntilCollapsedScrollBehavior`: Hides on scroll down, stays hidden while you scroll up until you reach the very top (0 offset).
- `enterAlwaysScrollBehavior`: Hides on scroll down, shows immediately on scroll up.

## Final step: Build and test

Build the app and run the local tests. If the project has screenshot tests, run
them but DO NOT update the reference images. Prompt the user to do this after
they have viewed the screenshot diffs.

## Additional documentation for experimental adaptive APIs

The following APIs are available from Compose 1.11.0-beta01.

### FlexBox

Check the FlexBox documentation:

- [Overview](references/android/develop/ui/compose/layouts/adaptive/flexbox/index.md)
- [Get started - setup](references/android/develop/ui/compose/layouts/adaptive/flexbox/get-started.md)
- [Set container behavior](references/android/develop/ui/compose/layouts/adaptive/flexbox/container-behavior.md)
- [Set item behavior](references/android/develop/ui/compose/layouts/adaptive/flexbox/item-behavior.md)

## MediaQuery

Check the [MediaQuery documentation](references/android/develop/ui/compose/layouts/adaptive/mediaquery/index.md) when you need to query the device's
screen size, pointer precision, keyboard type, whether it has cameras or
microphones, and other device capabilities.

## Grid

Check the Grid documentation when you need to display a fixed number of items in
a grid layout:

- [Overview](references/android/develop/ui/compose/layouts/adaptive/grid/index.md)
- [Get started - setup](references/android/develop/ui/compose/layouts/adaptive/grid/get-started.md)
- [Set container properties](references/android/develop/ui/compose/layouts/adaptive/grid/container-properties.md)
- [Set item properties](references/android/develop/ui/compose/layouts/adaptive/grid/item-properties.md)
Loading
Loading