Skip to content

fix: smooth swipe back from activity details - #1853

Merged
ovitrif merged 4 commits into
masterfrom
fix/activity-details-back-transition
Nov 11, 2026
Merged

ovitrif merged 4 commits into
masterfrom
fix/activity-details-back-transition

Conversation

@ovitrif

@ovitrif ovitrif commented Nov 11, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #1852

This PR pins navigation-compose to 2.9.8, the newest 2.9.x, so a swipe back from Activity details slides the screen out smoothly instead of stalling and snapping.

Description

  • Fixes the swipe-back transition. chore: bump the gradle group across 1 directory with 41 updates #1787 moved navigation-compose from 2.9.6 to 2.10.2, and 2.10 rewrote NavHost predictive back:
    • A swipe started soon after opening a screen seeks with the forward transitions: the screen slides left and dims while Home comes in from the right. It holds half-faded, then snaps away.
    • A later swipe ignores each destination's pop transitions and uses 2.10's default scaleOut(0.7f), then snaps.
    • 2.9.x, which 3.1.0 shipped on 2.9.6, plays the pop transitions for both.
  • Picks 2.9.8 over 2.9.6 for its fix of a NavHost predictive-back race that could crash with a NullPointerException.
  • Drops navigation's deepLinkIds and deepLinkArgs extras from launch intents in MainActivity. 2.10 honours them only from Bitkit itself; 2.9 honours them from any app, which could open an internal screen such as the recovery phrase. Bitkit never sets them.
  • Adds a Dependabot ignore for androidx.navigation:* from 2.10.0, so the monthly gradle group bump doesn't bring the bug back.

Out of Scope

  • ContentView.kt: the NavHost-level predictivePopEnterTransition / predictivePopExitTransition that 2.10 adds. Setting them changed neither swipe on an emulator: the late swipe still shrank to 70% and snapped, and the early one kept the forward pair. They wait until a navigation release fixes predictive back.
  • compileSdk stays at 37. 2.9.8 doesn't need it, but other libraries in chore: bump the gradle group across 1 directory with 41 updates #1787 do.

Design

N/A — no UI changes.

Preview

Swipe back about 0.6 s after opening Activity details, then the Back key:

Before After
before-fast2x.mp4
after298-fast2x.mp4

Swipe back 2.5 s after opening Activity details, then the Back key:

Before After
before-slow2x.mp4
after298-slow2x.mp4

QA Notes

Setup

  • Dev build. In Dev Settings, tap Generate Test Activities so Home lists a few activities.
  • Gesture navigation.

Journeys

N/A — not drivable; see Manual Tests.

Manual Tests

  • 1. Home → tap an activity → within about a second, swipe back from the left edge → details slides out to the right, Home slides back in from the left, with no half-faded hold or snap — transition frames not in Capabilities
  • 2. Home → tap an activity → wait a few seconds → swipe back → same smooth pop, no shrinking to 70% — transition frames not in Capabilities
  • 3. regression: Home → tap an activity → Back key → details slides out to the right — transition frames not in Capabilities
  • 4. From another app (or adb shell), launch MainActivity with the int-array extra android-support-nav:controller:deepLinkIds = 0,-898289677 → Bitkit opens on Home, not Mnemonic Phrase

Automated Checks

  • ran ./gradlew compileDevDebugUnitTestKotlin compileDevDebugAndroidTestKotlin — tests compile against navigation 2.9.8

Evidence

  • Cases 1–4 pass on c47eba0 (the head since then, e2403ad, only swaps the nav key constants for their literal values so lint passes), on an Android 17 (API 37) emulator with a dev debug build; the recordings above show 1–3. Master at 4f401bd fails 1 and 2.
  • Case 4 control: the same build with the extras kept opens Mnemonic Phrase from the shell launch; with them dropped it opens Home.
  • Bisect:
    • v3.1.0 is clean at the late swipe (API 36).
    • fd6949c's parent, also on navigation-compose 2.9.6, is clean at both swipe timings.
    • That parent with only navigation-compose 2.10.2, plus the compileSdk 37 that version requires, reproduces the bug at both timings.
    • fd6949c alone doesn't build without the compileSdk 37 from 034bf57.
  • Master also stalls on the late swipe on an Android 16 (API 36) emulator; the early swipe and the fix were tested on API 37 only.

