[macOS] Add quick feedback popup with toolbar button, screenshot, and diagnostics for internal users#4467
Open
[macOS] Add quick feedback popup with toolbar button, screenshot, and diagnostics for internal users#4467
Conversation
Introduce a Quick Feedback flow for internal users: adds QuickFeedbackService, QuickFeedbackWindowController, QuickFeedbackDiagnosticsCollector, and QuickFeedbackTipController to present a lightweight feedback popup with diagnostics and optional screenshot attachment. Integrates the feature into AppDelegate, main menus, navigation bar (button + tip), and WindowControllersManager (tab/window counts provider). Updates internal-feedback-autofiller.js to support quick mode, diagnostics injection, and screenshot handling. Adds AppVersionModel.distributionLabel and unit tests for distribution label and diagnostics collector behavior.
Add QuickFeedback module to the Xcode project and wire up UI and tests. Key changes: - Update project.pbxproj: add QuickFeedback group, source files and tests to targets and build phases. - New/updated QuickFeedback files: QuickFeedbackService, QuickFeedbackDiagnosticsCollector, window/tip controllers and tests. - QuickFeedbackService: - Marked lazy property usage @mainactor in AppDelegate where service is created. - Import os.log and switch WKWebsiteDataStore to .default() - Remove old native screenshot-injection code and formLoaded state; instead pass a %SCREENSHOT_BASE64% token into the JS template and add a timeout to restore hidden sections. - Simplify navigation delegate logic and sign-out/cleanup flows. - Resources JS (internal-feedback-autofiller.js): accept %SCREENSHOT_BASE64%, inject a screenshot section with checkbox/warning/enlarge overlay, add email field padding, and other UI tweaks. - Diagnostics collector: use appropriate I/O Kit port for pre-macOS-12 compatibility when matching IOPCIDevice. - NavigationBarViewController: add QuickFeedback button handling for internal users, subscribe to internalUser publisher to add/remove the button, swap icon name, and manage tip controller and spacer views. - AppVersionModel: import AppKit to fix usage context. These changes enable internal quick feedback with optional screenshot attachment, add tests and project references, and ensure compatibility across macOS versions.
Import DesignResourcesKitIcons and replace the previous NSImage/name lookup and SF Symbol fallback with DesignSystemImages.Color.Size16.feedback. Ensure the icon preserves its color by setting isTemplate = false and remove the previous contentTintColor fallback logic.
Use an isolated WKWebsiteDataStore for the internal feedback webview on macOS 14+ to preserve Asana sessions, and fall back to the default store on older macOS. Copy Asana cookies from the default store into the isolated store at startup. Add a script message handler and postMessage from the autofill JS so the app can dismiss the feedback popup after form submission. Restrict webview navigation to a small set of allowed domains. Simplify sign-out to clear all website data. Adjust Quick Feedback tip timings, swap the Dax image resource name, and update unit tests to match the revised scheduling and behavior.
…apple-browsers into shouts/quickfeedback
Contributor
Contributor
There was a problem hiding this comment.
Pull request overview
Adds an internal-user-only “Quick Feedback” popup flow on macOS (toolbar entry point + in-panel Asana form customization), aligning with the Windows implementation and routing existing internal feedback entry points to the popup instead of opening a tab.
Changes:
- Add
QuickFeedbackService+NSPanelwindow controller + Dax tip controller, and wire them into AppDelegate and internal feedback entry points. - Add diagnostics + screenshot placeholders to the Asana autofill JS and expand the JS to support a “quick mode” simplified UI.
- Add unit tests for the tip timing logic, diagnostics collector output, and distribution label formatting.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| macOS/UnitTests/Feedback/QuickFeedback/QuickFeedbackTipControllerTests.swift | Adds unit coverage for tip scheduling/cooldown and button-click persistence. |
| macOS/UnitTests/Feedback/QuickFeedback/QuickFeedbackDiagnosticsCollectorTests.swift | Adds unit coverage for diagnostics output structure, ordering, and optional tab/window counts. |
| macOS/UnitTests/Feedback/QuickFeedback/AppVersionModelDistributionLabelTests.swift | Adds tests for new distribution label behavior (DMG/App Store + Alpha suffix). |
| macOS/DuckDuckGo/Windows/View/WindowControllersManager.swift | Routes internal-user feedback modal entry to the popup; provides tab/window count via TabCountProviding. |
| macOS/DuckDuckGo/Tab/TabExtensions/InternalFeedbackFormTabExtension.swift | Updates JS placeholder replacements (app distribution label + quick-mode-related placeholders). |
| macOS/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift | Adds internal-only toolbar feedback button + tip scheduling + click routing to the popup. |
| macOS/DuckDuckGo/Menus/MainMenuActions.swift | Routes internal-user feedback menu actions to the popup instead of opening a tab. |
| macOS/DuckDuckGo/Feedback/Resources/internal-feedback-autofiller.js | Adds quick-mode behavior (hide fields, inject diagnostics/screenshot UI, submit hook). |
| macOS/DuckDuckGo/Feedback/QuickFeedback/QuickFeedbackWindowController.swift | Introduces the floating panel hosting a web view and sign-out bar. |
| macOS/DuckDuckGo/Feedback/QuickFeedback/QuickFeedbackTipController.swift | Introduces Dax discovery tip logic with cooldowns and auto-dismiss. |
| macOS/DuckDuckGo/Feedback/QuickFeedback/QuickFeedbackService.swift | Implements popup lifecycle, cookie inheritance, diagnostics/screenshot injection, and submission auto-hide. |
| macOS/DuckDuckGo/Feedback/QuickFeedback/QuickFeedbackDiagnosticsCollector.swift | Implements diagnostics collection (app/os/arch/gpu/memory/disk/tabs/session). |
| macOS/DuckDuckGo/Application/AppVersionModel.swift | Adds distributionLabel used by diagnostics and JS autofill. |
| macOS/DuckDuckGo/Application/AppDelegate.swift | Lazily wires up quickFeedbackService with diagnostics + fire-button publisher. |
| macOS/DuckDuckGo-macOS.xcodeproj/project.pbxproj | Registers new QuickFeedback sources and unit test files in the Xcode project. |
Injects a configurable launchDate into QuickFeedbackDiagnosticsCollector (defaults to Date()) and passes appLaunchDate from AppDelegate so diagnostics are deterministic/testable. Changes QuickFeedbackService.signOut to avoid wiping the entire default WKWebsiteDataStore: it now fetches data records and only removes records whose displayName contains 'asana' for the default store, while still clearing other non-default stores entirely. Updates internal feedback autofiller JS to always select 'Native Apps & Extensions' (removes the autoSelect parameter) and includes a minor whitespace cleanup in AppVersionModel.
Change QuickFeedbackService.forceClosePopup to call window.orderOut(nil) instead of window.close() to hide the feedback window without triggering a full close lifecycle. Remove the unused setTextareaValue helper from internal-feedback-autofiller.js to eliminate the textarea autofill logic (no longer needed/causing issues), leaving the other input autofill helpers intact.
Remove a stray blank line in AppVersionModel.swift and delete an outdated doc comment above the VPN setup in NavigationBarViewController.swift. Pure formatting/cleanup changes with no functional impact.
Switch openRequestANewFeature behavior for internal users to open quickFeedbackService.openFeedbackPopup(from: NSApp.mainWindow) instead of showing the internal feedback tab via WindowControllersManager. This displays a popup-based feedback UI for internal users.
Remove the webkit message-based handshake used when the feedback form is submitted. Deleted the formSubmittedMessageName constant, the WKScriptMessageHandler conformance and its delayed hidePopup logic, and the registration of the script message handler in QuickFeedbackService. Also removed the corresponding window.webkit.messageHandlers.feedbackFormSubmitted.postMessage call from internal-feedback-autofiller.js. These changes remove the in-page postMessage and related native handling for form submissions.
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ 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 f3b966a. Configure here.
Add a stored NSLayoutConstraint (signOutBarHeightConstraint) for the sign-out bar height and use it when activating constraints. setSignOutVisible now updates the constraint's constant to 28 or 0 to show/hide the bar instead of using a fixed height constraint, allowing the height to be toggled dynamically.
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/1211850802118632/task/1213914821996601
Tech Design URL: https://app.asana.com/1/137249556945/project/1211850802118632/task/1213878196777775?focus=true
CC:
Description
Adds a quick feedback popup for internal users on macOS, matching the Windows implementation. Instead of opening the Asana form in a full browser tab (slow, overwhelming, undiscoverable), internal users now get:
DesignSystemImages.Color.Size16.feedbackwith a 6pt spacer for visual separation.NSPanelhosting aWKWebViewthat loads the Asana form. JavaScript hides all irrelevant fields and injects a simplified "Report a Problem" UI with just a description textarea and Submit button. Auto-fills product area, platform, OS version, and app version.CGWindowListCreateImagebefore opening the popup. Displayed as an opt-in preview (unchecked by default) with a privacy warning and full-screen enlarge overlay.NSPopoveranchored to the toolbar button with rotating motivational messages. Pre-click: shows daily. Post-click: shows weekly. Auto-dismisses after 5 seconds.WKWebsiteDataStore(viaforIdentifier:on macOS 14+) keeps Asana cookies separate from the browsing session and survives Fire button presses. Asana cookies are copied from the main browser's default store on first open for seamless login inheritance.beforeunloadsuppression prevents navigation-blocking dialogs.Testing Steps
feedbackTip.lastShownandfeedbackTip.buttonClickedin UserDefaults), wait ~3 seconds — verify the Dax tip popover appears and auto-dismisses after ~5 seconds.beforeunloaddialog appears.Impact and Risks
Impact: None — This is internal tooling for DuckDuckGo employees only. The feature is gated behind
internalUserDecider.isInternalUserand has no effect on external users.What could go wrong?
DesignResourcesKitIconsremoves the feedback icon, the code won't compile (compile-time safe, no runtime failure).Quality Considerations
form.asana.com. Fire button during popup open correctly destroys the window controller. WebView reuse correctly re-navigates on reopen.QuickFeedbackServiceis lazily created. All diagnostics (IOKit,mach_task_basic_info, disk query) run only on user-initiated popup open in sub-millisecond time. Screenshot capture is ~5-20ms.WKWebsiteDataStore(viaforIdentifier:on macOS 14+) keeps Asana cookies separate from the browsing session. Onlyasana.comcookies are synced from the main browser for login inheritance — Microsoft SSO cookies are excluded. Sign out clears all data in the isolated store. No pixels or analytics added.QuickFeedbackServiceis not unit-tested due to tight coupling withWKWebView/NSPanel— covered by manual test steps above.Notes to Reviewer
DesignSystemImages.Color.Size16.feedback(notNSImage(named:)) to load from the correct Swift package bundle, andisTemplate = falseto render in color instead of monochrome.internal-feedback-autofiller.jsfile is significantly expanded — it now supports aquickModeflag that hides all Asana fields and injects the simplified form UI. The existing full-mode behavior (quickMode = false) is preserved for backward compatibility with the tab-based flow.Internal references:
Definition of Done | Engineering Expectations | Tech Design Template
Note
Medium Risk
Introduces a new internal-user-only feedback flow built on
WKWebView+ custom JS injection and cookie/data-store handling; regressions could affect internal feedback submission or cookie isolation, but external users are largely unaffected.Overview
Adds an internal-user Quick Feedback experience that opens the Asana feedback form in a floating popup (reused
NSPanel+WKWebView) instead of a full browser tab, and routes existing internal feedback entry points (Help/menu actions andWindowControllersManager.showFeedbackModal) to this popup.The popup auto-collects and optionally submits diagnostics (app/distribution label, OS, arch, GPU, memory, disk, tab/window counts, session length) and captures an opt-in screenshot of the current window; it uses an isolated persistent
WKWebsiteDataStoreon macOS 14+ (with Asana-cookie copying/sign-out clearing) and expandsinternal-feedback-autofiller.jsto support “quick mode” UI simplification, field hiding, diagnostics inclusion, and screenshot attachment.Adds a toolbar feedback button (internal users only) with a Dax tip popover cadence, plus new unit tests covering distribution labeling, diagnostics collection, and tip scheduling logic.
Reviewed by Cursor Bugbot for commit 8615c34. Bugbot is set up for automated code reviews on this repo. Configure here.