use link hooks and const loading
diff --git a/packages/vector_graphics/lib/src/loader.dart b/packages/vector_graphics/lib/src/loader.dart
index 8b49e3a..c4640a0 100644
--- a/packages/vector_graphics/lib/src/loader.dart
+++ b/packages/vector_graphics/lib/src/loader.dart
@@ -2,9 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// ignore_for_file: experimental_member_use
+
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:http/http.dart' as http;
+import 'package:meta/meta.dart' show RecordUse, mustBeConst;
/// An interface that can be implemented to support decoding vector graphic
/// binary assets from different byte sources.
@@ -36,6 +39,27 @@
Object cacheKey(BuildContext? context) => this;
}
+/// The magic prefix to prevent accidental non-const loading.
+///
+/// Must be the same as when storing the asset in build.dart.
+///
+/// TODO: move to a common location.
+const magicPrefix = 'svg1234:';
+
+/// Loads vector graphics data from an asset bundle.
+@RecordUse()
+class ConstAssetBytesLoader extends AssetBytesLoader {
+ ///
+ const ConstAssetBytesLoader(
+ @mustBeConst super.assetName, {
+ super.packageName,
+ super.assetBundle,
+ });
+
+ @override
+ String get assetName => magicPrefix + super.assetName;
+}
+
/// Loads vector graphics data from an asset bundle.
///
/// This loader does not cache bytes by default. The Flutter framework
@@ -73,9 +97,11 @@
@override
Future<ByteData> loadBytes(BuildContext? context) {
- return _resolveBundle(context).load(
- packageName == null ? assetName : 'packages/$packageName/$assetName',
- );
+ final String key = packageName == null
+ ? assetName
+ : 'packages/$packageName/$assetName';
+ print('load $key');
+ return _resolveBundle(context).load(key);
}
@override
diff --git a/packages/vector_graphics/lib/vector_graphics.dart b/packages/vector_graphics/lib/vector_graphics.dart
index 6eecdc6..3b8d72a 100644
--- a/packages/vector_graphics/lib/vector_graphics.dart
+++ b/packages/vector_graphics/lib/vector_graphics.dart
@@ -6,6 +6,7 @@
show
AssetBytesLoader,
BytesLoader,
+ ConstAssetBytesLoader,
NetworkBytesLoader,
PictureInfo,
VectorGraphic,
diff --git a/packages/vector_graphics/pubspec.yaml b/packages/vector_graphics/pubspec.yaml
index f759063..dcc860e 100644
--- a/packages/vector_graphics/pubspec.yaml
+++ b/packages/vector_graphics/pubspec.yaml
@@ -12,6 +12,7 @@
flutter:
sdk: flutter
http: ^1.0.0
+ meta: ^1.17.0
vector_graphics_codec: ^1.1.11+1
dev_dependencies:
diff --git a/packages/vector_graphics_compiler/example/hook/build.dart b/packages/vector_graphics_compiler/example/hook/build.dart
index 868c886..36d62a9 100644
--- a/packages/vector_graphics_compiler/example/hook/build.dart
+++ b/packages/vector_graphics_compiler/example/hook/build.dart
@@ -7,12 +7,11 @@
void main(List<String> args) {
build(args, (BuildInput input, BuildOutputBuilder output) async {
- await compileSvg(
+ await addSvg(
input,
output,
- name: 'example_file',
- file: input.packageRoot.resolve('assets/example.svg'),
- options: const Options(dumpDebug: true, concurrency: 2),
+ file: 'assets/example.svg',
+ treeshakeable: true,
);
});
}
diff --git a/packages/vector_graphics_compiler/example/lib/main.dart b/packages/vector_graphics_compiler/example/lib/main.dart
index d775769..2f4cdf8 100644
--- a/packages/vector_graphics_compiler/example/lib/main.dart
+++ b/packages/vector_graphics_compiler/example/lib/main.dart
@@ -22,7 +22,10 @@
home: const Scaffold(
body: Center(
child: VectorGraphic(
- loader: AssetBytesLoader('example_file', packageName: 'example'),
+ loader: ConstAssetBytesLoader(
+ 'assets/example.svg',
+ packageName: 'example',
+ ),
),
),
),
diff --git a/packages/vector_graphics_compiler/hook/link.dart b/packages/vector_graphics_compiler/hook/link.dart
new file mode 100644
index 0000000..389d2ac
--- /dev/null
+++ b/packages/vector_graphics_compiler/hook/link.dart
@@ -0,0 +1,15 @@
+import 'package:data_assets/data_assets.dart';
+import 'package:hooks/hooks.dart';
+import 'package:vector_graphics_compiler/build.dart';
+
+Future<void> main(List<String> arguments) async {
+ await link(arguments, (input, output) async {
+ await compileSvgs(
+ input,
+ output,
+ nameToFile: Map.fromEntries(
+ input.assets.data.map((e) => MapEntry(e.name, e.file)),
+ ),
+ );
+ });
+}
diff --git a/packages/vector_graphics_compiler/lib/build.dart b/packages/vector_graphics_compiler/lib/build.dart
index bd154ff..02f415a 100644
--- a/packages/vector_graphics_compiler/lib/build.dart
+++ b/packages/vector_graphics_compiler/lib/build.dart
@@ -11,27 +11,85 @@
import 'src/util/isolate_processor.dart';
import 'vector_graphics_compiler.dart';
-/// Helper to build svg
-Future<void> compileSvg(
+/// The magic prefix to prevent accidental non-const loading.
+const magicPrefix = 'svg1234:';
+
+/// Helper to add svg
+Future<void> addSvg(
BuildInput input,
BuildOutputBuilder output, {
- required String name,
- required Uri file,
+ required String file,
Options options = const Options(),
-}) async => compileSvgs(
- input,
- output,
- nameToFile: <String, Uri>{name: file},
- options: options,
-);
+
+ /// Whether this asset should be treeshaken if it's not used. Means that it
+ /// can only be loaded by the [ConstAssetBytesLoader] which knows about the
+ /// magic prefix to prevent accidental treeshaking.
+ required bool treeshakeable,
+}) async {
+ final String prefix = treeshakeable ? magicPrefix : '';
+ // If we are linking, then do the compilation there, as we can compile all SVGs at once
+ if (input.config.linkingEnabled) {
+ output.assets.data.add(
+ DataAsset(
+ package: input.packageName,
+ name: prefix + file,
+ file: input.packageRoot.resolve(file),
+ ),
+ routing: const ToLinkHook('vector_graphics_compiler'),
+ );
+ } else {
+ // If we are not linking, then do the compilation here
+ final Map<String, IOPair> pairs = await _compileSvgs(options, {
+ prefix + file: input.packageRoot.resolve(file),
+ }, input.outputDirectory);
+ for (final MapEntry<String, IOPair>(
+ key: String name,
+ value: IOPair(output: String outputPath),
+ )
+ in pairs.entries) {
+ output.assets.data.add(
+ DataAsset(
+ package: input.packageName,
+ name: name,
+ file: Uri.file(outputPath),
+ ),
+ );
+ }
+ }
+}
/// Helper to build svgs
Future<void> compileSvgs(
- BuildInput input,
- BuildOutputBuilder output, {
+ LinkInput input,
+ LinkOutputBuilder output, {
required Map<String, Uri> nameToFile,
Options options = const Options(),
}) async {
+ final Map<String, IOPair> pairs = await _compileSvgs(
+ options,
+ nameToFile,
+ input.outputDirectory,
+ );
+ for (final MapEntry<String, IOPair>(
+ key: String name,
+ value: IOPair(output: String outputPath),
+ )
+ in pairs.entries) {
+ output.assets.data.add(
+ DataAsset(
+ package: input.packageName,
+ name: name,
+ file: Uri.file(outputPath),
+ ),
+ );
+ }
+}
+
+Future<Map<String, IOPair>> _compileSvgs(
+ Options options,
+ Map<String, Uri> nameToFile,
+ Uri outputDirectory,
+) async {
final processor = IsolateProcessor(
options.libpathops,
options.libtessellator,
@@ -43,7 +101,7 @@
name,
IOPair(
file.path,
- '${p.join(input.outputDirectory.path, p.basenameWithoutExtension(file.path))}.vec',
+ '${p.join(outputDirectory.path, p.basenameWithoutExtension(file.path))}.vec',
),
),
);
@@ -61,19 +119,7 @@
'Did not succeed for ${pairs.map((String name, IOPair e) => MapEntry<String, String>(name, '$name: ${e.input} -> ${e.output}')).values}',
);
}
- for (final MapEntry<String, IOPair>(
- key: String name,
- value: IOPair(output: String outputPath),
- )
- in pairs.entries) {
- output.assets.data.add(
- DataAsset(
- package: input.packageName,
- name: name,
- file: Uri.file(outputPath),
- ),
- );
- }
+ return pairs;
}
/// Options for the processor.
diff --git a/packages/vector_graphics_compiler/pubspec.yaml b/packages/vector_graphics_compiler/pubspec.yaml
index 1400650..98bc35e 100644
--- a/packages/vector_graphics_compiler/pubspec.yaml
+++ b/packages/vector_graphics_compiler/pubspec.yaml
@@ -39,6 +39,10 @@
vector_graphics: ^1.1.13
vector_math: ^2.1.2
+dependency_overrides:
+ vector_graphics:
+ path: ../vector_graphics
+
flutter:
config:
enable-dart-data-assets: true