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
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@
- Fix rendering method for fast view rendering (#6360)
- Fix issue where the thread that generated an event could be missing when more than 100 threads are running (#6377)
- Fix wrong Frame Delay when becoming active, which lead to false reported app hangs when the app moves to the foreground after being in the background (#6381)
- Session Replay masking improvements (#6292)
- Fix SwiftUI.List background decoration view causing incorrect clipping of screen content
- Fix sublayer rendering order by properly sorting by zPosition with insertion order as tie-breaker
- Fix UISwitch internal images being incorrectly redacted
- Fix UITextField placeholder text (UITextFieldLabel) not being detected for redaction
- Use string-based class comparison to avoid triggering Objective-C +initialize on background threads
- Add layer class filtering for views used in multiple contexts (e.g., SwiftUI._UIGraphicsView)
- Improve transform calculations for views with custom anchor points
- Fix axis-aligned transform detection for optimized opaque view clipping

### Improvements

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Foundation
import ObjectiveC.NSObjCRuntime
import UIKit

final class SentryRedactRegion {
struct SentryRedactRegion: Equatable {
let size: CGSize
let transform: CGAffineTransform
let type: SentryRedactRegionType
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
public enum SentryRedactRegionType: String, Codable {
public enum SentryRedactRegionType: String, Codable, Equatable {
/// Redacts the region.
case redact = "redact"

Expand Down
542 changes: 395 additions & 147 deletions Sources/Swift/Core/Tools/ViewCapture/SentryUIRedactBuilder.swift

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,12 @@ import UIKit
}

public func image(view: UIView, onComplete: @escaping ScreenshotCallback) {
// Define a helper variable for the size, so the view is not accessed in the async block
let viewSize = view.bounds.size

// The redact regions are expected to be thread-safe data structures
let redactRegions = redactBuilder.redactRegionsFor(view: view)

// The render method is synchronous and must be called on the main thread.
// This is because the render method accesses the view hierarchy which is managed from the main thread.
let renderedScreenshot = renderer.render(view: view)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,28 +342,32 @@ class SentrySessionReplayIntegrationTests: XCTestCase {
}

func testMaskViewFromSDK() throws {
class AnotherLabel: UILabel {
}
// -- Arrange --
class AnotherLabel: UILabel {}

startSDK(sessionSampleRate: 1, errorSampleRate: 1) { options in
options.sessionReplay.maskedViewClasses = [AnotherLabel.self]
}

let sut = try getSut()
let redactBuilder = sut.viewPhotographer.getRedactBuilder()
XCTAssertTrue(redactBuilder.containsRedactClass(AnotherLabel.self))

// -- Act --
let redactBuilder = try getSut().viewPhotographer.getRedactBuilder()

// -- Assert --
XCTAssertTrue(redactBuilder.containsRedactClass(viewClass: AnotherLabel.self, layerClass: CALayer.self))
}

func testIgnoreViewFromSDK() throws {
class AnotherLabel: UILabel {
}
// -- Arrange --
class AnotherLabel: UILabel {}

startSDK(sessionSampleRate: 1, errorSampleRate: 1) { options in
options.sessionReplay.unmaskedViewClasses = [AnotherLabel.self]
}

let sut = try getSut()
let redactBuilder = sut.viewPhotographer.getRedactBuilder()

// -- Act --
let redactBuilder = try getSut().viewPhotographer.getRedactBuilder()

// -- Assert --
XCTAssertTrue(redactBuilder.containsIgnoreClass(AnotherLabel.self))
}

Expand Down
Loading
Loading