Skip to content

Add navigation drawer back to new study screen#21143

Open
timrae wants to merge 2 commits into
ankidroid:mainfrom
timrae:feature/new-study-screen-navigation-v2
Open

Add navigation drawer back to new study screen#21143
timrae wants to merge 2 commits into
ankidroid:mainfrom
timrae:feature/new-study-screen-navigation-v2

Conversation

@timrae
Copy link
Copy Markdown
Member

@timrae timrae commented May 25, 2026

Purpose / Description

The new study screen (ReviewerFragment) currently has no navigation drawer, so reaching Browser / Statistics / Settings / Help from a review session requires the user to back out to the deck picker first, introducing extra clicks.

This PR adds an app-level navigation drawer to the new reviewer, mirroring the destinations of the legacy
NavigationDrawerActivity drawer, and uses it as the first Compose surface in the app.

Fixes

#21139 (partial fix)

Approach

Done in two commits:

1. feat(reviewer): add navigation drawer to the new study screen — Views-only, no toolchain changes.

  • Extracts AppDestination as a single source of truth for the app-level navigation surface (Decks / Browser / Statistics / Settings / Help / Send feedback / etc.).
  • Both the new ReviewerFragment drawer and the legacy NavigationDrawerActivity now build their NavigationView menus from it via a shared Menu.populateFromAppDestinations() helper.
  • Deletes res/menu/navigation_drawer.xml; orphaned menu-item ids move into ids.xml so existing references (CardBrowser, DeckPicker, BottomNavActivity, espresso tests) keep resolving.
  • ReviewerFragment hosts the drawer locally — root becomes a ClosableDrawerLayout wrapping the existing CoordinatorLayout, with include_navigation_drawer.xml as the drawer panel. The hamburger button replaces the back button in the tools row; exiting the reviewer remains the system back gesture (an
    OnBackPressedCallback closes the drawer first when it's open).

2. feat(compose): render the reviewer's nav drawer with Compose — swap the implementation behind the same UX.

  • Adds Compose BOM 2026.05.01 + Material3 + kotlin.plugin.compose, plus activity-compose / lifecycle-viewmodel-compose / lifecycle-runtime-compose. First Compose surface in the app.
  • AnkiTheme — a minimal MaterialTheme bridge that reads the AppCompat / Material Components theme attributes so Compose surfaces honour the user's selected colour theme. Translucent values are composited over colorBackground so Compose colours are fully opaque.
  • AppNavigationDrawer — an M3 ModalNavigationDrawer rendering the AppDestination entries. Owns its open/closed state; the host emits on a one-shot Flow<Unit> of "open" requests and the drawer closes itself on scrim tap / predictive back / item click. Returns an empty composition while fully closed so
    touches fall through to the WebView underneath.
  • fragment_reviewer.xml: drops the ClosableDrawerLayout wrap and the <include> of include_navigation_drawer.xml; adds a ComposeView overlay. android:fitsSystemWindows="true" moves off the root CoordinatorLayout onto the inner LinearLayout so the ComposeView spans the full window and the drawer
    paints up to the top edge — parity with the legacy DrawerLayout behaviour.
  • ReviewerViewModel gains openNavigationDrawerFlow / onHamburgerClicked so the "should open" signal survives configuration changes; the drawer's own internal DrawerState handles open/close UX.

This second commit could be reverted if the majority opinion of the current maintainers is not to introduce the new dependencies yet.

How Has This Been Tested?

Manual testing on a physical Pixel 8a (Android 14) and the API 34 emulator, playDebug build:

  • Open a deck, enter the new reviewer, tap the hamburger → drawer slides in. Confirmed all destinations (Decks, Browser, Statistics, Settings, Help, Send feedback) navigate correctly.
  • Scrim tap, predictive back gesture, and item-click all close the drawer.
  • System back from a closed reviewer still exits to the deck picker; system back from an open drawer closes the drawer first.
  • Rotated the device with the drawer open — drawer state survives via ReviewerViewModel.openNavigationDrawerFlow + Compose's rememberSaveable.
  • Swapped themes (light/dark/black, plus a couple of custom palette themes) — AnkiTheme picks up the AppCompat colours and the drawer matches the surrounding chrome.
  • Verified the legacy NavigationDrawerActivity drawer still renders correctly after the AppDestination refactor (Decks/Browser/Stats/Settings/Help all present).
  • ./gradlew lintPlayDebug ktLintCheck :AnkiDroid:testPlayDebugUnitTest passes.

Screenshots

signal-2026-05-25-145034 signal-2026-05-25-144319_002 signal-2026-05-25-145236

Learning (optional, can help others)

Checklist

  • You have a descriptive commit message with a short title (first line, max 50 chars).
  • You have commented your code, particularly in hard-to-understand areas
  • You have performed a self-review of your own code
  • UI changes: include screenshots of all affected screens (in particular showing any new or changed strings)
  • UI Changes: You have tested your change using the Google Accessibility Scanner

Licenses

Library Description License
androidx.compose (BOM 2026.05.01) Jetpack Compose UI toolkit Apache 2.0
androidx.compose.material3 Material 3 components for Compose Apache 2.0
androidx.activity:activity-compose Activity + Compose integration Apache 2.0
androidx.lifecycle:lifecycle-viewmodel-compose ViewModel + Compose integration Apache 2.0
androidx.lifecycle:lifecycle-runtime-E-2.0.txt)

