Skip to content
Open
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 5.15.0

**Feature**

- [#759](https://github.com/FlutterGen/flutter_gen/issues/759) Added `flutter_gen_interface` to allow generated asset classes to implement a shared custom interface for Modular Architectures & Design Systems.

## 5.14.1

**Development**
Expand Down
3 changes: 3 additions & 0 deletions melos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ packages:
- packages/command
- packages/core
- packages/runner
- packages/flutter_gen_interface
- examples/example
- examples/example_resources
- examples/example_workspace
Expand Down Expand Up @@ -132,6 +133,7 @@ scripts:
- flutter_gen
- flutter_gen_core
- flutter_gen_runner
- flutter_gen_interface

publish:dry:
run: dart pub publish --dry-run
Expand All @@ -143,3 +145,4 @@ scripts:
- flutter_gen
- flutter_gen_core
- flutter_gen_runner
- flutter_gen_interface
11 changes: 9 additions & 2 deletions packages/core/lib/generators/assets_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ Future<String> generateAssets(
'The value of "flutter/assets:" is incorrect.',
);
}

final integrations = <Integration>[
if (config.flutterGen.integrations.image)
ImageIntegration(
Expand Down Expand Up @@ -165,7 +164,15 @@ Future<String> generateAssets(

final importsBuffer = StringBuffer();
for (final e in imports.sorted((a, b) => a.import.compareTo(b.import))) {
importsBuffer.writeln(import(e));
if (e.import ==
'package:flutter_gen_interface/flutter_gen_interface.dart') {
importsBuffer.writeln(
'import \'package:flutter_gen_interface/flutter_gen_interface.dart\';');
importsBuffer.writeln(
'export \'package:flutter_gen_interface/flutter_gen_interface.dart\';');
} else {
importsBuffer.writeln(import(e));
}
}

final buffer = StringBuffer();
Expand Down
110 changes: 8 additions & 102 deletions packages/core/lib/generators/integrations/image_integration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,110 +25,13 @@ class ImageIntegration extends Integration {
isPackage ? "'packages/$packageName/\$_assetName'" : '_assetName';

@override
List<Import> get requiredImports => const [
Import('package:flutter/widgets.dart'),
List<Import> get requiredImports => [
const Import(
'package:flutter_gen_interface/flutter_gen_interface.dart'),
];

@override
String get classOutput => _classDefinition;

String get _classDefinition => '''class AssetGenImage {
const AssetGenImage(
this._assetName, {
this.size,
this.flavors = const {},
this.animation,
});

final String _assetName;

${isPackage ? "\n static const String package = '$packageName';" : ''}

final Size? size;
final Set<String> flavors;
final AssetGenImageAnimation? animation;

Image image({
Key? key,
AssetBundle? bundle,
ImageFrameBuilder? frameBuilder,
ImageErrorWidgetBuilder? errorBuilder,
String? semanticLabel,
bool excludeFromSemantics = false,
double? scale,
double? width,
double? height,
Color? color,
Animation<double>? opacity,
BlendMode? colorBlendMode,
BoxFit? fit,
AlignmentGeometry alignment = Alignment.center,
ImageRepeat repeat = ImageRepeat.noRepeat,
Rect? centerSlice,
bool matchTextDirection = false,
bool gaplessPlayback = true,
bool isAntiAlias = false,
${isPackage ? '$deprecationMessagePackage\n' : ''}String? package$packageParameter,
FilterQuality filterQuality = FilterQuality.medium,
int? cacheWidth,
int? cacheHeight,
}) {
return Image.asset(
_assetName,
key: key,
bundle: bundle,
frameBuilder: frameBuilder,
errorBuilder: errorBuilder,
semanticLabel: semanticLabel,
excludeFromSemantics: excludeFromSemantics,
scale: scale,
width: width,
height: height,
color: color,
opacity: opacity,
colorBlendMode: colorBlendMode,
fit: fit,
alignment: alignment,
repeat: repeat,
centerSlice: centerSlice,
matchTextDirection: matchTextDirection,
gaplessPlayback: gaplessPlayback,
isAntiAlias: isAntiAlias,
package: package,
filterQuality: filterQuality,
cacheWidth: cacheWidth,
cacheHeight: cacheHeight,
);
}

ImageProvider provider({
AssetBundle? bundle,
${isPackage ? '$deprecationMessagePackage\n' : ''}String? package$packageParameter,
}) {
return AssetImage(
_assetName,
bundle: bundle,
package: package,
);
}

String get path => _assetName;

String get keyName => $keyName;
}

class AssetGenImageAnimation {
const AssetGenImageAnimation({
required this.isAnimation,
required this.duration,
required this.frames,
});

final bool isAnimation;
final Duration duration;
final int frames;
}
''';
String get classOutput => '';

@override
String get className => 'AssetGenImage';
Expand Down Expand Up @@ -157,7 +60,10 @@ class AssetGenImageAnimation {
final flavors = asset.flavors.map((e) => '\'$e\'').join(', ');
buffer.write(flavors);
buffer.write('}');
buffer.write(','); // Better formatting.
if (!isPackage) buffer.write(','); // Better formatting.
}
if (isPackage) {
buffer.write(', package: \'$packageName\',');
}
buffer.write(')');
return buffer.toString();
Expand Down
95 changes: 8 additions & 87 deletions packages/core/lib/generators/integrations/svg_integration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,95 +13,13 @@ class SvgIntegration extends Integration {
String get packageExpression => isPackage ? ' = package' : '';

@override
List<Import> get requiredImports => const [
Import('package:flutter/widgets.dart'),
Import('package:flutter/services.dart'),
Import('package:flutter_svg/flutter_svg.dart', alias: '_svg'),
Import('package:vector_graphics/vector_graphics.dart', alias: '_vg'),
List<Import> get requiredImports => [
const Import(
'package:flutter_gen_interface/flutter_gen_interface.dart'),
];

@override
String get classOutput => _classDefinition;

String get _classDefinition => '''class SvgGenImage {
const SvgGenImage(
this._assetName, {
this.size,
this.flavors = const {},
}) : _isVecFormat = false;

const SvgGenImage.vec(
this._assetName, {
this.size,
this.flavors = const {},
}) : _isVecFormat = true;

final String _assetName;
final Size? size;
final Set<String> flavors;
final bool _isVecFormat;

${isPackage ? "\n static const String package = '$packageName';" : ''}

_svg.SvgPicture svg({
Key? key,
bool matchTextDirection = false,
AssetBundle? bundle,
${isPackage ? '$deprecationMessagePackage\n' : ''}String? package$packageExpression,
double? width,
double? height,
BoxFit fit = BoxFit.contain,
AlignmentGeometry alignment = Alignment.center,
bool allowDrawingOutsideViewBox = false,
WidgetBuilder? placeholderBuilder,
String? semanticsLabel,
bool excludeFromSemantics = false,
_svg.SvgTheme? theme,
_svg.ColorMapper? colorMapper,
ColorFilter? colorFilter,
Clip clipBehavior = Clip.hardEdge,
@deprecated Color? color,
@deprecated BlendMode colorBlendMode = BlendMode.srcIn,
@deprecated bool cacheColorFilter = false,
}) {
final _svg.BytesLoader loader;
if (_isVecFormat) {
loader = _vg.AssetBytesLoader(
_assetName,
assetBundle: bundle,
packageName: package,
);
} else {
loader = _svg.SvgAssetLoader(
_assetName,
assetBundle: bundle,
packageName: package,
theme: theme,
colorMapper: colorMapper,
);
}
return _svg.SvgPicture(
loader,
key: key,
matchTextDirection: matchTextDirection,
width: width,
height: height,
fit: fit,
alignment: alignment,
allowDrawingOutsideViewBox: allowDrawingOutsideViewBox,
placeholderBuilder: placeholderBuilder,
semanticsLabel: semanticsLabel,
excludeFromSemantics: excludeFromSemantics,
colorFilter: colorFilter ?? (color == null ? null : ColorFilter.mode(color, colorBlendMode)),
clipBehavior: clipBehavior,
cacheColorFilter: cacheColorFilter,
);
}

String get path => _assetName;

String get keyName => ${isPackage ? '\'packages/$packageName/\$_assetName\'' : '_assetName'};
}''';
String get classOutput => '';

@override
String get className => 'SvgGenImage';
Expand All @@ -127,7 +45,10 @@ ${isPackage ? "\n static const String package = '$packageName';" : ''}
final flavors = asset.flavors.map((e) => '\'$e\'').join(', ');
buffer.write(flavors);
buffer.write('}');
buffer.write(','); // Better formatting.
if (!isPackage) buffer.write(','); // Better formatting.
}
if (isPackage) {
buffer.write(', package: \'$packageName\',');
}
buffer.write(')');
return buffer.toString();
Expand Down
15 changes: 0 additions & 15 deletions packages/core/test/assets_gen_integrations_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -174,21 +174,6 @@ void main() {
isFalse,
);
expect(integration.isConstConstructor, isTrue);
expect(integration.classOutput.contains('String? package,'), isTrue);

final integrationWithPackage = SvgIntegration('package_name');
expect(
integrationWithPackage.classOutput.contains(
'String? package = package,',
),
isTrue,
);
expect(
integrationWithPackage.classOutput.contains(
"static const String package = 'package_name';",
),
isTrue,
);
});

test('Assets with Rive integrations on pubspec.yaml', () async {
Expand Down
7 changes: 0 additions & 7 deletions packages/core/test/assets_gen_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,6 @@ void main() {

// The generated classes have `package` fields.
expect(content, contains("static const String package = 'test';"));
expect(
content,
contains(
"@Deprecated('Do not specify package for a generated library asset')",
),
);
expect(content, contains('String? package = package,'));
});

test('Assets with directory path enabled', () async {
Expand Down
Loading