feat: Add screenshot picker to feedback - #8655
Conversation
Add a privacy-preserving PHPicker flow to the user feedback form so users can attach one image without photo library authorization. Preserve the selected image bytes and metadata, enforce the attachment size limit, and support loading, removal, accessibility, and configurable labels. Add enableScreenshot, enabled by default, to Swift and ObjC. Update the sample, tests, changelog, and generated API surfaces. Closes #7969
|
📲 Install BuildsiOS
|
Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 66cfde1 | 1226.84 ms | 1255.50 ms | 28.66 ms |
| a505b7d | 1226.52 ms | 1260.67 ms | 34.15 ms |
| 9c19a06 | 1217.77 ms | 1248.98 ms | 31.21 ms |
| dd40710 | 1220.65 ms | 1251.36 ms | 30.71 ms |
| 7b6ea60 | 1230.86 ms | 1250.91 ms | 20.05 ms |
| fd30f64 | 1226.24 ms | 1251.23 ms | 24.99 ms |
| cf226b0 | 1217.35 ms | 1254.55 ms | 37.20 ms |
| 16c51a6 | 1215.72 ms | 1256.65 ms | 40.93 ms |
| c5a3e1c | 1226.65 ms | 1263.67 ms | 37.02 ms |
| 10c6b75 | 1207.09 ms | 1241.16 ms | 34.07 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 66cfde1 | 24.14 KiB | 1.20 MiB | 1.17 MiB |
| a505b7d | 24.14 KiB | 1.19 MiB | 1.17 MiB |
| 9c19a06 | 24.14 KiB | 1.16 MiB | 1.13 MiB |
| dd40710 | 24.14 KiB | 1.17 MiB | 1.14 MiB |
| 7b6ea60 | 24.14 KiB | 1.18 MiB | 1.15 MiB |
| fd30f64 | 24.14 KiB | 1.26 MiB | 1.23 MiB |
| cf226b0 | 24.14 KiB | 1.24 MiB | 1.21 MiB |
| 16c51a6 | 24.14 KiB | 1.17 MiB | 1.15 MiB |
| c5a3e1c | 24.14 KiB | 1.23 MiB | 1.20 MiB |
| 10c6b75 | 24.14 KiB | 1.27 MiB | 1.24 MiB |
Previous results on branch: feat/user-feedback-attachments
Startup times
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 1d9c012 | 1226.90 ms | 1268.91 ms | 42.01 ms |
| d7e3fcf | 1216.29 ms | 1271.80 ms | 55.51 ms |
| c62a0c9 | 1217.69 ms | 1265.09 ms | 47.40 ms |
| 5e54c2a | 1206.79 ms | 1238.12 ms | 31.34 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 1d9c012 | 24.14 KiB | 1.28 MiB | 1.25 MiB |
| d7e3fcf | 24.14 KiB | 1.27 MiB | 1.24 MiB |
| c62a0c9 | 24.14 KiB | 1.27 MiB | 1.25 MiB |
| 5e54c2a | 24.14 KiB | 1.27 MiB | 1.25 MiB |
|
@markushi We are introducing public API changes here, therefore i added you as a reviewer if you can find the time, thx! :bow |
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, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 744aea1. Configure here.
| func presentAlert(message: String, errorCode: Int, info: [String: Any]) { | ||
| let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert) | ||
| alert.addAction(UIAlertAction(title: "OK", style: .default)) | ||
| present(alert, animated: config.animations) { [config] in | ||
| presentErrorAlert(message: message) { [config] in |
There was a problem hiding this comment.
Bug: Conflicting Auto Layout constraints with priority 1000 are active when the screenshot view is hidden, causing warnings and unpredictable layout.
Severity: MEDIUM
Suggested Fix
To resolve the conflict, either lower the priority of the removeScreenshotButtonHeightConstraint to 999, or dynamically manage the constraints' active state. For example, set isActive = false on the conflicting constraints when the stack view is hidden and isActive = true when it becomes visible.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location:
Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackFormController.swift#L225-L226
Potential issue: When the `removeScreenshotStack` is hidden, `UIStackView` adds a hiding
constraint with priority 1000 to set its height to zero. However, the code adds a
`removeScreenshotButtonHeightConstraint` and a height-equality constraint between
`screenshotImageView` and `removeScreenshotButton`, both with the same required priority
of 1000. This conflict between the system's hiding constraint and the explicit height
constraints will generate Auto Layout warnings and can lead to unpredictable layout
behavior whenever the screenshot view is not visible.

📜 Description
Add a privacy-preserving PHPicker flow to the user feedback form so users can attach one image without photo library authorization.
Preserve the selected image bytes and metadata, enforce the attachment size limit, and support loading, removal, accessibility, and configurable labels. Add enableScreenshot, enabled by default, to Swift and ObjC.
Known image formats are uploaded directly, others fall back to jpeg encoding.
Update the sample, tests, changelog, and generated API surfaces.
💡 Motivation and Context
Closes #7969
💚 How did you test it?
Ran the sample app, verified image reached sentry. Added tests.
📝 Checklist
You have to check all boxes before merging:
sendDefaultPIIis enabled.