Skip to content

NTP omnibar: screenshot capture and pasted attachments - #3076

Open
anpete wants to merge 4 commits into
mainfrom
feature/anpete/ntp-screenshot
Open

anpete wants to merge 4 commits into
mainfrom
feature/anpete/ntp-screenshot

Conversation

@anpete

@anpete anpete commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Asana Task/Github Issue: Windows side: duckduckgo/windows-browser#9333 (stacked on duckduckgo/windows-browser#9290 and duckduckgo/windows-browser#9286)

Description

Adds screenshot capture and pasted attachments to the Duck.ai omnibar on the NTP. Native (Windows) captures the image and the page attaches it through the existing image pipeline.

  • Screenshot: an "Add Screenshot" submenu in the attach menu ("Drag to Select", "Select Window or Display"), driven by the new omnibar_captureScreenshot request. Native returns an image already scaled to at most 1024px; the page keeps that size. Choosing a mode again while one is pending replaces it (native answers the older request as cancelled).
  • Paste: with enablePastedAttachments, clipboard images and PDFs attach on paste. If the clipboard has text, the text pastes and nothing is attached.
  • Config: screenshotModes and enablePastedAttachments in OmnibarConfig. Both are off when absent. On Windows they sit behind aiChat.ntpScreenshot and aiChat.ntpPasteImages.
  • Telemetry: omnibar_image_attached / omnibar_image_removed (with source), and omnibar_screenshot_taken / _removed / _failed. These feed existing Windows NTP image pixels, which have never fired because the page didn't send these events.
  • Shared Dropdown: a new DropdownSubmenu primitive (hover, click, Enter or ArrowRight opens; ArrowLeft or Escape closes).

Message and config docs are in special-pages/pages/new-tab/app/omnibar/omnibar.md.

Testing Steps

  • Open the integration build of the New Tab Page with ?omnibar.mode=ai&omnibar.enableAiChatTools=true&omnibar.screenshotModes=dragToSelect,selectWindowOrDisplay&omnibar.enablePastedAttachments=true.
  • Open the paperclip menu → "Add Screenshot" → pick a mode. A mock screenshot attaches as an image chip.
  • Add &omnibar.screenshotResult=error to see "Couldn't capture screenshot", or =cancel to see that nothing happens.
  • Paste an image into the prompt and check it attaches. Paste text copied together with an image (e.g. cells from Excel) and check only the text is pasted.
  • Automated: special-pages/pages/new-tab/app/omnibar/integration-tests/omnibar-screenshot.spec.js and unit-tests/uniqueFileName.spec.js.

Checklist

Please tick all that apply:

  • I have tested this change locally
  • I have tested this change locally in all supported browsers
  • This change will be visible to users
  • I have added automated tests that cover this change
  • I have ensured the change is gated by config
  • This change was covered by a ship review
  • This change was covered by a tech design
  • Any dependent config has been merged

🤖 Generated with Claude Code

anpete and others added 2 commits September 30, 2026 11:50
Adds "Add Screenshot" to the Duck.ai omnibar attach menu and lets images and
files be pasted into the prompt, for the Windows NTP.

- New `omnibar_captureScreenshot` request: native captures (region overlay or
  window/display picker) and returns a processed image; the page attaches it
  through the existing image pipeline at up to 1024px.
- Config: `screenshotModes` (menu rows) and `enablePastedAttachments` (paste
  kill switch).
- Paste: clipboard text wins; otherwise bitmaps attach at screenshot size,
  copied images like picked ones, PDFs as file chips.
- Telemetry: omnibar_image_attached / _removed (with source) and
  omnibar_screenshot_taken / _removed / _failed.
- Shared Dropdown gains a DropdownSubmenu primitive (hover, click,
  Enter/ArrowRight to open; ArrowLeft/Escape to close).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Native now answers a pending capture as cancelled when a new one replaces it,
so the page no longer greys the screenshot rows while a request is pending.
Only the latest request may show the capture error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the semver-minor New feature — triggers minor version bump label Sep 30, 2026
@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

[Beta] Generated file diff

Time updated: Thu, 01 Oct 2026 11:43:32 GMT

Apple
    - apple/pages/new-tab/dist/index.css
  • apple/pages/new-tab/dist/index.js
  • apple/pages/new-tab/locales/en/new-tab.json

File has changed

Integration
    - integration/pages/new-tab/dist/index.css
  • integration/pages/new-tab/dist/index.js
  • integration/pages/new-tab/locales/en/new-tab.json

File has changed

Windows
    - windows/pages/new-tab/dist/index.css
  • windows/pages/new-tab/dist/index.js
  • windows/pages/new-tab/locales/en/new-tab.json

File has changed

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Cursor review was not successful.

This PR requires a manual review and approval from a member of one of the following teams:

  • @duckduckgo/content-scope-scripts-owners
  • @duckduckgo/apple-devs
  • @duckduckgo/android-devs
  • @duckduckgo/team-windows-development
  • @duckduckgo/extension-owners
  • @duckduckgo/config-aor
  • @duckduckgo/breakage-aor
  • @duckduckgo/breakage

@anpete

anpete commented Sep 30, 2026

Copy link
Copy Markdown
Contributor Author

@claude review

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.

Beyond the inline finding, I also checked two other candidates and ruled them out: the paperclip dropdown's file-attach row for screenshot-only users silently no-ops at the image cap the same way the pre-existing tabsEnabled dropdown path already does (not a new regression, just extended to a new entry point); and the screenshot decode path's synchronous atob loop runs before the size/pixel checks, but native is documented to always scale screenshots to at most 1024px, so there's no practical main-thread-freeze risk in the trusted native→page contract.

Extended reasoning...

The diff adds screenshot capture and clipboard paste to the NTP omnibar (new native message, image/file attachment pipeline, a generic dropdown/submenu primitive, telemetry, and integration tests) with no auth/crypto surface; the confirmed inline finding is a real but non-security UX gap (unsupported pasted image MIME types silently drop with no feedback). I independently verified the file-read code path and two other candidate issues (dropdown cap no-op for screenshot-only users, and the screenshotToFile atob loop preceding size checks) and found both to be pre-existing patterns or backed by a trusted native size contract rather than new regressions, so I'm noting them as ruled out rather than raising them.

A pasted BMP, TIFF or GIF was dropped with only a console warning, and the
paste itself was swallowed. processFiles now reports format-rejected files
with the existing "Failed to process image" error, for paste and picker alike.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Build Branch

Branch pr-releases/feature/anpete/ntp-screenshot
Commit 8075b80aff
Updated October 1, 2026 at 11:43:17 AM UTC

Static preview entry points

QR codes (mobile preview)
Entry point QR code
Docs QR for docs preview
Static pages QR for static pages preview
Integration pages QR for integration pages preview

Integration commands

npm (Android / Extension):

npm i github:duckduckgo/content-scope-scripts#pr-releases/feature/anpete/ntp-screenshot

Swift Package Manager (Apple):

.package(url: "https://github.com/duckduckgo/content-scope-scripts.git", branch: "pr-releases/feature/anpete/ntp-screenshot")

git submodule (Windows):

git -C submodules/content-scope-scripts fetch origin pr-releases/feature/anpete/ntp-screenshot
git -C submodules/content-scope-scripts checkout origin/pr-releases/feature/anpete/ntp-screenshot
Pin to exact commit

npm (Android / Extension):

npm i github:duckduckgo/content-scope-scripts#8075b80aff80abfc1819dff55df313c4da5b6293

Swift Package Manager (Apple):

.package(url: "https://github.com/duckduckgo/content-scope-scripts.git", revision: "8075b80aff80abfc1819dff55df313c4da5b6293")

git submodule (Windows):

git -C submodules/content-scope-scripts fetch origin pr-releases/feature/anpete/ntp-screenshot
git -C submodules/content-scope-scripts checkout 8075b80aff80abfc1819dff55df313c4da5b6293

@anpete
anpete marked this pull request as ready for review September 30, 2026 13:32

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

…ending"

This reverts commit 6f6b627. Windows now draws its own region selector
over every monitor, so a second capture can't start while one is up: native
is back to one capture at a time and answers a second request as cancelled.
The screenshot rows grey out again while a request is pending, and the
request-id / stale-reply handling is gone. Docs updated to match.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sashalavron

Copy link
Copy Markdown
Contributor

@anpete nice work! Two points for now:

  1. Could you split this into 2 stacked PRs? The first would be paste on its own (no native work needed) plus the image telemetry, and the second the native screenshot feature on top. That would also move the paste logic out of useScreenshotCapture, where it's easy to mistake for part of the screenshot feature.
  2. Do we need enablePastedAttachments? AFAIK paste (apart from the dedicated screenshot feature) doesn't need native support, e.g. I can copy an image to my clipboard, paste it, and it should just work.

This branch has not been deployed

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

Labels

semver-minor New feature — triggers minor version bump

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants