Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
28 changes: 12 additions & 16 deletions Sentry.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

35 changes: 0 additions & 35 deletions Sources/Sentry/SentryFeedbackAPIHelper.m

This file was deleted.

4 changes: 2 additions & 2 deletions Sources/Sentry/SentryHub.m
Original file line number Diff line number Diff line change
Expand Up @@ -894,8 +894,8 @@ - (void)captureLog:(SentryLog *)log
#if SENTRY_TARGET_REPLAY_SUPPORTED
- (NSString *__nullable)getSessionReplayId
{
SentrySessionReplayIntegration *integration =
[self getInstalledIntegration:[SentrySessionReplayIntegration class]];
SentrySessionReplayIntegration *integration = (SentrySessionReplayIntegration *)[self
getInstalledIntegration:[SentrySessionReplayIntegration class]];
if (integration == nil || integration.sessionReplay == nil) {
return nil;
}
Expand Down
9 changes: 2 additions & 7 deletions Sources/Sentry/SentrySDKInternal.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,13 @@
#import "SentrySwiftAsyncIntegration.h"
#import "SentryTransactionContext.h"
#import "SentryUseNSExceptionCallstackWrapper.h"
#import "SentryUserFeedbackIntegration.h"

#if SENTRY_HAS_UIKIT
# import "SentryAppStartTrackingIntegration.h"
# import "SentryFramesTrackingIntegration.h"
# import "SentryPerformanceTrackingIntegration.h"
# import "SentryScreenshotIntegration.h"
# import "SentryUIEventTrackingIntegration.h"
# import "SentryUserFeedbackIntegration.h"
# import "SentryViewHierarchyIntegration.h"
# import "SentryWatchdogTerminationTrackingIntegration.h"
#endif // SENTRY_HAS_UIKIT
Expand Down Expand Up @@ -535,10 +533,6 @@ + (void)endSession
[SentryFileIOTrackingIntegration class], [SentryNetworkTrackingIntegration class],
[SentrySwiftAsyncIntegration class], nil];

#if TARGET_OS_IOS && SENTRY_HAS_UIKIT
[defaultIntegrations addObject:[SentryUserFeedbackIntegration class]];
#endif // TARGET_OS_IOS && SENTRY_HAS_UIKIT

#if SENTRY_HAS_METRIC_KIT
[defaultIntegrations addObject:[SentryMetricKitIntegration class]];
#endif // SENTRY_HAS_METRIC_KIT
Expand Down Expand Up @@ -567,7 +561,7 @@ + (void)installIntegrations
continue;
}

id<SentryIntegrationProtocol> integrationInstance = [[integrationClass alloc] init];
id<SentryObjCIntegrationProtocol> integrationInstance = [[integrationClass alloc] init];
BOOL shouldInstall = [integrationInstance installWithOptions:options];
if (shouldInstall) {
SENTRY_LOG_DEBUG(@"Integration installed: %@", NSStringFromClass(integrationClass));
Expand All @@ -576,6 +570,7 @@ + (void)installIntegrations
name:NSStringFromClass(integrationClass)];
}
}
[SentrySwiftIntegrationInstaller installWith:options];
}

+ (void)reportFullyDisplayed
Expand Down
52 changes: 0 additions & 52 deletions Sources/Sentry/SentryUserFeedbackIntegration.m

This file was deleted.

2 changes: 1 addition & 1 deletion Sources/Sentry/include/SentryBaseIntegration.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ typedef NS_OPTIONS(NSUInteger, SentryIntegrationOption) {

@class SentryOptions;

@interface SentryBaseIntegration : NSObject <SentryIntegrationProtocol>
@interface SentryBaseIntegration : NSObject <SentryObjCIntegrationProtocol>

- (NSString *)integrationName;
- (BOOL)installWithOptions:(SentryOptions *)options;
Expand Down
28 changes: 0 additions & 28 deletions Sources/Sentry/include/SentryFeedbackAPIHelper.h

This file was deleted.

18 changes: 14 additions & 4 deletions Sources/Sentry/include/SentryIntegrationProtocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,27 @@ NS_ASSUME_NONNULL_BEGIN

@class SentryOptions;

// All Integrations conform to this protocol so that the SDK
// can uninstall them when the SDK is closed.
@protocol SentryIntegrationProtocol <NSObject>

/**
* Installs the integration and returns YES if successful.
* Uninstalls the integration.
*/
- (BOOL)installWithOptions:(SentryOptions *)options NS_SWIFT_NAME(install(with:));
- (void)uninstall;

@end

// ObjC integrations conform to this protocol. This should not be used for new
// integrations. New ones should be written in Swift and use the `Sentry.Integration`
// protocol. The main difference is that the ObjC protocol does not inject dependencies
// so conformers need to access the singleton.
@protocol SentryObjCIntegrationProtocol <SentryIntegrationProtocol>

/**
* Uninstalls the integration.
* Installs the integration and returns YES if successful.
*/
- (void)uninstall;
- (BOOL)installWithOptions:(SentryOptions *)options NS_SWIFT_NAME(install(with:));

@end

Expand Down
2 changes: 1 addition & 1 deletion Sources/Sentry/include/SentryPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#import "SentryEnvelopeAttachmentHeader.h"
#import "SentryEventSwiftHelper.h"
#import "SentryHub+Private.h"
#import "SentryIntegrationProtocol.h"
#import "SentryNSDataUtils.h"
#import "SentrySDK+Private.h"
#import "SentryTime.h"
Expand All @@ -47,7 +48,6 @@
#import "SentryDelayedFramesTracker.h"
#import "SentryDependencyContainerSwiftHelper.h"
#import "SentryDeviceContextKeys.h"
#import "SentryFeedbackAPIHelper.h"
#import "SentryFileIOTrackerHelper.h"
#import "SentryFileManagerHelper.h"
#import "SentryMeta.h"
Expand Down
17 changes: 0 additions & 17 deletions Sources/Sentry/include/SentryUserFeedbackIntegration.h

This file was deleted.

48 changes: 48 additions & 0 deletions Sources/Swift/Core/Integrations/Integrations.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
@_implementationOnly import _SentryPrivate

// The Swift counterpart to `SentryObjcIntegrationProtocol`. This protocol allows
// injecting the dependencies in a way that does not require the Integration to
// depend on SentryDependencyContainer.
protocol SwiftIntegration: SentryIntegrationProtocol {
// The dependencies required for the integration. The easiest way to satisfy this requirement when migrating from ObjC
// is to define it as `SentryDependencyContainer` with a typealias. However, a generic Swift class that has a protocol
// constraint on the `Dependencies` type can make it easier to test and to use without a direct dependency on all
// of `SentryDependencyContainer`.
associatedtype Dependencies

// The initializer is failable, return nil if the integration was not installed, for example when the options that enable the integration is not enabled.
init?(with options: Options, dependencies: Dependencies)

// Name of the integration that is used by `SentrySdkInfo`
static var name: String { get }
}

// Type erases the `Integration` so that it can be stored in an array and used for `addInstalledIntegration`
private struct AnyIntegration {
let install: (Options, SentryDependencyContainer) -> SentryIntegrationProtocol?
let name: String

init<I: SwiftIntegration>(_ integration: I.Type) where I.Dependencies == SentryDependencyContainer {
name = I.name
install = {
integration.init(with: $0, dependencies: $1)
}
}
}

// Bridges to ObjC code to trigger installing the integrations
@_spi(Private) @objc public final class SentrySwiftIntegrationInstaller: NSObject {
@objc public class func install(with options: Options) {
let dependencies = SentryDependencyContainer.sharedInstance()
#if os(iOS) && !SENTRY_NO_UIKIT
let integrations: [AnyIntegration] = [.init(UserFeedbackIntegration<SentryDependencyContainer>.self)]
#else
let integrations: [AnyIntegration] = []
#endif
integrations.forEach { anyIntegration in
guard let integration = anyIntegration.install(options, dependencies) else { return }

SentrySDKInternal.currentHub().addInstalledIntegration(integration, name: anyIntegration.name)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,19 @@ public final class SentryFeedbackAPI: NSObject {
/// - seealso: See `SentryOptions.configureUserFeedback` to configure the widget.
@available(iOSApplicationExtension, unavailable)
@objc public func showWidget() {
SentryFeedbackAPIHelper.showWidget()
getIntegration()?.driver.showWidget()
}

/// Hide the feedback widget button.
/// - warning: This is an experimental feature and may still have bugs.
/// - seealso: See `SentryOptions.configureUserFeedback` to configure the widget.
@available(iOSApplicationExtension, unavailable)
@objc public func hideWidget() {
SentryFeedbackAPIHelper.hideWidget()
getIntegration()?.driver.hideWidget()
}

private func getIntegration() -> UserFeedbackIntegration<SentryDependencyContainer>? {
SentrySDKInternal.currentHub().getInstalledIntegration(UserFeedbackIntegration<SentryDependencyContainer>.self) as? UserFeedbackIntegration<SentryDependencyContainer>
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,21 @@ import Foundation
@_implementationOnly import _SentryPrivate
import UIKit

@objc
@_spi(Private) public protocol SentryUserFeedbackIntegrationDriverDelegate: NSObjectProtocol {
func capture(feedback: SentryFeedback)
}

/**
* An integration managing a workflow for end users to report feedback via Sentry.
* - note: The default method to show the feedback form is via a floating widget placed in the bottom trailing corner of the screen. See the configuration classes for alternative options.
*/
@available(iOSApplicationExtension, unavailable)
@objcMembers
@_spi(Private) public class SentryUserFeedbackIntegrationDriver: NSObject {
final class SentryUserFeedbackIntegrationDriver: NSObject {
let configuration: SentryUserFeedbackConfiguration
private var widget: SentryUserFeedbackWidget?
weak var delegate: (any SentryUserFeedbackIntegrationDriverDelegate)?
fileprivate let callback: (SentryFeedback) -> Void
let screenshotSource: SentryScreenshotSource
weak var customButton: UIButton?

@_spi(Private) public init(configuration: SentryUserFeedbackConfiguration, delegate: any SentryUserFeedbackIntegrationDriverDelegate, screenshotSource: SentryScreenshotSource) {
init(configuration: SentryUserFeedbackConfiguration, screenshotSource: SentryScreenshotSource, callback: @escaping (SentryFeedback) -> Void) {
self.configuration = configuration
self.delegate = delegate
self.callback = callback
self.screenshotSource = screenshotSource
super.init()

Expand Down Expand Up @@ -64,15 +58,15 @@ import UIKit
customButton?.removeTarget(self, action: #selector(showForm(sender:)), for: .touchUpInside)
}

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

widget?.rootVC.setWidget(visible: true, animated: configuration.animations)
}

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

Expand All @@ -88,7 +82,7 @@ import UIKit
extension SentryUserFeedbackIntegrationDriver: SentryUserFeedbackFormDelegate {
func finished(with feedback: SentryFeedback?) {
if let feedback = feedback {
delegate?.capture(feedback: feedback)
callback(feedback)
}
presenter?.dismiss(animated: configuration.animations) {
self.configuration.onFormClose?()
Expand Down
Loading
Loading