native icon indicating copy to clipboard operation
native copied to clipboard

[native_assets_cli] Helper to add all files in a directory as `DataAsset`s

Open dcharkes opened this issue 1 year ago • 2 comments
trafficstars

Adding all files in a directory as data assets seems to be a common use case.

In Flutter, all files in a directory can be added as assets easily:

https://docs.flutter.dev/ui/assets/assets-and-images#specifying-assets

flutter:
  assets:
    - directory/
    - directory/subdirectory/

Using these assets in Flutter is via the full file path:

https://docs.flutter.dev/ui/assets/assets-and-images#loading-text-assets

await rootBundle.loadString('assets/config.json')

We should be able to support this type of use case:

void main(List<String> args) async {
  await build(args, (config, output) async {
    await output.addDataAssetsDirectory('directory/', config);
    await output.addDataAssetsDirectory('directory/subdirectory/', config);
  });
}

Implementation sketch:

extension on BuildOutput {
  /// Adds all the files in [directory] as [DataAsset]s to this [BuildOutput].
  ///
  /// The [directory] must end with a slash and be relative to
  /// [BuildConfig.packageRoot].
  Future<void> addDataAssetsDirectory(
    String directory, {
    required BuildConfig config,
    String? linkInPackage,
  }) async {
    final packageName = config.packageName;
    final packageRoot = config.packageRoot;
    final assetDirectory = Directory.fromUri(packageRoot.resolve('assets/'));
    addDependency(assetDirectory.uri);

    await for (final assetFile in assetDirectory.list()) {
      if (assetFile is! File) {
        continue;
      }
      final assetUri = assetFile.uri;

      // The file path relative to the package root, with forward slashes.
      final name = assetUri
          .toFilePath(windows: false)
          .substring(packageRoot.toFilePath(windows: false).length);

      addAsset(
        DataAsset(
          package: packageName,
          name: name,
          file: assetUri,
        ),
        linkInPackage: linkInPackage,
      );
      addDependency(assetUri);
    }
  }
}

With such an implementation we'd also establish a convention that the a data asset in assets/foo.json will be available at runtime as package:my_package/assets/foo.json which aligns with the Flutter assets approach of making assets available via their full path.

Inspired by https://github.com/dart-lang/native/pull/1345#discussion_r1679054714.

Open to alternative suggestions, WDYT @mosuem?

dcharkes avatar Jul 16 '24 10:07 dcharkes

As discussed earlier:

In would be even nicer if adding all assets was enabled by default. This requires us to land automatic treeshaking of assets first, and needs special care because of existing asset folders.

mosuem avatar Jul 16 '24 13:07 mosuem

And we could add bool recursive param to the helper function.

  • https://github.com/dart-lang/native/pull/1345#discussion_r1679481691

dcharkes avatar Jul 17 '24 07:07 dcharkes