Bound message snapshot raster size

Co-authored-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz>
Signed-off-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz>
This commit is contained in:
Princess Donut
2026-08-15 11:22:34 +01:00
parent 661f08ae28
commit aab75fb9a9
2 changed files with 59 additions and 3 deletions
@@ -8,6 +8,13 @@ import 'package:flutter/rendering.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
const _iosMessageLongPressDuration = Duration(milliseconds: 200);
const _maxMessageSnapshotDimension = 2048.0;
double _messageSnapshotPixelRatio(Size size, double devicePixelRatio) {
final longestSide = size.longestSide;
if (!longestSide.isFinite || longestSide <= 0) return devicePixelRatio;
return math.min(devicePixelRatio, _maxMessageSnapshotDimension / longestSide);
}
/// Geometry and snapshot controls for a completed message long press.
class MessageLongPressDetails {
@@ -99,7 +106,7 @@ class _MessageLongPressRegion extends HookWidget {
onLongPress?.call(anchorRect);
return;
}
final snapshotPixelRatio = math.min(
final maxSnapshotPixelRatio = math.min(
MediaQuery.devicePixelRatioOf(context),
2.0,
);
@@ -113,6 +120,10 @@ class _MessageLongPressRegion extends HookWidget {
if (boundary == null) {
throw StateError('Message snapshot is unavailable');
}
final snapshotPixelRatio = _messageSnapshotPixelRatio(
boundary.size,
maxSnapshotPixelRatio,
);
try {
return await boundary.toImage(pixelRatio: snapshotPixelRatio);
} catch (_) {
@@ -123,10 +134,17 @@ class _MessageLongPressRegion extends HookWidget {
rethrow;
}
try {
return await retryBoundary.toImage(pixelRatio: snapshotPixelRatio);
return await retryBoundary.toImage(
pixelRatio: _messageSnapshotPixelRatio(
retryBoundary.size,
maxSnapshotPixelRatio,
),
);
} catch (_) {
if (snapshotPixelRatio <= 1) rethrow;
return retryBoundary.toImage(pixelRatio: 1);
return retryBoundary.toImage(
pixelRatio: _messageSnapshotPixelRatio(retryBoundary.size, 1),
);
}
}
}
@@ -441,6 +441,44 @@ void main() {
},
);
testWidgets('message snapshot bounds very tall raster dimensions', (
tester,
) async {
tester.view.devicePixelRatio = 1;
tester.view.physicalSize = const Size(800, 5000);
addTearDown(tester.view.resetDevicePixelRatio);
addTearDown(tester.view.resetPhysicalSize);
MessageLongPressDetails? longPressDetails;
ui.Image? snapshot;
addTearDown(() => snapshot?.dispose());
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: Material(
child: MessageLongPressInkWell(
key: const ValueKey('tall-snapshot-gesture-target'),
onLongPressDetails: (details) => longPressDetails = details,
child: const SizedBox(width: 240, height: 4096),
),
),
),
),
);
await tester.longPress(
find.byKey(const ValueKey('tall-snapshot-gesture-target')),
);
expect(longPressDetails, isNotNull);
final capture = longPressDetails!.captureSnapshot();
await tester.pump();
snapshot = await capture;
expect(snapshot.width, 120);
expect(snapshot.height, 2048);
});
testWidgets('message snapshot can exclude attached reaction content', (
tester,
) async {