Allow setting of favourite serp easter egg logo#7467
Merged
mikescamell merged 26 commits intodevelopfrom Feb 6, 2026
Merged
Conversation
19e36d2 to
3b8dd59
Compare
7362335 to
b763bc4
Compare
app/src/main/java/com/duckduckgo/app/browser/omnibar/OmnibarLayoutViewModel.kt
Show resolved
Hide resolved
app/src/main/java/com/duckduckgo/app/browser/omnibar/OmnibarLayoutViewModel.kt
Show resolved
Hide resolved
b763bc4 to
bff3474
Compare
app/src/main/java/com/duckduckgo/app/browser/omnibar/OmnibarLayoutViewModel.kt
Outdated
Show resolved
Hide resolved
bff3474 to
cf15f2f
Compare
...rp-logos-impl/src/main/kotlin/com/duckduckgo/serp/logos/impl/ui/SerpEasterEggLogoActivity.kt
Show resolved
Hide resolved
cae2868 to
20a6686
Compare
500da4f to
b0e3498
Compare
anikiki
approved these changes
Feb 4, 2026
Contributor
anikiki
left a comment
There was a problem hiding this comment.
Looks good and works as expected! 🎉
There's a failing test (missing param).
app/src/main/java/com/duckduckgo/app/browser/omnibar/OmnibarLayoutViewModel.kt
Outdated
Show resolved
Hide resolved
5b93a05 to
64f8fcd
Compare
We now include a title to tell the user they have discovered an easter egg logo and allow them to set the logo as their favourite via the newly added button on screen.
When an Easter Egg logo is displayed in the omnibar (from a special search like "f1"), it now plays a subtle wiggle animation once the image loads. The animation: - Only plays once per unique logo URL (prevents re-triggering on ViewState updates) - Skips animation for favourite logos (set by user preference) We also need to make sure we cancel the wobble animation before the shared element transition otherwise it becomes glitchy.
When a SERP page loads with an Easter Egg logo, two events occur in non-deterministic order: onViewModeChanged and onExternalOmnibarStateChanged. If onViewModeChanged was called after the Easter Egg was already set, it would overwrite the leadingIconState with Dax because it always passed logoUrl = null. This fix preserves the existing Easter Egg URL in onViewModeChanged by extracting it from the current state before updating, following the same pattern already used in onExternalLoadingStateChanged.
When navigating between searches, onExternalOmnibarStateChanged may be called with serpLogo = null before the new logo extraction completes. Previously this would clear the existing Easter Egg logo, causing Dax to briefly flash or persist if timing was unfavorable. Now we distinguish between: - SerpLogo.Normal: Explicitly no Easter Egg, clear and show Dax - null: Unknown/pending state, preserve existing Easter Egg if present This prevents the logo from being lost during navigation between Easter Egg searches.
No need to extract an existing logo if we have a favourite set. Also prevents getting into any weird state.
…te button clicked Matches iOS and request from Ship Review
… on SERP page in BrowserTabViewModel Moves the logic to ensure we set a Favourite EasterEgg logo to the BrowserTabViewModel. This makes the OmnibarViewModel dumber like before adding the favourite feature, leaving responsibility to the caller (BrowserTab) to decide what should be shown. Add flow observer that combines favourite toggle state and favourite URL to reactively update the serpLogo when: - Favourite logo is set: Show the favourite Easter egg logo - Favourite logo is cleared: Show Dax (Normal logo) - Feature is disabled: Let normal extraction handle it Only reacts when on a SERP page to avoid unnecessary updates on other pages.
When a favourite SERP logo is cleared while on a SERP page, the omnibarViewState.serpLogo should update from EasterEgg to Normal, but currently it stays stale. This test verifies the expected behavior and will pass once a flow observer is added to BrowserTabViewModel to react to favourite logo changes
The icon will now shrink depending on how much room we have between the text and the button. On all but the tiniest of phones this will be fine. I reduced margins to give the logo the best chance of being as big as possible without overlapping.
No longer needed as we moved the logic to the BrowserViewModel
64f8fcd to
918b1f5
Compare
...p-logos-impl/src/main/kotlin/com/duckduckgo/serp/logos/impl/ui/SerpEasterEggLogoViewModel.kt
Show resolved
Hide resolved
Task/Issue URL: https://app.asana.com/1/137249556945/project/1207908166761516/task/1212768545044373?focus=true ### Description Translations for setting a favourite easter egg logo ### Steps to test this PR Enable setFavourite toggle _Translations_ - [x] Switch languages - [x] Search for an easter egg logo e.g. "predator" - [x] Check strings on the SERP easter egg logo screen have changed ### UI changes N/A <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Resource-only localization changes with no functional logic modifications; risk is limited to missing/incorrect string resources causing UI text regressions. > > **Overview** > Adds new localized strings used by the SERP easter egg logo screen for **setting a favourite logo**, **resetting to default**, and the discovery message (`serpLogoSetAsFavourite`, `serpLogoResetToDefault`, `serpLogoDiscoveryText`) across multiple `values-xx/strings-serp-logos.xml` files, plus the base `values/strings-serp-logos.xml`. > > Removes the `values/donottranslate.xml` resource that previously held the English versions of these strings, and updates several locale resource headers (copyright year). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit d6264dd. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
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/1207908166761516/task/1212553599261552?focus=true
Description
This PR adds the ability for users to set a SERP Easter Egg logo as their favourite, which will then display on all DuckDuckGo search result pages.
Features implemented:
- Display a title telling the user they've discovered an Easter Egg logo
- Added a button to set/unset the logo as favourite
- Only plays once per unique logo URL
- Skips animation for favourite logos
- Waits for image crossfade to complete before animating
- Preserve existing Easter Egg when onViewModeChanged is called
- Distinguish between SerpLogo.Normal (explicitly no Easter Egg) and null (pending state)
- Reset to Dax logo when favourite preference changes
Steps to test this PR
Easter Egg Discovery
Setting a Favourite Logo
Resetting to Default
Flag off
UI changes
Note
Medium Risk
Touches omnibar state/animation handling and adds new persistence + feature-flagged behaviour, so regressions could affect address bar logo rendering across navigation and page loads. Scope is contained to SERP-logo UI/state and is well covered by new/updated tests.
Overview
Adds a feature-flagged “favourite” SERP Easter Egg logo that, when set, overrides normal SERP logo extraction and is shown on all DuckDuckGo search result pages.
Introduces persistence via a new
FavouriteSerpLogoDataStore(DataStore-backed) and wires it throughSerpLogos/BrowserTabViewModelso favourite changes immediately update the omnibar and avoid issuingExtractSerpLogowhen a favourite is active.Updates the discovery UI to let users set/unset a favourite (new
SerpEasterEggLogoViewModel, layout + strings) and refines omnibar rendering/animations: adds a one-time wiggle animation for non-favourite Easter Egg logos, plus explicit cancellation of that animation during logo transitions to prevent glitches. Tests are expanded across app + serp-logos modules, andSerpLogo.EasterEggnow carries anisFavouriteflag to distinguish behaviour.Written by Cursor Bugbot for commit e3e334d. This will update automatically on new commits. Configure here.