Gaps

  • Not run on a physical device.

Models used

  • Planning/scoping: claude-opus-5-5 (reasoning: medium)
  • Implementation: claude-opus-5-5 (reasoning: medium)
  • Review: Not performed

Navigation 2.10 rewrote NavHost predictive back. A swipe back started
soon after a forward navigation seeks with the forward transitions
(the screen slides left and dims while the previous one comes in from
the right), holds, then snaps. A later swipe uses the new default
scaleOut instead of the destination's pop transitions.

Pin 2.9.6, which 3.1.0 shipped, and keep Dependabot off 2.10.

Closes #1852
@ovitrif ovitrif self-assigned this Nov 11, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-11T11:55:22.852751Z c8b4f49 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@ovitrif
ovitrif requested review from a team, ben-kaufman and coreyphillips and removed request for a team November 11, 2026 11:54
@greptile-apps

greptile-apps Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] This PR appears safe to merge; no actionable regression was found.

Summary

Returns Navigation Compose and its test library to 2.9.6 to restore smooth swipe-back transitions.

  • Activity details slide away smoothly when users swipe back.

Reviews (1) · Last reviewed commit: "fix: pin navigation-compose to 2.9.6" · Reviewed by Greptile

@talosmachina talosmachina left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No findings. Pins navigation-compose (and navigation-testing) back to 2.9.6 to restore the pop transitions on predictive back, and adds a Dependabot ignore so the gradle group bump cannot bring 2.10 back. Reviewed c8b4f49, full tier (dependency manifest).

What I checked, and 3 candidates I ruled out

Read in full: gradle/libs.versions.toml, .github/dependabot.yml, the navigation deps in app/build.gradle.kts
Build: not run here. Auto reviews of bitkit-android do not build the branch, so this is static plus CI. At review time build-local (assembles the app against 2.9.6) was green; build-and-test, lint, compose-ui / ui-tests and the e2e jobs were still running.

Ruled out

  • Something still resolving navigation 2.10 transitively, silently undoing the pin: hilt-navigation-compose 1.4.0 asks for navigation-compose 2.9.0 (its POM on Google Maven), so Gradle settles on 2.9.6; no other catalog entry (lottie, haze, coil, compose-charts, glance) depends on androidx.navigation.
  • Code written against 2.10-only API: no use of predictivePopEnterTransition/predictivePopExitTransition or other 2.10 symbols under app/src, and build-local compiles on 2.9.6.
  • Dependabot ignore not matching: androidx.navigation:* with versions: [">= 2.10.0"] is the documented Maven range form and covers both navigation-compose and navigation-testing, which share navCompose; patch bumps inside 2.9.x still flow.

