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
4 changes: 4 additions & 0 deletions third_party/packages/flutter_svg/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.0.17

* Implement errorBuilder callback

## 2.0.16

* Adopts code excerpts for README.
Expand Down
18 changes: 18 additions & 0 deletions third_party/packages/flutter_svg/lib/svg.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ export 'src/cache.dart';
export 'src/default_theme.dart';
export 'src/loaders.dart';

/// Builder function to create an error widget. This builder is called when
/// the image failed loading.
typedef SvgErrorWidgetBuilder = Widget Function(
BuildContext context,
Object error,
StackTrace stackTrace,
);

/// Instance for [Svg]'s utility methods, which can produce a [DrawableRoot]
/// or [PictureInfo] from [String] or [Uint8List].
final Svg svg = Svg._();
Expand Down Expand Up @@ -86,6 +94,7 @@ class SvgPicture extends StatelessWidget {
this.semanticsLabel,
this.excludeFromSemantics = false,
this.clipBehavior = Clip.hardEdge,
this.errorBuilder,
@Deprecated(
'No code should use this parameter. It never was implemented properly. '
'The SVG theme must be set on the bytesLoader.')
Expand Down Expand Up @@ -184,6 +193,7 @@ class SvgPicture extends StatelessWidget {
this.semanticsLabel,
this.excludeFromSemantics = false,
this.clipBehavior = Clip.hardEdge,
this.errorBuilder,
SvgTheme? theme,
ui.ColorFilter? colorFilter,
@Deprecated('Use colorFilter instead.') ui.Color? color,
Expand Down Expand Up @@ -248,6 +258,7 @@ class SvgPicture extends StatelessWidget {
this.semanticsLabel,
this.excludeFromSemantics = false,
this.clipBehavior = Clip.hardEdge,
this.errorBuilder,
@Deprecated('This no longer does anything.') bool cacheColorFilter = false,
SvgTheme? theme,
http.Client? httpClient,
Expand Down Expand Up @@ -306,6 +317,7 @@ class SvgPicture extends StatelessWidget {
this.semanticsLabel,
this.excludeFromSemantics = false,
this.clipBehavior = Clip.hardEdge,
this.errorBuilder,
SvgTheme? theme,
@Deprecated('This no longer does anything.') bool cacheColorFilter = false,
}) : bytesLoader = SvgFileLoader(file, theme: theme),
Expand Down Expand Up @@ -355,6 +367,7 @@ class SvgPicture extends StatelessWidget {
this.semanticsLabel,
this.excludeFromSemantics = false,
this.clipBehavior = Clip.hardEdge,
this.errorBuilder,
SvgTheme? theme,
@Deprecated('This no longer does anything.') bool cacheColorFilter = false,
}) : bytesLoader = SvgBytesLoader(bytes, theme: theme),
Expand Down Expand Up @@ -404,6 +417,7 @@ class SvgPicture extends StatelessWidget {
this.semanticsLabel,
this.excludeFromSemantics = false,
this.clipBehavior = Clip.hardEdge,
this.errorBuilder,
SvgTheme? theme,
@Deprecated('This no longer does anything.') bool cacheColorFilter = false,
}) : bytesLoader = SvgStringLoader(string, theme: theme),
Expand Down Expand Up @@ -487,6 +501,9 @@ class SvgPicture extends StatelessWidget {
/// Defaults to [Clip.hardEdge], and must not be null.
final Clip clipBehavior;

/// Widget displayed while the target image failed loading.
final SvgErrorWidgetBuilder? errorBuilder;

/// The color filter, if any, to apply to this widget.
final ColorFilter? colorFilter;

Expand All @@ -501,6 +518,7 @@ class SvgPicture extends StatelessWidget {
semanticsLabel: semanticsLabel,
excludeFromSemantics: excludeFromSemantics,
clipBehavior: clipBehavior,
errorBuilder: errorBuilder,
colorFilter: colorFilter,
placeholderBuilder: placeholderBuilder,
clipViewbox: !allowDrawingOutsideViewBox,
Expand Down
2 changes: 1 addition & 1 deletion third_party/packages/flutter_svg/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: flutter_svg
description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files.
repository: https://github.com/flutter/packages/tree/main/third_party/packages/flutter_svg
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+flutter_svg%22
version: 2.0.16
version: 2.0.17

environment:
sdk: ^3.4.0
Expand Down
102 changes: 102 additions & 0 deletions third_party/packages/flutter_svg/test/widget_svg_test.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:convert';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
Expand Down Expand Up @@ -767,6 +768,107 @@ void main() {
widgetFinder, matchesGoldenFile('golden_widget/image_$key.png'));
}
});

group('SvgPicture - errorBuilder', () {
testWidgets('SvgPicture.string handles failure',
(WidgetTester tester) async {
await tester.pumpWidget(
MediaQuery(
data: mediaQueryData,
child: SvgPicture.string(
'<!-- invalid svg -->',
errorBuilder: (
BuildContext context,
Object error,
StackTrace stackTrace,
) {
return const Directionality(
textDirection: TextDirection.ltr,
child: Text('image failed'),
);
},
),
),
);
await tester.pumpAndSettle();

expect(find.text('image failed'), findsOneWidget);
});

testWidgets('SvgPicture.memory handles failure',
(WidgetTester tester) async {
await tester.pumpWidget(
MediaQuery(
data: mediaQueryData,
child: SvgPicture.memory(
Uint8List.fromList(utf8.encode('<!-- invalid svg -->')),
errorBuilder: (
BuildContext context,
Object error,
StackTrace stackTrace,
) {
return const Directionality(
textDirection: TextDirection.ltr,
child: Text('image failed'),
);
},
),
),
);
await tester.pumpAndSettle();

expect(find.text('image failed'), findsOneWidget);
});

testWidgets('SvgPicture.asset handles failure',
(WidgetTester tester) async {
await tester.pumpWidget(
MediaQuery(
data: mediaQueryData,
child: SvgPicture.asset(
'/wrong path',
errorBuilder: (
BuildContext context,
Object error,
StackTrace stackTrace,
) {
return const Directionality(
textDirection: TextDirection.ltr,
child: Text('image failed'),
);
},
),
),
);
await tester.pumpAndSettle();

expect(find.text('image failed'), findsOneWidget);
});

testWidgets('SvgPicture.file handles failure', (WidgetTester tester) async {
await tester.pumpWidget(
MediaQuery(
data: mediaQueryData,
child: SvgPicture.file(
File('nosuchfile'),
errorBuilder: (
BuildContext context,
Object error,
StackTrace stackTrace,
) {
return const Directionality(
textDirection: TextDirection.ltr,
child: Text('image failed'),
);
},
),
),
);
await tester.pumpAndSettle();

expect(find.text('image failed'), findsOneWidget);
});
});
}

class FakeAssetBundle extends Fake implements AssetBundle {
Expand Down
Loading