Hatch: only show after idle return#8336
Merged
Merged
Conversation
The return-to-page Hatch card on the NTP now only appears when the NTP was shown as a result of an idle return, not when the user opens a new tab themselves. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the synchronous isAfterIdleReturn() getter with a StateFlow so the Hatch ViewModel reactively hides when onNtpShown() resets the idle state. This fixes a race condition where creating a new tab would show the Hatch because the ViewModel evaluated before onNtpShown ran. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The StateFlow _isAfterIdleReturn already tracks the same state. Use its .value for pixel classification instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
joshliebe
reviewed
Apr 22, 2026
Contributor
joshliebe
left a comment
There was a problem hiding this comment.
I tested this and m_ntp_after_idle_ntp_shown_user_initiated is fired every time the app is launched on new tab.
Is this expected behavior?
joshliebe
approved these changes
Apr 24, 2026
Contributor
joshliebe
left a comment
There was a problem hiding this comment.
@malmstein Will leave it up to you to decide if #8336 (review) is correct or not.
…h_only_after_idle # Conflicts: # app/src/main/java/com/duckduckgo/app/generalsettings/showonapplaunch/FirstScreenHandler.kt # app/src/main/java/com/duckduckgo/app/generalsettings/showonapplaunch/ShowOnAppLaunchOptionHandler.kt # app/src/test/java/com/duckduckgo/app/generalsettings/showonapplaunch/FirstScreenHandlerImplTest.kt # app/src/test/java/com/duckduckgo/app/generalsettings/showonapplaunch/ShowOnAppLaunchOptionHandlerImplTest.kt
Only fire ntpAfterIdleManager.onIdleReturnTriggered() synchronously from FirstScreenHandlerImpl.onOpen when the currently selected tab is already an NTP; otherwise let the ShowOnAppLaunchOptionHandler path fire it when it adds (or preserves) an NTP. Without this gate, LastOpenedTab/SpecificPage users on a URL tab would leave a stale pendingAfterIdle flag that a later user-initiated NTP would consume. Also expand the handler to fire on idle for the NewTabPage branch even when the user is already on an NTP (no new tab added), so the already-shown NTP is correctly classified as after-idle. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
onUserSubmittedQuery is also called from onViewReady and restoreWebViewState to replay the previously-saved URL of a tab. At that moment globalLayoutState is still Browser(isNewTabState = true) from ViewModel init, so the NTP search-submitted pixel would fire even though the user never typed into the omnibar. Gate the notification on url == null so restoration paths (where site was already built by loadData) are excluded. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 3 total unresolved issues (including 2 from previous reviews).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit d039c11. Configure here.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Task/Issue URL: https://app.asana.com/1/137249556945/project/1174433894299346/task/1214181027808336?focus=true
Description
The return-to-page Hatch card on the NTP was previously shown whenever a last-accessed tab existed and the
showNTPAfterIdleReturnfeature flag was enabled. This meant it appeared even when the user manually opened a new tab, which is incorrect — the Hatch should only appear when the NTP was shown as a result of an idle return.Changes:
isAfterIdleReturnStateFlow<Boolean>to theNtpAfterIdleManagerAPI, replacing the internalcurrentAfterIdleAtomicBooleanNewTabReturnHatchViewModelnowcombinesflowLastAccessedTabwithisAfterIdleReturnto reactively show/hide the Hatch:new-tab-page-apidependency to:browser-uimoduleSteps to test this PR
Hatch appears after idle return
showNTPAfterIdleReturnfeature flagHatch does not appear on user-initiated NTP
NTP shown pixels fire correctly after idle return
m_ntp_after_idle_ntp_shown_after_idlepixel firesm_ntp_after_idle_ntp_shown_user_initiatedpixel fires (not the after_idle variant)Return-to-page and search pixels classify correctly
m_ntp_after_idle_return_to_page_tapped_after_idlepixel firesm_ntp_after_idle_bar_used_from_ntp_after_idlepixel firesm_ntp_after_idle_bar_used_from_ntp_user_initiatedpixel firesUI changes
No UI changes — the Hatch card appearance is unchanged, only when it appears has changed.
Note
Medium Risk
Changes idle-return classification and lifecycle ordering for NTP state/pixeling, which can affect when the hatch appears and how metrics are recorded across app recreation/backgrounding.
Overview
Ensures the NTP “return-to-page” hatch only appears when the NTP was shown due to an idle return, not when the user manually opens a new tab.
This introduces
NtpAfterIdleManager.isAfterIdleReturn(aStateFlow) and updatesNtpAfterIdleManagerImplto track/clear after-idle state safely acrossonOpen/onCloseordering, with tests updated accordingly.Idle-return triggering is tightened:
FirstScreenHandlerImplcan now synchronously callonIdleReturnTriggered()when reopening directly onto an NTP,ShowOnAppLaunchOptionHandleralways marks after-idle when the inactivity option resolves to NTP even if no new tab is added, andBrowserTabViewModelavoids firing NTP-search-submitted pixels during restore flows by requiringurl == null.Reviewed by Cursor Bugbot for commit 55a2251. Bugbot is set up for automated code reviews on this repo. Configure here.