Merge confidence: 4/5, a dependency manifest change whose behaviour no test covers (the transition evidence is the author's emulator recordings), with build-and-test and lint still pending at review time.

Reviewer model: claude-opus-5-5
Reasoning effort: Not exposed (the run's metadata available to this reviewer does not report it)

@github-actions

github-actions Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Regtest APK

Built from e2403ad (run).

Download bitkit-dev-debug universal APK (expires in 30 days).

@coreyphillips coreyphillips left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two independent reviews.

worth doing, does not block

  • Pin to 2.9.6 skips 2.9.8's NavHost predictive-back crash fix (gradle/libs.versions.toml:14)
  • The selected version restores a predictive-back crash (gradle/libs.versions.toml:14)

nits

  • Changelog fragment covers only the early swipe and a regression no release had (changelog.d/next/1853.fixed.md:1)

the reviewers disagree, your call

  • External intents regain access to the internal seed screen (gradle/libs.versions.toml:14)

Comment thread gradle/libs.versions.toml Resolved
Comment thread changelog.d/next/1853.fixed.md Resolved
Comment thread gradle/libs.versions.toml Resolved
Comment thread gradle/libs.versions.toml Resolved
2.9.8 is the newest 2.9.x and fixes a NavHost predictive-back race (b/500945998). The changelog fragment now covers both swipe timings.
Navigation 2.10 honours deepLinkIds only from the app itself; 2.9 honours them from any caller. Bitkit never sets them, so MainActivity removes them before NavHost reads the intent.
NavController.KEY_DEEP_LINK_IDS and KEY_DEEP_LINK_ARGS are restricted to androidx.navigation, so lint rejects them; the literals match their values.
@ovitrif

ovitrif commented Nov 11, 2026

Copy link
Copy Markdown
Collaborator Author

e2403ad fixes the lint failure on c47eba0: NavController.KEY_DEEP_LINK_IDS and KEY_DEEP_LINK_ARGS are restricted to androidx.navigation (RestrictedApi), so MainActivity now uses their literal values. Behaviour is unchanged. lintDevDebug and detekt pass locally.

@coreyphillips coreyphillips left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rechecked after 3 new commits (d8be263, c47eba0, e2403ad). Nothing blocking remains.

addressed

  • Pin to 2.9.6 skips 2.9.8's NavHost predictive-back crash fix (gradle/libs.versions.toml:14). Fixed: gradle/libs.versions.toml:14 is now navCompose = "2.9.8". I unzipped the CI APK built from e2403ad, and its META-INF lists navigation-compose, navigation-runtime and navigation-common all at 2.9.8. In the 2.9.8 sources, NavHost.kt:512-541 still chooses createPopEnterTransition/createPopExitTransition while inPredictiveBack is set, which agrees with your device results for cases 1 to 3.
  • Changelog fragment covers only the early swipe and a regression no release had (changelog.d/next/1853.fixed.md:1). Fixed: changelog.d/next/1853.fixed.md now says swiping back "slides it out like the Back button does". That covers both swipe timings, and with "again" gone it no longer implies 3.1.0 shipped the bug.
  • External intents regain access to the internal seed screen (gradle/libs.versions.toml:14). Fixed: MainActivity.kt:117 strips the extras in onCreate before any NavHost composes, :286 strips them in onNewIntent before super/setIntent, and :296-299 holds the strip helper. The literals match KEY_DEEP_LINK_IDS/KEY_DEEP_LINK_ARGS in 2.9.8's NavController.android.kt:1158,1160. 2.9.8's handleDeepLink(Intent) has no trust check and reads those keys only from the intent, and onGraphCreated passes it activity.intent, which is the object that was stripped. Release builds declare no navDeepLinks, so the unstripped deepLinkExtras key cannot select a destination on its own. I did not rerun case 4 on a device.
  • The selected version restores a predictive-back crash (gradle/libs.versions.toml:14). Fixed: Same pin as point 1. In the 2.9.8 sources, NavHost.kt:521-529 now returns early when the back stack has fewer than two entries, and it binds currentBackStackEntry as non-null from currentBackStack.last(). That removes the path where the entry stayed null and was dereferenced later.

@ovitrif

ovitrif commented Nov 11, 2026

Copy link
Copy Markdown
Collaborator Author

Auto-merge on: approved by @coreyphillips on e2403ad, all four review threads fixed and resolved. It merges once the two remaining e2e jobs pass.

@ovitrif
ovitrif enabled auto-merge November 11, 2026 13:10
@ovitrif
ovitrif merged commit 2c7427e into master Nov 11, 2026
23 checks passed
@ovitrif
ovitrif deleted the fix/activity-details-back-transition branch November 11, 2026 13:16

@coreyphillips coreyphillips left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rechecked after replies, with no new commit since e2403ad. Nothing blocking remains.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: swipe back from activity details stalls, then snaps

3 participants