Maintainers:

@timrae timrae changed the title Feature/new study screen navigation v2 Add navigation drawer back to new study screen May 25, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 25, 2026

Snapshot diff report vs main. Open screenshot-diff for diffs.

  • StudyScreenScreenshotTest: 8 changes
All 8 changed screenshots

StudyScreenScreenshotTest

  • bar=BOTTOM_frame=BOXbttns=false_compare.png
  • bar=BOTTOM_frame=BOXbttns=true_compare.png
  • bar=BOTTOM_frame=CARDbttns=false_compare.png
  • bar=BOTTOM_frame=CARDbttns=true_compare.png
  • bar=TOP_frame=BOXbttns=false_compare.png
  • bar=TOP_frame=BOXbttns=true_compare.png
  • bar=TOP_frame=CARDbttns=false_compare.png
  • bar=TOP_frame=CARDbttns=true_compare.png

timrae added 2 commits May 25, 2026 15:08
Adds an app-level navigation drawer to the new study screen, mirroring
the destinations in the legacy nav drawer. This allows users to navigate
to the Browser/Stats/Settings/Help pages directly from the reviewer
without unnecessary button presses, or leaving the reviewer context.

Extracts AppDestination as a single source of truth for the app-level
navigation surface; both the new ReviewerFragment drawer and the legacy
NavigationDrawerActivity build their NavigationView menus from it via a
shared Menu.populateFromAppDestinations() helper. res/menu/navigation_drawer.xml
is deleted; the orphaned menu-item ids move into ids.xml so existing
references (CardBrowser, DeckPicker, BottomNavActivity, espresso tests)
keep resolving.

ReviewerFragment hosts the drawer locally — its layout root becomes a
ClosableDrawerLayout wrapping the existing CoordinatorLayout, with an
<include> of the existing include_navigation_drawer.xml as the drawer
panel. The hamburger button replaces the back button in the tools row;
exiting the reviewer is the system back gesture (which closes the
drawer first when it's open via an OnBackPressedCallback).

No Compose; no toolchain changes. The legacy and new drawers use the
same Views widgets so they stay in lockstep.
Swap the ClosableDrawerLayout-based drawer for a Compose
ModalNavigationDrawer hosted in a ComposeView overlay. This is the first
Compose surface in the app.

Brings in:

- Compose BOM 2026.05.01 + Material3 + kotlin.plugin.compose, plus
  activity-compose / lifecycle-viewmodel-compose / lifecycle-runtime-compose.
- AnkiTheme — a minimal MaterialTheme bridge that reads the AppCompat /
  Material Components theme attributes so Compose surfaces honour the
  user's selected colour theme. Translucent values are composited over
  colorBackground so Compose colours are fully opaque.
- AppNavigationDrawer — the M3 ModalNavigationDrawer rendering the
  AppDestination entries. Owns its own open/closed state; the host emits
  on a one-shot Flow<Unit> of "open" requests and the drawer closes
  itself on scrim tap / predictive back / item click. Returns an empty
  composition while fully closed so touches fall through to the WebView.

In the reviewer:

- fragment_reviewer.xml: drop the ClosableDrawerLayout wrap and the
  <include> of include_navigation_drawer.xml. Add a ComposeView overlay
  for the drawer. Move android:fitsSystemWindows="true" off the root
  CoordinatorLayout onto the inner LinearLayout so the ComposeView
  spans the full window and the drawer paints up to the top edge —
  parity with the legacy DrawerLayout behaviour.
- ReviewerFragment: drop the Views-based setupNavigationDrawer in
  favour of one that wires the ComposeView to AppNavigationDrawer.
- ReviewerViewModel: add openNavigationDrawerFlow / onHamburgerClicked
  so view-model state survives configuration changes; the drawer's own
  internal state is what handles the open/close UX.
@timrae timrae force-pushed the feature/new-study-screen-navigation-v2 branch from 6d2e8ed to 626a601 Compare May 25, 2026 13:09
@criticalAY
Copy link
Copy Markdown
Contributor

Heya! We are moving away from Nav rail and bottom app bar will be introduced (part of GSoC 2026 project), I don't think it will be worth the efforts

@BrayanDSO
Copy link
Copy Markdown
Member

Unless you are super productive, and based on how the code is written, I believe that AI was used here.

If so, you need to follow the AI policy and disclose it.

@timrae
Copy link
Copy Markdown
Member Author

timrae commented May 25, 2026

My bad, looks like I read an older version of the policy that said disclosure is optional for established contributors.

Disclosure of tool use is left to the submitter's discretion to reduce unnecessary process.

Yes I used Opus 4.7 during the creation of this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants