Skip to content

Commit

Permalink
fix: mask sizing on scaling transform widget children (#2520)
Browse files Browse the repository at this point in the history
* fix: mask sizing on scaling transform widget children

* chore: changelog
  • Loading branch information
vaind authored Dec 20, 2024
1 parent ec83631 commit 1cc9547
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 45 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
### Fixes

- Missing replay gestures on Android ([#2515](https://github.com/getsentry/sentry-dart/pull/2515))
- Replay mask sizing on scaling transform widget children ([#2520](https://github.com/getsentry/sentry-dart/pull/2520))

### Enhancements

Expand Down
19 changes: 12 additions & 7 deletions flutter/lib/src/screenshot/recorder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,9 @@ class ScreenshotRecorder {
final filter = WidgetFilter(_maskingConfig!, options.logger);
final colorScheme = capture.context.findColorScheme();
filter.obscure(
root: capture.root,
context: capture.context,
pixelRatio: capture.pixelRatio,
colorScheme: colorScheme,
bounds: capture.bounds,
);
return filter.items;
}
Expand All @@ -134,14 +133,16 @@ class ScreenshotRecorder {
}

class _Capture<R> {
final RenderRepaintBoundary root;
final widgets.BuildContext context;
final double srcWidth;
final double srcHeight;
final double pixelRatio;
final _completer = Completer<R>();

_Capture._(
{required this.context,
{required this.root,
required this.context,
required this.srcWidth,
required this.srcHeight,
required this.pixelRatio});
Expand All @@ -158,16 +159,14 @@ class _Capture<R> {
widgets.MediaQuery.of(context).devicePixelRatio;

return _Capture._(
root: renderObject,
context: context,
srcWidth: srcWidth,
srcHeight: srcHeight,
pixelRatio: pixelRatio,
);
}

Rect get bounds =>
Rect.fromLTWH(0, 0, srcWidth * pixelRatio, srcHeight * pixelRatio);

int get width => (srcWidth * pixelRatio).round();

int get height => (srcHeight * pixelRatio).round();
Expand Down Expand Up @@ -226,7 +225,13 @@ class _Capture<R> {
final paint = Paint()..style = PaintingStyle.fill;
for (var item in items) {
paint.color = item.color;
canvas.drawRect(item.bounds, paint);
final source = item.bounds;
final scaled = Rect.fromLTRB(
source.left * pixelRatio,
source.top * pixelRatio,
source.right * pixelRatio,
source.bottom * pixelRatio);
canvas.drawRect(scaled, paint);
}
}
}
Expand Down
19 changes: 7 additions & 12 deletions flutter/lib/src/screenshot/widget_filter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class WidgetFilter {
final SentryLogger logger;
final SentryMaskingConfig config;
late WidgetFilterColorScheme _scheme;
late double _pixelRatio;
late RenderObject _root;
late Rect _bounds;
late List<Element> _visitList;
final _warnedWidgets = <int>{};
Expand All @@ -24,14 +24,14 @@ class WidgetFilter {
WidgetFilter(this.config, this.logger);

void obscure({
required RenderRepaintBoundary root,
required BuildContext context,
required double pixelRatio,
required Rect bounds,
required WidgetFilterColorScheme colorScheme,
Rect? bounds,
}) {
_pixelRatio = pixelRatio;
_bounds = bounds;
_root = root;
_scheme = colorScheme;
_bounds = bounds ?? Offset.zero & root.size;
assert(colorScheme.background.isOpaque);
assert(colorScheme.defaultMask.isOpaque);
assert(colorScheme.defaultTextMask.isOpaque);
Expand Down Expand Up @@ -215,13 +215,8 @@ class WidgetFilter {

@pragma('vm:prefer-inline')
Rect _boundingBox(RenderBox box) {
final offset = box.localToGlobal(Offset.zero);
return Rect.fromLTWH(
offset.dx * _pixelRatio,
offset.dy * _pixelRatio,
box.size.width * _pixelRatio,
box.size.height * _pixelRatio,
);
final transform = box.getTransformTo(_root);
return MatrixUtils.transformRect(transform, box.paintBounds);
}
}

Expand Down
2 changes: 1 addition & 1 deletion flutter/test/screenshot/test_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Future<Element> pumpTestElement(WidgetTester tester,
),
),
);
return TestWidgetsFlutterBinding.instance.rootElement!;
return find.byType(SentryScreenshotWidget).evaluate().first;
}

final testImageData = Uint8List.fromList([
Expand Down
39 changes: 14 additions & 25 deletions flutter/test/screenshot/widget_filter_test.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
Expand All @@ -12,7 +13,6 @@ import 'test_widget.dart';
// We'll keep these tests although they're not unit-tests anymore.
void main() async {
TestWidgetsFlutterBinding.ensureInitialized();
const defaultBounds = Rect.fromLTRB(0, 0, 1000, 1000);
final rootBundle = TestAssetBundle();
final otherBundle = TestAssetBundle();
final logger = MockLogger();
Expand Down Expand Up @@ -43,8 +43,7 @@ void main() async {
final element = await pumpTestElement(tester);
sut.obscure(
context: element,
pixelRatio: 1.0,
bounds: defaultBounds,
root: element.renderObject as RenderRepaintBoundary,
colorScheme: colorScheme);
expect(sut.items.length, 6);
});
Expand All @@ -54,8 +53,7 @@ void main() async {
final element = await pumpTestElement(tester);
sut.obscure(
context: element,
pixelRatio: 1.0,
bounds: defaultBounds,
root: element.renderObject as RenderRepaintBoundary,
colorScheme: colorScheme);
expect(sut.items.length, 0);
});
Expand All @@ -66,7 +64,7 @@ void main() async {
final element = await pumpTestElement(tester);
sut.obscure(
context: element,
pixelRatio: 1.0,
root: element.renderObject as RenderRepaintBoundary,
bounds: Rect.fromLTRB(0, 0, 100, 100),
colorScheme: colorScheme);
expect(sut.items.length, 1);
Expand All @@ -77,8 +75,7 @@ void main() async {
final element = await pumpTestElement(tester);
sut.obscure(
context: element,
pixelRatio: 1.0,
bounds: defaultBounds,
root: element.renderObject as RenderRepaintBoundary,
colorScheme: colorScheme);
expect(sut.items.length, 6);
expect(
Expand All @@ -100,8 +97,7 @@ void main() async {
final element = await pumpTestElement(tester);
sut.obscure(
context: element,
pixelRatio: 1.0,
bounds: defaultBounds,
root: element.renderObject as RenderRepaintBoundary,
colorScheme: colorScheme);
expect(sut.items.length, 3);
});
Expand Down Expand Up @@ -144,8 +140,7 @@ void main() async {
final element = await pumpTestElement(tester);
sut.obscure(
context: element,
pixelRatio: 1.0,
bounds: defaultBounds,
root: element.renderObject as RenderRepaintBoundary,
colorScheme: colorScheme);
expect(sut.items.length, 0);
});
Expand All @@ -156,7 +151,7 @@ void main() async {
final element = await pumpTestElement(tester);
sut.obscure(
context: element,
pixelRatio: 1.0,
root: element.renderObject as RenderRepaintBoundary,
bounds: Rect.fromLTRB(0, 0, 500, 100),
colorScheme: colorScheme);
expect(sut.items.length, 1);
Expand All @@ -167,8 +162,7 @@ void main() async {
final element = await pumpTestElement(tester);
sut.obscure(
context: element,
pixelRatio: 1.0,
bounds: defaultBounds,
root: element.renderObject as RenderRepaintBoundary,
colorScheme: colorScheme);
expect(sut.items.length, 3);
expect(boundsRect(sut.items[0]), '1x1');
Expand All @@ -184,8 +178,7 @@ void main() async {
]);
sut.obscure(
context: element,
pixelRatio: 1.0,
bounds: defaultBounds,
root: element.renderObject as RenderRepaintBoundary,
colorScheme: colorScheme);
expect(sut.items.length, 1);
expect(boundsRect(sut.items[0]), '344x248');
Expand All @@ -200,8 +193,7 @@ void main() async {
]);
sut.obscure(
context: element,
pixelRatio: 1.0,
bounds: defaultBounds,
root: element.renderObject as RenderRepaintBoundary,
colorScheme: colorScheme);
expect(sut.items, isEmpty);
});
Expand All @@ -213,16 +205,14 @@ void main() async {
]);
sut.obscure(
context: element,
pixelRatio: 1.0,
bounds: defaultBounds,
root: element.renderObject as RenderRepaintBoundary,
colorScheme: colorScheme);
expect(sut.items.length, 1);
expect(boundsRect(sut.items[0]), '144x48');
sut.throwInObscure = true;
sut.obscure(
context: element,
pixelRatio: 1.0,
bounds: defaultBounds,
root: element.renderObject as RenderRepaintBoundary,
colorScheme: colorScheme);
expect(sut.items.length, 1);
expect(boundsRect(sut.items[0]), '344x248');
Expand All @@ -239,8 +229,7 @@ void main() async {
await pumpTestElement(tester, children: [CustomPasswordWidget()]);
sut.obscure(
context: element,
pixelRatio: 1.0,
bounds: defaultBounds,
root: element.renderObject as RenderRepaintBoundary,
colorScheme: colorScheme);
final logMessages = logger.items
.where((item) => item.level == SentryLevel.warning)
Expand Down

0 comments on commit 1cc9547

Please sign in to comment.