Skip to content

Commit 7708b0b

Browse files
authored
fix: Session replay masking not working inside scroll view (#4498)
Fixed calculation of scroll view children position for masking
1 parent 8fb1a4a commit 7708b0b

File tree

4 files changed

+33
-12
lines changed

4 files changed

+33
-12
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929

3030
- Masking text with transparent text color (#4499)
3131

32+
### Fixes
33+
34+
- Session replay masking not working inside scroll view (#4498)
35+
3236
## 8.39.0
3337

3438
### Removal of Experimental API

Samples/iOS-Swift/iOS-Swift/ViewControllers/TableViewController.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class TableViewController: UITableViewController {
3636

3737
let w = 1.0 - (Double(indexPath.row) / 99)
3838
cell.backgroundColor = UIColor(white: CGFloat(w), alpha: 1)
39+
cell.textLabel?.text = "Row #\(indexPath.row)"
3940

4041
return cell
4142
}

Sources/Swift/Tools/UIRedactBuilder.swift

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,9 @@ class UIRedactBuilder {
158158
var redactingRegions = [RedactRegion]()
159159

160160
self.mapRedactRegion(fromView: view,
161+
relativeTo: nil,
161162
redacting: &redactingRegions,
162-
rootFrame: view.frame,
163-
transform: CGAffineTransform.identity)
163+
rootFrame: view.frame)
164164

165165
var swiftUIRedact = [RedactRegion]()
166166
var otherRegions = [RedactRegion]()
@@ -198,12 +198,12 @@ class UIRedactBuilder {
198198
return image.imageAsset?.value(forKey: "_containingBundle") == nil
199199
}
200200

201-
private func mapRedactRegion(fromView view: UIView, redacting: inout [RedactRegion], rootFrame: CGRect, transform: CGAffineTransform, forceRedact: Bool = false) {
201+
private func mapRedactRegion(fromView view: UIView, relativeTo parentLayer: CALayer?, redacting: inout [RedactRegion], rootFrame: CGRect, forceRedact: Bool = false) {
202202
guard !redactClassesIdentifiers.isEmpty && !view.isHidden && view.alpha != 0 else { return }
203203

204204
let layer = view.layer.presentation() ?? view.layer
205205

206-
let newTransform = concatenateTranform(transform, with: layer)
206+
let newTransform = getTranform(from: layer, withParent: parentLayer)
207207

208208
let ignore = !forceRedact && shouldIgnore(view: view)
209209
let swiftUI = SentryRedactViewHelper.shouldRedactSwiftUI(view)
@@ -233,23 +233,24 @@ class UIRedactBuilder {
233233
redacting.append(RedactRegion(size: layer.bounds.size, transform: newTransform, type: .clipEnd))
234234
}
235235
for subview in view.subviews.sorted(by: { $0.layer.zPosition < $1.layer.zPosition }) {
236-
mapRedactRegion(fromView: subview, redacting: &redacting, rootFrame: rootFrame, transform: newTransform, forceRedact: enforceRedact)
236+
mapRedactRegion(fromView: subview, relativeTo: layer, redacting: &redacting, rootFrame: rootFrame, forceRedact: enforceRedact)
237237
}
238238
if view.clipsToBounds {
239239
redacting.append(RedactRegion(size: layer.bounds.size, transform: newTransform, type: .clipBegin))
240240
}
241241
}
242-
242+
243243
/**
244-
Apply the layer transformation and position to given transformation.
244+
Gets a transform that represents the layer global position.
245245
*/
246-
private func concatenateTranform(_ transform: CGAffineTransform, with layer: CALayer) -> CGAffineTransform {
246+
private func getTranform(from layer: CALayer, withParent parentLayer: CALayer?) -> CGAffineTransform {
247247
let size = layer.bounds.size
248-
let layerMiddle = CGPoint(x: size.width * layer.anchorPoint.x, y: size.height * layer.anchorPoint.y)
249-
250-
var newTransform = transform.translatedBy(x: layer.position.x, y: layer.position.y)
248+
let anchorPoint = CGPoint(x: size.width * layer.anchorPoint.x, y: size.height * layer.anchorPoint.y)
249+
let position = parentLayer?.convert(layer.position, to: nil) ?? layer.position
250+
251+
var newTransform = CGAffineTransform(translationX: position.x, y: position.y)
251252
newTransform = CATransform3DGetAffineTransform(layer.transform).concatenating(newTransform)
252-
return newTransform.translatedBy(x: -layerMiddle.x, y: -layerMiddle.y)
253+
return newTransform.translatedBy(x: -anchorPoint.x, y: -anchorPoint.y)
253254
}
254255

255256
/**

Tests/SentryTests/SentryViewPhotographerTests.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,21 @@ class SentryViewPhotographerTests: XCTestCase {
195195
assertColor(pixel1, .green)
196196
}
197197

198+
func testLabelInsideScrollView() throws {
199+
let label1 = UILabel(frame: CGRect(x: 0, y: 25, width: 50, height: 25))
200+
label1.text = "Test"
201+
label1.textColor = .green
202+
203+
let scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
204+
scrollView.addSubview(label1)
205+
scrollView.contentOffset = CGPoint(x: 0, y: 25)
206+
207+
let image = try XCTUnwrap(prepare(views: [scrollView]))
208+
let pixel1 = color(at: CGPoint(x: 10, y: 10), in: image)
209+
210+
assertColor(pixel1, .green)
211+
}
212+
198213
private func assertColor(_ color1: UIColor, _ color2: UIColor) {
199214
let sRGBColor1 = color1.cgColor.converted(to: CGColorSpace(name: CGColorSpace.sRGB)!, intent: .defaultIntent, options: nil)
200215
let sRGBColor2 = color2.cgColor.converted(to: CGColorSpace(name: CGColorSpace.sRGB)!, intent: .defaultIntent, options: nil)

0 commit comments

Comments
 (0)