Unverified Commit af09b57e authored by pdblasi-google's avatar pdblasi-google Committed by GitHub

Removes deprecated APIs from AnimationBuilder (#129657)

Removes deprecated APIs from AnimationBuilder.

Resolves #129653
parent 51bef1b6
......@@ -20,60 +20,6 @@ void main() {
* because [matchesGoldenFile] does not use Skia Gold in its native package.
*/
testWidgetsWithLeakTracking('correctly records frames using display', (WidgetTester tester) async {
final AnimationSheetBuilder builder = AnimationSheetBuilder(frameSize: _DecuplePixels.size);
await tester.pumpFrames(
builder.record(
const _DecuplePixels(Duration(seconds: 1)),
),
const Duration(milliseconds: 200),
const Duration(milliseconds: 100),
);
await tester.pumpFrames(
builder.record(
const _DecuplePixels(Duration(seconds: 1)),
recording: false,
),
const Duration(milliseconds: 200),
const Duration(milliseconds: 100),
);
await tester.pumpFrames(
builder.record(
const _DecuplePixels(Duration(seconds: 1)),
),
const Duration(milliseconds: 400),
const Duration(milliseconds: 100),
);
// This test verifies deprecated methods.
final Widget display = await builder.display(); // ignore: deprecated_member_use
await tester.binding.setSurfaceSize(builder.sheetSize()); // ignore: deprecated_member_use
await tester.pumpWidget(display);
await expectLater(find.byWidget(display), matchesGoldenFile('test.animation_sheet_builder.records.png'));
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/56001
testWidgetsWithLeakTracking('correctly wraps a row', (WidgetTester tester) async {
final AnimationSheetBuilder builder = AnimationSheetBuilder(frameSize: _DecuplePixels.size);
const Duration duration = Duration(seconds: 2);
await tester.pumpFrames(
builder.record(const _DecuplePixels(duration)),
duration,
const Duration(milliseconds: 200),
);
// This test verifies deprecated methods.
final Widget display = await builder.display(); // ignore: deprecated_member_use
await tester.binding.setSurfaceSize(builder.sheetSize(maxWidth: 80)); // ignore: deprecated_member_use
await tester.pumpWidget(display);
await expectLater(find.byWidget(display), matchesGoldenFile('test.animation_sheet_builder.wraps.png'));
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/56001
testWidgetsWithLeakTracking('correctly records frames using collate', (WidgetTester tester) async {
final AnimationSheetBuilder builder = AnimationSheetBuilder(frameSize: _DecuplePixels.size);
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:math' as math;
import 'dart:ui' as ui;
import 'package:flutter/foundation.dart';
......@@ -136,7 +135,7 @@ class AnimationSheetBuilder {
/// The frame is only recorded if the `recording` argument is true, or during
/// a procedure that is wrapped within [recording]. In either case, the
/// painted result of each frame will be stored and later available for
/// [display]. If neither condition is met, the frames are not recorded, which
/// [collate]. If neither condition is met, the frames are not recorded, which
/// is useful during setup phases.
///
/// The `child` must not be null.
......@@ -158,113 +157,6 @@ class AnimationSheetBuilder {
);
}
/// Constructs a widget that renders the recorded frames in an animation sheet.
///
/// The resulting widget takes as much space as its parent allows, which is
/// usually the screen size. It is then filled with all recorded frames, each
/// having a size specified by [frameSize], chronologically from top-left to
/// bottom-right in a row-major order.
///
/// This widget does not check whether its size fits all recorded frames.
/// Having too many frames can cause overflow errors, while having too few can
/// waste the size of golden files. Therefore you should usually adjust the
/// viewport size to [sheetSize] before calling this method.
///
/// The `key` is applied to the root widget.
///
/// This method can only be called if at least one frame has been recorded.
///
/// The [display] is the legacy way of acquiring the output for comparison.
/// It is not recommended because it requires more boilerplate, and produces
/// a much large image than necessary: each pixel is rendered in 3x3 pixels
/// without higher definition. Use [collate] instead.
///
/// Using this way includes the following steps:
///
/// * Create an instance of this class.
/// * Pump frames that render the target widget wrapped in [record]. Every frame
/// that has `recording` being true will be recorded.
/// * Adjust the size of the test viewport to the [sheetSize] (see the
/// documentation of [sheetSize] for more information).
/// * Pump a frame that renders [display], which shows all recorded frames in an
/// animation sheet, and can be matched against the golden test.
///
/// {@tool snippet}
/// The following example shows how to record an animation sheet of an [InkWell]
/// being pressed then released.
///
/// ```dart
/// testWidgets('Inkwell animation sheet', (WidgetTester tester) async {
/// // Create instance
/// final AnimationSheetBuilder animationSheet = AnimationSheetBuilder(frameSize: const Size(48, 24));
///
/// final Widget target = Material(
/// child: Directionality(
/// textDirection: TextDirection.ltr,
/// child: InkWell(
/// splashColor: Colors.blue,
/// onTap: () {},
/// ),
/// ),
/// );
///
/// // Optional: setup before recording (`recording` is false)
/// await tester.pumpWidget(animationSheet.record(
/// target,
/// recording: false,
/// ));
///
/// final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(InkWell)));
///
/// // Start recording (`recording` is true)
/// await tester.pumpFrames(animationSheet.record(
/// target,
/// recording: true,
/// ), const Duration(seconds: 1));
///
/// await gesture.up();
///
/// await tester.pumpFrames(animationSheet.record(
/// target,
/// recording: true,
/// ), const Duration(seconds: 1));
///
/// // Adjust view port size
/// tester.binding.setSurfaceSize(animationSheet.sheetSize());
///
/// // Display
/// final Widget display = await animationSheet.display();
/// await tester.pumpWidget(display);
///
/// // Compare against golden file
/// await expectLater(
/// find.byWidget(display),
/// matchesGoldenFile('inkwell.press.animation.png'),
/// );
/// }, skip: isBrowser); // Animation sheet does not support browser https://github.com/flutter/flutter/issues/56001
/// ```
/// {@end-tool}
@Deprecated(
'Use AnimationSheetBuilder.collate instead. '
'This feature was deprecated after v2.3.0-13.0.pre.',
)
Future<Widget> display({Key? key}) async {
assert(_recordedFrames.isNotEmpty);
final List<ui.Image> frames = await _frames;
return _CellSheet(
key: key,
cellSize: frameSize,
children: frames.map((ui.Image image) => RawImage(
image: image.clone(),
width: frameSize.width,
height: frameSize.height,
// Disable quality enhancement because the point of this class is to
// precisely record what the widget looks like.
filterQuality: ui.FilterQuality.none,
)).toList(),
);
}
/// Returns an result image by putting all frames together in a table.
///
/// This method returns a table of captured frames, `cellsPerRow` images
......@@ -277,39 +169,6 @@ class AnimationSheetBuilder {
'No frames are collected. Have you forgot to set `recording` to true?');
return _collateFrames(frames, frameSize, cellsPerRow);
}
/// Returns the smallest size that can contain all recorded frames.
///
/// This is used to adjust the viewport during unit tests, i.e. the size of
/// virtual screen. Having too many frames recorded than the default viewport
/// size can contain will lead to overflow errors, while having too few frames
/// means the golden file might be larger than necessary.
///
/// The [sheetSize] returns the smallest possible size by placing the
/// recorded frames, each of which has a size specified by [frameSize], in a
/// row-major grid with a maximum width specified by `maxWidth`, and returns
/// the size of that grid.
///
/// Setting the viewport size during a widget test usually involves
/// [TestWidgetsFlutterBinding.setSurfaceSize] and [WidgetTester.binding].
///
/// The `maxWidth` defaults to the width of the default viewport, 800.0.
///
/// This method can only be called if at least one frame has been recorded.
@Deprecated(
'The `sheetSize` is only useful for `display`, which should be migrated to `collate`. '
'This feature was deprecated after v2.3.0-13.0.pre.',
)
Size sheetSize({double maxWidth = _kDefaultTestViewportWidth}) {
assert(_recordedFrames.isNotEmpty);
final int cellsPerRow = (maxWidth / frameSize.width).floor();
final int rowNum = (_recordedFrames.length / cellsPerRow).ceil();
final double width = math.min(cellsPerRow, _recordedFrames.length) * frameSize.width;
return Size(width, frameSize.height * rowNum);
}
// The width of _kDefaultTestViewportSize in [TestViewConfiguration].
static const double _kDefaultTestViewportWidth = 800.0;
}
typedef _RecordedHandler = void Function(Future<ui.Image> image);
......@@ -446,45 +305,6 @@ Future<ui.Image> _collateFrames(List<ui.Image> frames, Size frameSize, int cells
return image;
}
// Layout children in a grid of fixed-sized cells.
//
// The sheet fills up as much space as the parent allows. The cells are
// positioned from top left to bottom right in a row-major order.
class _CellSheet extends StatelessWidget {
_CellSheet({
super.key,
required this.cellSize,
required this.children,
}) : assert(children.isNotEmpty);
final Size cellSize;
final List<Widget> children;
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
final double rowWidth = constraints.biggest.width;
final int cellsPerRow = (rowWidth / cellSize.width).floor();
final List<Widget> rows = <Widget>[];
for (int rowStart = 0; rowStart < children.length; rowStart += cellsPerRow) {
final Iterable<Widget> rowTargets = children.sublist(rowStart, math.min(rowStart + cellsPerRow, children.length));
rows.add(Row(
textDirection: TextDirection.ltr,
children: rowTargets.map((Widget target) => SizedBox.fromSize(
size: cellSize,
child: target,
)).toList(),
));
}
return Column(
textDirection: TextDirection.ltr,
crossAxisAlignment: CrossAxisAlignment.start,
children: rows,
);
});
}
}
class _RenderRootableRepaintBoundary extends RenderRepaintBoundary {
// Like [toImage], but captures an image of all layers (composited by
// RenderView and its children) clipped by the region of this object.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment