diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index 83086b77c6..093c07ac83 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -708,6 +708,7 @@ 84CFA4CA2C9DF884008DA5F4 /* SentryUserFeedbackWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CFA4C92C9DF884008DA5F4 /* SentryUserFeedbackWidget.swift */; }; 84CFA4CD2C9E0CA3008DA5F4 /* SentryUserFeedbackIntegration.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFA4CC2C9E0CA3008DA5F4 /* SentryUserFeedbackIntegration.m */; }; 84CFA4CE2C9E0CA3008DA5F4 /* SentryUserFeedbackIntegration.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFA4CB2C9E0CA3008DA5F4 /* SentryUserFeedbackIntegration.h */; }; + 84DBC62C2CE82F12000C4904 /* SentryFeedback.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DBC62B2CE82F0E000C4904 /* SentryFeedback.swift */; }; 84DEE86B2B686BD400A7BC17 /* SentrySamplerDecision.h in Headers */ = {isa = PBXBuildFile; fileRef = 84DEE86A2B686BD400A7BC17 /* SentrySamplerDecision.h */; }; 84DEE8762B69AD6400A7BC17 /* SentryLaunchProfiling.h in Headers */ = {isa = PBXBuildFile; fileRef = 84DEE8752B69AD6400A7BC17 /* SentryLaunchProfiling.h */; }; 84E13B842CBF1D91003B52EC /* SentryUserFeedbackWidgetButtonMegaphoneIconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E13B832CBF1D91003B52EC /* SentryUserFeedbackWidgetButtonMegaphoneIconView.swift */; }; @@ -1777,6 +1778,7 @@ 84CFA4C92C9DF884008DA5F4 /* SentryUserFeedbackWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryUserFeedbackWidget.swift; sourceTree = ""; }; 84CFA4CB2C9E0CA3008DA5F4 /* SentryUserFeedbackIntegration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryUserFeedbackIntegration.h; path = ../../../Sentry/include/SentryUserFeedbackIntegration.h; sourceTree = ""; }; 84CFA4CC2C9E0CA3008DA5F4 /* SentryUserFeedbackIntegration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SentryUserFeedbackIntegration.m; path = ../../../Sentry/SentryUserFeedbackIntegration.m; sourceTree = ""; }; + 84DBC62B2CE82F0E000C4904 /* SentryFeedback.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryFeedback.swift; sourceTree = ""; }; 84DEE86A2B686BD400A7BC17 /* SentrySamplerDecision.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentrySamplerDecision.h; path = include/SentrySamplerDecision.h; sourceTree = ""; }; 84DEE8752B69AD6400A7BC17 /* SentryLaunchProfiling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryLaunchProfiling.h; path = Sources/Sentry/include/SentryLaunchProfiling.h; sourceTree = SOURCE_ROOT; }; 84E13B832CBF1D91003B52EC /* SentryUserFeedbackWidgetButtonMegaphoneIconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryUserFeedbackWidgetButtonMegaphoneIconView.swift; sourceTree = ""; }; @@ -3524,6 +3526,7 @@ children = ( 849B8F9E2C70091A00148E1F /* Configuration */, 849B8F962C6E906900148E1F /* SentryUserFeedbackIntegrationDriver.swift */, + 84DBC62B2CE82F0E000C4904 /* SentryFeedback.swift */, 84CFA4CB2C9E0CA3008DA5F4 /* SentryUserFeedbackIntegration.h */, 84CFA4CC2C9E0CA3008DA5F4 /* SentryUserFeedbackIntegration.m */, 84CFA4C92C9DF884008DA5F4 /* SentryUserFeedbackWidget.swift */, @@ -4566,6 +4569,7 @@ 7B6438AB26A70F24000D0F65 /* UIViewController+Sentry.m in Sources */, 84302A812B5767A50027A629 /* SentryLaunchProfiling.m in Sources */, 63AA76A31EB9CBAA00D153DE /* SentryDsn.m in Sources */, + 84DBC62C2CE82F12000C4904 /* SentryFeedback.swift in Sources */, 63B818FA1EC34639002FDF4C /* SentryDebugMeta.m in Sources */, 7B98D7D325FB65AE00C5A389 /* SentryWatchdogTerminationTracker.m in Sources */, 8E564AE8267AF22600FE117D /* SentryNetworkTrackingIntegration.m in Sources */, diff --git a/Sources/Sentry/Public/SentrySDK.h b/Sources/Sentry/Public/SentrySDK.h index d11431f707..409cb08e71 100644 --- a/Sources/Sentry/Public/SentrySDK.h +++ b/Sources/Sentry/Public/SentrySDK.h @@ -6,11 +6,18 @@ @protocol SentrySpan; -@class SentryOptions, SentryEvent, SentryBreadcrumb, SentryScope, SentryUser, SentryId, - SentryUserFeedback, SentryTransactionContext; +@class SentryBreadcrumb; +@class SentryEvent; +@class SentryFeedback; +@class SentryId; @class SentryMetricsAPI; -@class UIView; +@class SentryOptions; @class SentryReplayApi; +@class SentryScope; +@class SentryTransactionContext; +@class SentryUser; +@class SentryUserFeedback; +@class UIView; NS_ASSUME_NONNULL_BEGIN @@ -246,25 +253,28 @@ SENTRY_NO_INIT /** * Captures user feedback that was manually gathered and sends it to Sentry. * @param userFeedback The user feedback to send to Sentry. + * @note This method will be deprecated in a future release; use `captureFeedback` instead. + */ ++ (void)captureUserFeedback:(SentryUserFeedback *)userFeedback + NS_SWIFT_NAME(capture(userFeedback:)); + +/** + * Captures user feedback that was manually gathered and sends it to Sentry. + * @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, * consider using `showUserFeedbackForm`, which delivers a prepackaged user feedback experience. See * @c SentryOptions.configureUserFeedback to customize a fully managed integration. See - * https://docs.sentry.io/platforms/apple/user-feedback/#user-feedback-api and (TODO: add link to - * new docs) for more information on each approach. + * https://docs.sentry.io/platforms/apple/user-feedback/ for more information. */ -+ (void)captureUserFeedback:(SentryUserFeedback *)userFeedback - NS_SWIFT_NAME(capture(userFeedback:)); ++ (void)captureFeedback:(SentryFeedback *)feedback NS_SWIFT_NAME(capture(feedback:)); /** * Display a form to gather information from an end user in the app to send to Sentry as a user * feedback event. - * @see @c SentryOptions.enableUserFeedbackIntegration and @c SentryOptions.configureUserFeedback to - * enable the functionality and customize the experience. - * @note If @c SentryOptions.enableUserFeedbackIntegration is @c NO, this method is a no-op. + * @see @c SentryOptions.configureUserFeedback to customize the experience. * @note This is a fully managed user feedback flow; there will be no need to call * @c SentrySDK.captureUserFeedback . See - * https://docs.sentry.io/platforms/apple/user-feedback/#user-feedback-api and (TODO: add link to - * new docs) for more information on each approach. + * https://docs.sentry.io/platforms/apple/user-feedback/ for more information. */ + (void)showUserFeedbackForm; diff --git a/Sources/Sentry/Public/SentryUserFeedback.h b/Sources/Sentry/Public/SentryUserFeedback.h index 6bd777f128..e915b18a6d 100644 --- a/Sources/Sentry/Public/SentryUserFeedback.h +++ b/Sources/Sentry/Public/SentryUserFeedback.h @@ -15,14 +15,24 @@ NS_ASSUME_NONNULL_BEGIN */ NS_SWIFT_NAME(UserFeedback) @interface SentryUserFeedback : NSObject -SENTRY_NO_INIT /** * Initializes SentryUserFeedback and sets the required eventId. * @param eventId The eventId of the event to which the user feedback is associated. + * @note Uses the old envelope format descried at + * https://develop.sentry.dev/sdk/data-model/envelope-items/#user-feedback and will be deprecated in + * the future. */ - (instancetype)initWithEventId:(SentryId *)eventId; +/** + * Initializes a new `SentryUserFeedback` as its own event, instead of one attached to a transaction + * or error event. + * @note Uses the new envelope format described at + * https://develop.sentry.dev/application/feedback-architecture/#feedback-events. + */ +- (instancetype)init; + /** * The eventId of the event to which the user feedback is associated. */ diff --git a/Sources/Sentry/SentryClient.m b/Sources/Sentry/SentryClient.m index a31ac3abff..167cd8a3a6 100644 --- a/Sources/Sentry/SentryClient.m +++ b/Sources/Sentry/SentryClient.m @@ -569,6 +569,16 @@ - (void)captureUserFeedback:(SentryUserFeedback *)userFeedback [self.transportAdapter sendUserFeedback:userFeedback]; } +- (void)captureFeedback:(SentryFeedback *)feedback +{ + if ([self isDisabled]) { + [self logDisabledMessage]; + return; + } + + [self.transportAdapter sendFeedback:feedback]; +} + - (void)storeEnvelope:(SentryEnvelope *)envelope { [self.fileManager storeEnvelope:envelope]; diff --git a/Sources/Sentry/SentryEnvelope.m b/Sources/Sentry/SentryEnvelope.m index 7b63610d2e..72181c0afd 100644 --- a/Sources/Sentry/SentryEnvelope.m +++ b/Sources/Sentry/SentryEnvelope.m @@ -129,6 +129,24 @@ - (instancetype)initWithUserFeedback:(SentryUserFeedback *)userFeedback data:json]; } +- (instancetype)initWithFeedback:(SentryFeedback *)feedback +{ + NSError *error = nil; + NSData *json = [NSJSONSerialization dataWithJSONObject:[feedback serialize] + options:0 + error:&error]; + + if (nil != error) { + SENTRY_LOG_ERROR(@"Couldn't serialize feedback."); + json = [NSData new]; + } + + return [self + initWithHeader:[[SentryEnvelopeItemHeader alloc] initWithType:SentryEnvelopeItemTypeFeedback + length:json.length] + data:json]; +} + - (instancetype)initWithClientReport:(SentryClientReport *)clientReport { NSError *error = nil; diff --git a/Sources/Sentry/SentryHub.m b/Sources/Sentry/SentryHub.m index 79989327f5..fc8be8fc3b 100644 --- a/Sources/Sentry/SentryHub.m +++ b/Sources/Sentry/SentryHub.m @@ -489,6 +489,14 @@ - (void)captureUserFeedback:(SentryUserFeedback *)userFeedback } } +- (void)captureFeedback:(SentryFeedback *)feedback +{ + SentryClient *client = _client; + if (client != nil) { + [client captureFeedback:feedback]; + } +} + - (void)addBreadcrumb:(SentryBreadcrumb *)crumb { SentryOptions *options = [[self client] options]; diff --git a/Sources/Sentry/SentrySDK.m b/Sources/Sentry/SentrySDK.m index 9a6048a773..7f61dcc202 100644 --- a/Sources/Sentry/SentrySDK.m +++ b/Sources/Sentry/SentrySDK.m @@ -406,6 +406,11 @@ + (void)captureUserFeedback:(SentryUserFeedback *)userFeedback [SentrySDK.currentHub captureUserFeedback:userFeedback]; } ++ (void)captureFeedback:(SentryFeedback *)feedback +{ + [SentrySDK.currentHub captureFeedback:feedback]; +} + + (void)showUserFeedbackForm { // TODO: implement diff --git a/Sources/Sentry/SentryTransportAdapter.m b/Sources/Sentry/SentryTransportAdapter.m index b63453bd53..28ef32598d 100644 --- a/Sources/Sentry/SentryTransportAdapter.m +++ b/Sources/Sentry/SentryTransportAdapter.m @@ -2,6 +2,7 @@ #import "SentryEnvelope.h" #import "SentryEvent.h" #import "SentryOptions.h" +#import "SentrySwift.h" #import "SentryUserFeedback.h" #import @@ -87,6 +88,16 @@ - (void)sendUserFeedback:(SentryUserFeedback *)userFeedback [self sendEnvelope:envelope]; } +- (void)sendFeedback:(SentryFeedback *)feedback +{ + SentryEnvelopeItem *item = [[SentryEnvelopeItem alloc] initWithFeedback:feedback]; + SentryEnvelopeHeader *envelopeHeader = + [[SentryEnvelopeHeader alloc] initWithId:feedback.eventId]; + SentryEnvelope *envelope = [[SentryEnvelope alloc] initWithHeader:envelopeHeader + singleItem:item]; + [self sendEnvelope:envelope]; +} + - (void)sendEnvelope:(SentryEnvelope *)envelope { for (id transport in self.transports) { diff --git a/Sources/Sentry/SentryUserFeedback.m b/Sources/Sentry/SentryUserFeedback.m index fc43f4bb2c..307574a61f 100644 --- a/Sources/Sentry/SentryUserFeedback.m +++ b/Sources/Sentry/SentryUserFeedback.m @@ -2,7 +2,26 @@ #import "SentrySwift.h" #import -@implementation SentryUserFeedback +typedef enum : NSUInteger { + /** A user feedback attached to a transaction or error event. */ + kSentryUserFeedbackTypeAttached, + + /** A user feedback sent as its own event independent of any other event. */ + kSentryUserFeedbackTypeStandalone, +} SentryUserFeedbackType; + +@implementation SentryUserFeedback { + SentryUserFeedbackType _type; +} + +- (instancetype)init +{ + if (self = [super init]) { + _type = kSentryUserFeedbackTypeStandalone; + _eventId = [[SentryId alloc] init]; + } + return self; +} - (instancetype)initWithEventId:(SentryId *)eventId { @@ -11,18 +30,26 @@ - (instancetype)initWithEventId:(SentryId *)eventId _email = @""; _name = @""; _comments = @""; + _type = kSentryUserFeedbackTypeAttached; } return self; } - (NSDictionary *)serialize { - return @{ - @"event_id" : self.eventId.sentryIdString, - @"email" : self.email, - @"name" : self.name, - @"comments" : self.comments - }; + switch (_type) { + case kSentryUserFeedbackTypeAttached: + return @{ + @"event_id" : self.eventId.sentryIdString, + @"email" : self.email, + @"name" : self.name, + @"comments" : self.comments + }; + case kSentryUserFeedbackTypeStandalone: + return @{ + + }; + } } @end diff --git a/Sources/Sentry/include/HybridPublic/SentryEnvelope.h b/Sources/Sentry/include/HybridPublic/SentryEnvelope.h index 76350d6b47..284bd252cd 100644 --- a/Sources/Sentry/include/HybridPublic/SentryEnvelope.h +++ b/Sources/Sentry/include/HybridPublic/SentryEnvelope.h @@ -7,13 +7,14 @@ #endif -@class SentryEvent; -@class SentrySession; -@class SentryId; -@class SentryUserFeedback; @class SentryAttachment; @class SentryEnvelopeItemHeader; +@class SentryEvent; +@class SentryFeedback; +@class SentryId; +@class SentrySession; @class SentryTraceContext; +@class SentryUserFeedback; NS_ASSUME_NONNULL_BEGIN @@ -82,6 +83,7 @@ SENTRY_NO_INIT - (instancetype)initWithEvent:(SentryEvent *)event; - (instancetype)initWithSession:(SentrySession *)session; - (instancetype)initWithUserFeedback:(SentryUserFeedback *)userFeedback; +- (instancetype)initWithFeedback:(SentryFeedback *)feedback; - (_Nullable instancetype)initWithAttachment:(SentryAttachment *)attachment maxAttachmentSize:(NSUInteger)maxAttachmentSize; - (instancetype)initWithHeader:(SentryEnvelopeItemHeader *)header diff --git a/Sources/Sentry/include/HybridPublic/SentryEnvelopeItemType.h b/Sources/Sentry/include/HybridPublic/SentryEnvelopeItemType.h index 811c441c89..f3ae59f983 100644 --- a/Sources/Sentry/include/HybridPublic/SentryEnvelopeItemType.h +++ b/Sources/Sentry/include/HybridPublic/SentryEnvelopeItemType.h @@ -3,6 +3,7 @@ static NSString *const SentryEnvelopeItemTypeEvent = @"event"; static NSString *const SentryEnvelopeItemTypeSession = @"session"; static NSString *const SentryEnvelopeItemTypeUserFeedback = @"user_report"; +static NSString *const SentryEnvelopeItemTypeFeedback = @"feedback"; static NSString *const SentryEnvelopeItemTypeTransaction = @"transaction"; static NSString *const SentryEnvelopeItemTypeAttachment = @"attachment"; static NSString *const SentryEnvelopeItemTypeClientReport = @"client_report"; diff --git a/Sources/Sentry/include/SentryClient+Private.h b/Sources/Sentry/include/SentryClient+Private.h index ccd95f1471..704c315221 100644 --- a/Sources/Sentry/include/SentryClient+Private.h +++ b/Sources/Sentry/include/SentryClient+Private.h @@ -2,8 +2,15 @@ #import "SentryDataCategory.h" #import "SentryDiscardReason.h" -@class SentrySession, SentryEnvelopeItem, SentryId, SentryAttachment, SentryThreadInspector, - SentryReplayEvent, SentryReplayRecording, SentryEnvelope; +@class SentryAttachment; +@class SentryEnvelope; +@class SentryEnvelopeItem; +@class SentryFeedback; +@class SentryId; +@class SentryReplayEvent; +@class SentryReplayRecording; +@class SentrySession; +@class SentryThreadInspector; NS_ASSUME_NONNULL_BEGIN @@ -63,6 +70,12 @@ NS_ASSUME_NONNULL_BEGIN - (void)addAttachmentProcessor:(id)attachmentProcessor; - (void)removeAttachmentProcessor:(id)attachmentProcessor; +/** + * Captures a new-style user feedback and sends it to Sentry. + * @param feedback The user feedback to send to Sentry. + */ +- (void)captureFeedback:(SentryFeedback *)feedback NS_SWIFT_NAME(capture(feedback:)); + @end NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryHub+Private.h b/Sources/Sentry/include/SentryHub+Private.h index a99c24a87f..2066ffff99 100644 --- a/Sources/Sentry/include/SentryHub+Private.h +++ b/Sources/Sentry/include/SentryHub+Private.h @@ -6,6 +6,7 @@ @class SentryTransaction; @class SentryDispatchQueueWrapper; @class SentryEnvelope; +@class SentryFeedback; @class SentryNSTimerFactory; @class SentrySession; @class SentryTracer; @@ -62,6 +63,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)storeEnvelope:(SentryEnvelope *)envelope; - (void)captureEnvelope:(SentryEnvelope *)envelope; +- (void)captureFeedback:(SentryFeedback *)feedback; - (void)registerSessionListener:(id)listener; - (void)unregisterSessionListener:(id)listener; diff --git a/Sources/Sentry/include/SentryPrivate.h b/Sources/Sentry/include/SentryPrivate.h index 28d5190819..36657301f7 100644 --- a/Sources/Sentry/include/SentryPrivate.h +++ b/Sources/Sentry/include/SentryPrivate.h @@ -3,6 +3,7 @@ #import "SentryDispatchQueueWrapper.h" #import "SentryNSDataUtils.h" #import "SentryRandom.h" +#import "SentrySDK+Private.h" #import "SentryTime.h" // Headers that also import SentryDefines should be at the end of this list diff --git a/Sources/Sentry/include/SentrySDK+Private.h b/Sources/Sentry/include/SentrySDK+Private.h index c4e486e89c..e8f02c0dc6 100644 --- a/Sources/Sentry/include/SentrySDK+Private.h +++ b/Sources/Sentry/include/SentrySDK+Private.h @@ -10,7 +10,11 @@ # import "SentrySDK.h" #endif -@class SentryHub, SentryId, SentryAppStartMeasurement, SentryEnvelope; +@class SentryAppStartMeasurement; +@class SentryEnvelope; +@class SentryFeedback; +@class SentryHub; +@class SentryId; NS_ASSUME_NONNULL_BEGIN @@ -51,6 +55,8 @@ NS_ASSUME_NONNULL_BEGIN */ + (void)captureEnvelope:(SentryEnvelope *)envelope; ++ (void)captureFeedback:(SentryFeedback *)feedback; + @end NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryTransportAdapter.h b/Sources/Sentry/include/SentryTransportAdapter.h index 81c7f36fc4..6929ff36a6 100644 --- a/Sources/Sentry/include/SentryTransportAdapter.h +++ b/Sources/Sentry/include/SentryTransportAdapter.h @@ -3,8 +3,15 @@ #import "SentryDiscardReason.h" #import "SentryTransport.h" -@class SentryEnvelope, SentryEnvelopeItem, SentryEvent, SentrySession, SentryUserFeedback, - SentryAttachment, SentryTraceContext, SentryOptions; +@class SentryAttachment; +@class SentryEnvelope; +@class SentryEnvelopeItem; +@class SentryEvent; +@class SentryFeedback; +@class SentryOptions; +@class SentrySession; +@class SentryTraceContext; +@class SentryUserFeedback; NS_ASSUME_NONNULL_BEGIN @@ -40,6 +47,7 @@ SENTRY_NO_INIT attachments:(NSArray *)attachments; - (void)sendUserFeedback:(SentryUserFeedback *)userFeedback NS_SWIFT_NAME(send(userFeedback:)); +- (void)sendFeedback:(SentryFeedback *)feedback NS_SWIFT_NAME(send(feedback:)); - (void)sendEnvelope:(SentryEnvelope *)envelope NS_SWIFT_NAME(send(envelope:)); diff --git a/Sources/Swift/Integrations/UserFeedback/SentryFeedback.swift b/Sources/Swift/Integrations/UserFeedback/SentryFeedback.swift new file mode 100644 index 0000000000..a4869523af --- /dev/null +++ b/Sources/Swift/Integrations/UserFeedback/SentryFeedback.swift @@ -0,0 +1,57 @@ +import Foundation +#if os(iOS) && !SENTRY_NO_UIKIT +@_implementationOnly import _SentryPrivate +import UIKit + +/** + * A user feedback item that serializes to an envelope with the new format described at + * https://develop.sentry.dev/application/feedback-architecture/#feedback-events. + */ +@objcMembers +class SentryFeedback: NSObject, SentrySerializable { + enum Source: String { + case widget + case custom + } + + var name: String? + var email: String? + var message: String + var hints: [String: Any]? + var source: Source + let eventId: SentryId + + /// The event id that this feedback is associated with, like a crash report. + var associatedEventId: String? + + init(name: String?, email: String?, message: String, hints: [String: Any]? = nil, source: Source = .widget, associatedEventId: String? = nil) { + self.eventId = SentryId() + self.name = name + self.email = email + self.message = message + self.hints = hints + self.source = source + self.associatedEventId = associatedEventId + super.init() + } + + func serialize() -> [String: Any] { + var dict: [String: Any] = [ + "message": message + ] + if let name = name { + dict["name"] = name + } + if let email = email { + dict["contact_email"] = email + } + if let associatedEventId = associatedEventId { + dict["associated_event_id"] = associatedEventId + } + dict["source"] = source.rawValue + + return dict + } +} + +#endif // os(iOS) && !SENTRY_NO_UIKIT diff --git a/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackForm.swift b/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackForm.swift index a2c1f10c5f..4ee2abca66 100644 --- a/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackForm.swift +++ b/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackForm.swift @@ -5,8 +5,7 @@ import UIKit @available(iOS 13.0, *) protocol SentryUserFeedbackFormDelegate: NSObjectProtocol { - func cancelled() - func confirmed() + func finished() } @available(iOS 13.0, *) @@ -109,12 +108,13 @@ class SentryUserFeedbackForm: UIViewController { } func submitFeedbackButtonTapped() { - // TODO: validate and package entries - delegate?.confirmed() + let feedback = SentryFeedback(name: fullNameTextField.text, email: emailTextField.text, message: messageTextView.text, hints: nil) + SentrySDK.capture(feedback: feedback) + delegate?.finished() } func cancelButtonTapped() { - delegate?.cancelled() + delegate?.finished() } // MARK: Layout diff --git a/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift b/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift index f9b3d7167c..6e7b887a31 100644 --- a/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift +++ b/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift @@ -60,18 +60,6 @@ class SentryUserFeedbackIntegrationDriver: NSObject { } - /** - * Captures feedback using custom UI. This method allows you to submit feedback data directly. - * - Parameters: - * - message: The feedback message (required). - * - name: The name of the user (optional). - * - email: The email of the user (optional). - * - hints: Additional hints or metadata for the feedback submission (optional). - */ - func captureFeedback(message: String, name: String? = nil, email: String? = nil, hints: [String: Any]? = nil) { - // Implementation to capture feedback - } - private func validate(_ config: SentryUserFeedbackWidgetConfiguration) { let noOpposingHorizontals = config.location.contains(.trailing) && !config.location.contains(.leading) || !config.location.contains(.trailing) && config.location.contains(.leading) diff --git a/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackWidget.swift b/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackWidget.swift index 986158422d..518058e284 100644 --- a/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackWidget.swift +++ b/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackWidget.swift @@ -66,12 +66,7 @@ struct SentryUserFeedbackWidget { // MARK: SentryUserFeedbackFormDelegate - func cancelled() { - closeForm() - } - - func confirmed() { - // TODO: submit + func finished() { closeForm() }