Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

### Features

- Apps can now manually show and hide the included feedback widget button (#5236)

## 8.50.2

### Fixes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,7 @@ public enum SentrySDKOverrides {

public var boolValue: Bool {
get {
switch self {
case .disableAutoInject: return getBoolOverride(for: rawValue)
default: return getBoolOverride(for: rawValue)
}
return getBoolOverride(for: rawValue)
}
set(newValue) {
setBoolOverride(for: rawValue, value: newValue)
Expand Down
12 changes: 12 additions & 0 deletions Samples/iOS-Swift/iOS-Swift-UITests/UserFeedbackUITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,8 @@ extension UserFeedbackUITests {
XCTAssertEqual(try dictionaryFromSuccessHookFile(), ["name": testName, "message": "UITest user feedback", "email": testContactEmail])
}

// MARK: Alternative widget control

func testFormShowsAndDismissesProperlyWithCustomButton() {
launchApp(args: ["--io.sentry.feedback.use-custom-feedback-button"])

Expand All @@ -512,6 +514,16 @@ extension UserFeedbackUITests {
XCTAssert(customButton.isHittable)
XCTAssertFalse(widgetButton.isHittable)
}

func testManuallyDisplayingWidget() {
launchApp(args: ["--io.sentry.feedback.no-auto-inject-widget"])
XCTAssertFalse(widgetButton.isHittable)
extrasAreaTabBarButton.tap()
app.buttons["io.sentry.ui-test.button.show-widget"].tap()
XCTAssert(widgetButton.isHittable)
app.buttons["io.sentry.ui-test.button.hide-widget"].tap()
XCTAssertFalse(widgetButton.isHittable)
}
}

// MARK: UI Element access
Expand Down
90 changes: 59 additions & 31 deletions Samples/iOS-Swift/iOS-Swift/Base.lproj/Main.storyboard

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions Samples/iOS-Swift/iOS-Swift/ExtraViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -348,4 +348,20 @@ class ExtraViewController: UIViewController {
result["item_header_type"] = json["type"]
}
}

@IBAction func showFeedbackWidget(_ sender: Any) {
if #available(iOS 13.0, *) {
SentrySDK.showFeedbackWidget()
} else {
showToast(in: self, type: .warning, message: "Feedback widget only available in iOS 13 or later.")
}
}

@IBAction func hideFeedbackWidget(_ sender: Any) {
if #available(iOS 13.0, *) {
SentrySDK.hideFeedbackWidget()
} else {
showToast(in: self, type: .warning, message: "Feedback widget only available in iOS 13 or later.")
}
}
}
1 change: 1 addition & 0 deletions Sources/Sentry/Public/SentryOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,7 @@ typedef void (^SentryProfilingConfigurationBlock)(SentryProfileOptions *_Nonnull
* either this block to configure a widget and UI form to gather feedback, or directly submits
* feedback you've gathered using your own UI by calling the method @c SentrySDK.captureFeedback
* (se https://docs.sentry.io/platforms/apple/user-feedback/configuration/).
* @note User feedback widget is only available for iOS 13 or later.
*/
@property (nonatomic, copy, nullable)
SentryUserFeedbackConfigurationBlock configureUserFeedback API_AVAILABLE(ios(13.0));
Expand Down
21 changes: 21 additions & 0 deletions Sources/Sentry/Public/SentrySDK.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,13 +263,34 @@ SENTRY_NO_INIT

/**
* Captures user feedback that was manually gathered and sends it to Sentry.
* @warning This is an experimental feature and may still have bugs.
* @param feedback The feedback to send to Sentry.
* @note If you'd prefer not to have to build the UI required to gather the feedback from the user,
* see @c SentryOptions.configureUserFeedback to customize a fully managed integration. See
* https://docs.sentry.io/platforms/apple/user-feedback/ for more information.
*/
+ (void)captureFeedback:(SentryFeedback *)feedback NS_SWIFT_NAME(capture(feedback:));

#if TARGET_OS_IOS && SENTRY_HAS_UIKIT

/**
* Show the feedback widget button.
* @warning This is an experimental feature and may still have bugs.
* @seealso See @c SentryOptions.configureUserFeedback to configure the widget.
* @note User feedback widget is only available for iOS 13 or later.
*/
+ (void)showFeedbackWidget API_AVAILABLE(ios(13.0));

/**
* Hide the feedback widget button.
* @warning This is an experimental feature and may still have bugs.
* @seealso See @c SentryOptions.configureUserFeedback to configure the widget.
* @note User feedback widget is only available for iOS 13 or later.
*/
+ (void)hideFeedbackWidget API_AVAILABLE(ios(13.0));

#endif // TARGET_OS_IOS && SENTRY_HAS_UIKIT

/**
* Adds a Breadcrumb to the current Scope of the current Hub. If the total number of breadcrumbs
* exceeds the @c SentryOptions.maxBreadcrumbs the SDK removes the oldest breadcrumb.
Expand Down
27 changes: 27 additions & 0 deletions Sources/Sentry/SentrySDK.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#import "SentrySerialization.h"
#import "SentrySwift.h"
#import "SentryTransactionContext.h"
#import "SentryUserFeedbackIntegration.h"

#if TARGET_OS_OSX
# import "SentryCrashExceptionApplication.h"
Expand Down Expand Up @@ -431,6 +432,32 @@
[SentrySDK.currentHub captureFeedback:feedback];
}

#if TARGET_OS_IOS && SENTRY_HAS_UIKIT

+ (void)showFeedbackWidget
{
if (@available(iOS 13.0, *)) {
SentryUserFeedbackIntegration *feedback =
[currentHub getInstalledIntegration:[SentryUserFeedbackIntegration class]];
[feedback showWidget];

Check warning on line 442 in Sources/Sentry/SentrySDK.m

View check run for this annotation

Codecov / codecov/patch

Sources/Sentry/SentrySDK.m#L440-L442

Added lines #L440 - L442 were not covered by tests
} else {
SENTRY_LOG_WARN(@"Sentry User Feedback is only available on iOS 13 or later.");
}
}

Check warning on line 446 in Sources/Sentry/SentrySDK.m

View check run for this annotation

Codecov / codecov/patch

Sources/Sentry/SentrySDK.m#L445-L446

Added lines #L445 - L446 were not covered by tests

+ (void)hideFeedbackWidget
{
if (@available(iOS 13.0, *)) {
SentryUserFeedbackIntegration *feedback =
[currentHub getInstalledIntegration:[SentryUserFeedbackIntegration class]];
[feedback hideWidget];

Check warning on line 453 in Sources/Sentry/SentrySDK.m

View check run for this annotation

Codecov / codecov/patch

Sources/Sentry/SentrySDK.m#L451-L453

Added lines #L451 - L453 were not covered by tests
} else {
SENTRY_LOG_WARN(@"Sentry User Feedback is only available on iOS 13 or later.");
}
}

Check warning on line 457 in Sources/Sentry/SentrySDK.m

View check run for this annotation

Codecov / codecov/patch

Sources/Sentry/SentrySDK.m#L456-L457

Added lines #L456 - L457 were not covered by tests

#endif // TARGET_OS_IOS && SENTRY_HAS_UIKIT

+ (void)addBreadcrumb:(SentryBreadcrumb *)crumb
{
[SentrySDK.currentHub addBreadcrumb:crumb];
Expand Down
10 changes: 10 additions & 0 deletions Sources/Sentry/SentryUserFeedbackIntegration.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@
return YES;
}

- (void)showWidget
{
[_driver showWidget];
}

Check warning on line 33 in Sources/Sentry/SentryUserFeedbackIntegration.m

View check run for this annotation

Codecov / codecov/patch

Sources/Sentry/SentryUserFeedbackIntegration.m#L32-L33

Added lines #L32 - L33 were not covered by tests

- (void)hideWidget
{
[_driver hideWidget];
}

Check warning on line 38 in Sources/Sentry/SentryUserFeedbackIntegration.m

View check run for this annotation

Codecov / codecov/patch

Sources/Sentry/SentryUserFeedbackIntegration.m#L37-L38

Added lines #L37 - L38 were not covered by tests

// MARK: SentryUserFeedbackIntegrationDriverDelegate

- (void)captureWithFeedback:(SentryFeedback *)feedback
Expand Down
3 changes: 2 additions & 1 deletion Sources/Sentry/include/SentryUserFeedbackIntegration.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ NS_ASSUME_NONNULL_BEGIN

API_AVAILABLE(ios(13.0))
@interface SentryUserFeedbackIntegration : SentryBaseIntegration

- (void)showWidget;
- (void)hideWidget;
@end

NS_ASSUME_NONNULL_END
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@
customButton?.removeTarget(self, action: #selector(showForm(sender:)), for: .touchUpInside)
}

@objc public func showWidget() {
if widget == nil {
widget = SentryUserFeedbackWidget(config: configuration, delegate: self)

Check warning on line 59 in Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift#L59

Added line #L59 was not covered by tests
} else {
widget?.rootVC.setWidget(visible: true, animated: configuration.animations)

Check warning on line 61 in Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift#L61

Added line #L61 was not covered by tests
}
}

Check warning on line 63 in Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift#L63

Added line #L63 was not covered by tests

@objc public func hideWidget() {
widget?.rootVC.setWidget(visible: false, animated: configuration.animations)
}

Check warning on line 67 in Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift#L66-L67

Added lines #L66 - L67 were not covered by tests

@objc func showForm(sender: UIButton) {
presenter?.present(SentryUserFeedbackFormController(config: configuration, delegate: self, screenshot: nil), animated: configuration.animations) {
self.configuration.onFormOpen?()
Expand All @@ -72,6 +84,7 @@
self.configuration.onFormClose?()
}
widget?.rootVC.setWidget(visible: true, animated: configuration.animations)
displayingForm = false

Check warning on line 87 in Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift#L87

Added line #L87 was not covered by tests
}
}

Expand All @@ -88,6 +101,7 @@
extension SentryUserFeedbackIntegrationDriver: UIAdaptivePresentationControllerDelegate {
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
widget?.rootVC.setWidget(visible: true, animated: configuration.animations)
displayingForm = false

Check warning on line 104 in Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift#L104

Added line #L104 was not covered by tests
configuration.onFormClose?()
}
}
Expand All @@ -99,6 +113,7 @@
let form = SentryUserFeedbackFormController(config: configuration, delegate: self, screenshot: screenshot)
form.presentationController?.delegate = self
widget?.rootVC.setWidget(visible: false, animated: configuration.animations)
displayingForm = true

Check warning on line 116 in Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift#L116

Added line #L116 was not covered by tests
presenter?.present(form, animated: configuration.animations) {
self.configuration.onFormOpen?()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,6 @@ class SentryUserFeedbackWidget {
} else {
button?.isHidden = !visible
}

displayingForm = !visible
}
}
}
Expand Down
Loading