From 397ca8170f445976c210dd67dcf673baa242f907 Mon Sep 17 00:00:00 2001 From: Hao-Cher Hong Date: Wed, 18 Jan 2023 14:49:19 +0800 Subject: [PATCH 1/4] support ios background color when removing alpha --- lib/flutter_launcher_icons_config.dart | 5 +++++ lib/flutter_launcher_icons_config.g.dart | 4 ++++ lib/ios.dart | 10 ++++++++++ test/abs/icon_generator_test.mocks.dart | 5 +++++ test/macos/macos_icon_generator_test.mocks.dart | 6 ++++++ test/windows/windows_icon_generator_test.mocks.dart | 5 +++++ 6 files changed, 35 insertions(+) diff --git a/lib/flutter_launcher_icons_config.dart b/lib/flutter_launcher_icons_config.dart index 0f9dcf3553..d12c2afd87 100644 --- a/lib/flutter_launcher_icons_config.dart +++ b/lib/flutter_launcher_icons_config.dart @@ -50,6 +50,10 @@ class FlutterLauncherIconsConfig { @JsonKey(name: 'remove_alpha_ios') final bool removeAlphaIOS; + /// IOS background_color_ios + @JsonKey(name: 'background_color_ios') + final String backgroundColorIOS; + /// Web platform config @JsonKey(name: 'web') final WebConfig? webConfig; @@ -73,6 +77,7 @@ class FlutterLauncherIconsConfig { this.adaptiveIconBackground, this.minSdkAndroid = constants.androidDefaultAndroidMinSDK, this.removeAlphaIOS = false, + this.backgroundColorIOS = '#ffffff', this.webConfig, this.windowsConfig, this.macOSConfig, diff --git a/lib/flutter_launcher_icons_config.g.dart b/lib/flutter_launcher_icons_config.g.dart index 5636badb01..cc290c760c 100644 --- a/lib/flutter_launcher_icons_config.g.dart +++ b/lib/flutter_launcher_icons_config.g.dart @@ -26,6 +26,8 @@ FlutterLauncherIconsConfig _$FlutterLauncherIconsConfigFromJson(Map json) => (v) => v as int? ?? constants.androidDefaultAndroidMinSDK), removeAlphaIOS: $checkedConvert('remove_alpha_ios', (v) => v as bool? ?? false), + backgroundColorIOS: $checkedConvert( + 'background_color_ios', (v) => v as String? ?? '#ffffff'), webConfig: $checkedConvert( 'web', (v) => v == null ? null : WebConfig.fromJson(v as Map)), windowsConfig: $checkedConvert('windows', @@ -43,6 +45,7 @@ FlutterLauncherIconsConfig _$FlutterLauncherIconsConfigFromJson(Map json) => 'adaptiveIconBackground': 'adaptive_icon_background', 'minSdkAndroid': 'min_sdk_android', 'removeAlphaIOS': 'remove_alpha_ios', + 'backgroundColorIOS': 'background_color_ios', 'webConfig': 'web', 'windowsConfig': 'windows', 'macOSConfig': 'macos' @@ -61,6 +64,7 @@ Map _$FlutterLauncherIconsConfigToJson( 'adaptive_icon_background': instance.adaptiveIconBackground, 'min_sdk_android': instance.minSdkAndroid, 'remove_alpha_ios': instance.removeAlphaIOS, + 'background_color_ios': instance.backgroundColorIOS, 'web': instance.webConfig, 'windows': instance.windowsConfig, 'macos': instance.macOSConfig, diff --git a/lib/ios.dart b/lib/ios.dart index 439a82d82b..939f687f36 100644 --- a/lib/ios.dart +++ b/lib/ios.dart @@ -52,7 +52,17 @@ void createIcons(FlutterLauncherIconsConfig config, String? flavor) { return; } if (config.removeAlphaIOS) { + final backgroundColorHex = config.backgroundColorIOS.startsWith('#') ? config.backgroundColorIOS.substring(1) : config.backgroundColorIOS; + if (backgroundColorHex.length != 6) { + throw Exception('background_color_ios hex should be 6 characters long'); + } + final backgroundByte = int.parse(backgroundColorHex, radix: 16); + final data = image.data; + for (var i = 0; i < data.length; i++) { + data[i] = alphaBlendColors(backgroundByte, data[i]); + } image.channels = Channels.rgb; + } if (image.channels == Channels.rgba) { print( diff --git a/test/abs/icon_generator_test.mocks.dart b/test/abs/icon_generator_test.mocks.dart index 8b26393b81..63a79ae815 100644 --- a/test/abs/icon_generator_test.mocks.dart +++ b/test/abs/icon_generator_test.mocks.dart @@ -50,6 +50,11 @@ class MockFlutterLauncherIconsConfig extends _i1.Mock returnValue: false, ) as bool); @override + String get backgroundColorIOS => (super.noSuchMethod( + Invocation.getter(#backgroundColorIOS), + returnValue: '', + ) as String); + @override bool get hasAndroidAdaptiveConfig => (super.noSuchMethod( Invocation.getter(#hasAndroidAdaptiveConfig), returnValue: false, diff --git a/test/macos/macos_icon_generator_test.mocks.dart b/test/macos/macos_icon_generator_test.mocks.dart index 1039287ade..aecb3b4c85 100644 --- a/test/macos/macos_icon_generator_test.mocks.dart +++ b/test/macos/macos_icon_generator_test.mocks.dart @@ -58,6 +58,12 @@ class MockFlutterLauncherIconsConfig extends _i1.Mock returnValueForMissingStub: false, ) as bool); @override + String get backgroundColorIOS => (super.noSuchMethod( + Invocation.getter(#backgroundColorIOS), + returnValue: '', + returnValueForMissingStub: '', + ) as String); + @override bool get hasAndroidAdaptiveConfig => (super.noSuchMethod( Invocation.getter(#hasAndroidAdaptiveConfig), returnValue: false, diff --git a/test/windows/windows_icon_generator_test.mocks.dart b/test/windows/windows_icon_generator_test.mocks.dart index 4ca4948570..590c18d8dd 100644 --- a/test/windows/windows_icon_generator_test.mocks.dart +++ b/test/windows/windows_icon_generator_test.mocks.dart @@ -60,6 +60,11 @@ class MockFlutterLauncherIconsConfig extends _i1.Mock returnValue: false, ) as bool); @override + String get backgroundColorIOS => (super.noSuchMethod( + Invocation.getter(#backgroundColorIOS), + returnValue: '', + ) as String); + @override bool get hasAndroidAdaptiveConfig => (super.noSuchMethod( Invocation.getter(#hasAndroidAdaptiveConfig), returnValue: false, From 281edaa23612cae0521958248a09bb6d6dde7d71 Mon Sep 17 00:00:00 2001 From: Hao-Cher Hong Date: Fri, 5 May 2023 18:37:57 +0800 Subject: [PATCH 2/4] Merge main --- .../cd-pub-deploy-published-release.yml | 2 +- CHANGELOG.md | 18 +- README.md | 48 ++- analysis_options.yaml | 1 + bin/generate.dart | 113 +++++++ example/default_example/.metadata | 41 ++- example/default_example/pubspec.yaml | 4 +- .../flutter_launcher_icons-development.yaml | 2 +- .../flutter_launcher_icons-integration.yaml | 2 +- .../flutter_launcher_icons-production.yaml | 2 +- lib/abs/icon_generator.dart | 11 +- lib/android.dart | 70 ++--- lib/config/config.dart | 204 ++++++++++++ lib/config/config.g.dart | 64 ++++ lib/config/macos_config.dart | 33 ++ lib/config/macos_config.g.dart | 26 ++ lib/config/web_config.dart | 42 +++ lib/config/web_config.g.dart | 34 ++ lib/config/windows_config.dart | 37 +++ lib/config/windows_config.g.dart | 28 ++ lib/constants.dart | 4 +- lib/custom_exceptions.dart | 24 +- lib/flutter_launcher_icons_config.dart | 293 ------------------ lib/flutter_launcher_icons_config.g.dart | 138 --------- lib/ios.dart | 71 ++++- lib/macos/macos_icon_generator.dart | 6 +- lib/main.dart | 40 ++- lib/src/version.dart | 2 +- lib/utils.dart | 2 + lib/web/web_icon_generator.dart | 10 +- lib/xml_templates.dart | 2 + pubspec.yaml | 25 +- test/abs/icon_generator_test.dart | 8 +- test/abs/icon_generator_test.mocks.dart | 25 +- test/all_tests.dart | 2 +- test/android_test.dart | 11 +- test/config/test_pubspec.yaml | 2 +- ...cons_config_test.dart => config_test.dart} | 20 +- test/macos/macos_icon_generator_test.dart | 14 +- .../macos_icon_generator_test.mocks.dart | 33 +- test/main_test.dart | 38 +-- test/templates.dart | 12 +- test/web/web_icon_generator_test.dart | 6 +- test/windows/windows_icon_generator_test.dart | 13 +- .../windows_icon_generator_test.mocks.dart | 32 +- 45 files changed, 967 insertions(+), 648 deletions(-) create mode 100644 bin/generate.dart create mode 100644 lib/config/config.dart create mode 100644 lib/config/config.g.dart create mode 100644 lib/config/macos_config.dart create mode 100644 lib/config/macos_config.g.dart create mode 100644 lib/config/web_config.dart create mode 100644 lib/config/web_config.g.dart create mode 100644 lib/config/windows_config.dart create mode 100644 lib/config/windows_config.g.dart delete mode 100644 lib/flutter_launcher_icons_config.dart delete mode 100644 lib/flutter_launcher_icons_config.g.dart rename test/{flutter_launcher_icons_config_test.dart => config_test.dart} (93%) diff --git a/.github/workflows/cd-pub-deploy-published-release.yml b/.github/workflows/cd-pub-deploy-published-release.yml index dbf6d4c17f..1dd595b8b6 100644 --- a/.github/workflows/cd-pub-deploy-published-release.yml +++ b/.github/workflows/cd-pub-deploy-published-release.yml @@ -16,7 +16,7 @@ jobs: - name: Checkout repo uses: actions/checkout@v2 - name: Run a one-line script - uses: k-paxian/dart-package-publisher@v1.2 + uses: k-paxian/dart-package-publisher@v1.5.1 with: accessToken: ${{ secrets.PUB_ACCESS_TOKEN }} refreshToken: ${{ secrets.PUB_REFRESH_TOKEN}} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 528f3f8248..2ac4713380 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,23 @@ # Changelog -## 0.11.0 (27th September 2022) +## 0.13.1 (15th April 2023) + +- Can now use `flutter_launcher_icons` instead of `flutter_icons` [#478](https://github.com/fluttercommunity/flutter_launcher_icons/pull/478) +- Can use command `flutter pub run flutter_launcher_icons:generate` to automatically generate config file [#475](https://github.com/fluttercommunity/flutter_launcher_icons/pull/475) + + +## 0.13.0 (7th April 2023) +- Fix remove alpha for iOS [#464](https://github.com/fluttercommunity/flutter_launcher_icons/pull/464) +- Updating code style [#472](https://github.com/fluttercommunity/flutter_launcher_icons/pull/472) +- Updated out of bounds dependency [#473](https://github.com/fluttercommunity/flutter_launcher_icons/pull/473) + +## 0.12.0 (24th February 2023) + +- Updated image package and other packages [#447](https://github.com/fluttercommunity/flutter_launcher_icons/pull/447) + +## 0.11.0 (27th September 2022) + - Support for Macos Icons [#407](https://github.com/fluttercommunity/flutter_launcher_icons/pull/407) - Cli-improvement [#400](https://github.com/fluttercommunity/flutter_launcher_icons/pull/400) - Add `repository` and `issue_tracker` [#411](https://github.com/fluttercommunity/flutter_launcher_icons/pull/411) (thanks to [@patelpathik](https://github.com/patelpathik)) diff --git a/README.md b/README.md index 4e152139a7..c261528a71 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Flutter Community: flutter_launcher_icons](https://fluttercommunity.dev/_github/header/flutter_launcher_icons)](https://github.com/fluttercommunity/community) -[![Build Status](https://travis-ci.org/fluttercommunity/flutter_launcher_icons.svg?branch=master)](https://travis-ci.org/MarkOSullivan94/flutter_launcher_icons) [![pub package](https://img.shields.io/pub/v/flutter_launcher_icons.svg)](https://pub.dartlang.org/packages/flutter_launcher_icons) +[![pub package](https://img.shields.io/pub/v/flutter_launcher_icons.svg)](https://pub.dartlang.org/packages/flutter_launcher_icons) A command-line tool which simplifies the task of updating your Flutter app's launcher icon. Fully flexible, allowing you to choose what platform you wish to update the launcher icon for and if you want, the option to keep your old launcher icon in case you want to revert back sometime in the future. @@ -10,14 +10,36 @@ A command-line tool which simplifies the task of updating your Flutter app's lau ### 1. Setup the config file -Add your Flutter Launcher Icons configuration to your `pubspec.yaml` or create a new config file called `flutter_launcher_icons.yaml`. +Run the following command to create a new config automatically: + +```shell +flutter pub run flutter_launcher_icons:generate +``` + +This will create a new file called `flutter_launcher_icons.yaml` in your `flutter` project's root directory. + +If you want to override the default location or name of the config file, use the `-f` flag: + +```shell +flutter pub run flutter_launcher_icons:generate -f +``` + +To override an existing config file, use the `-o` flag: + +```shell +flutter pub run flutter_launcher_icons:generate -o +``` + +OR + +Add your Flutter Launcher Icons configuration to your `pubspec.yaml`. An example is shown below. More complex examples [can be found in the example projects](https://github.com/fluttercommunity/flutter_launcher_icons/tree/master/example). ```yaml dev_dependencies: - flutter_launcher_icons: "^0.11.0" + flutter_launcher_icons: "^0.13.1" -flutter_icons: +flutter_launcher_icons: android: "launcher_icon" ios: true image_path: "assets/icon/icon.png" @@ -36,25 +58,25 @@ flutter_icons: image_path: "path/to/image.png" ``` -If you name your configuration file something other than `flutter_launcher_icons.yaml` or `pubspec.yaml` you will need to specify -the name of the file when running the package. +### 2. Run the package + +After setting up the configuration, all that is left to do is run the package. ```shell flutter pub get -flutter pub run flutter_launcher_icons -f +flutter pub run flutter_launcher_icons ``` -Note: If you are not using the existing `pubspec.yaml` ensure that your config file is located in the same directory as it. - -### 2. Run the package - -After setting up the configuration, all that is left to do is run the package. +If you name your configuration file something other than `flutter_launcher_icons.yaml` or `pubspec.yaml` you will need to specify +the name of the file when running the package. ```shell flutter pub get -flutter pub run flutter_launcher_icons +flutter pub run flutter_launcher_icons -f ``` +Note: If you are not using the existing `pubspec.yaml` ensure that your config file is located in the same directory as it. + If you encounter any issues [please report them here](https://github.com/fluttercommunity/flutter_launcher_icons/issues). In the above configuration, the package is setup to replace the existing launcher icons in both the Android and iOS project diff --git a/analysis_options.yaml b/analysis_options.yaml index f898260f78..1421ef5bcb 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -20,6 +20,7 @@ analyzer: - "lib/src/http/**" - "example/**" - "**/*.g.dart" + - "lib/src/version.dart" linter: rules: diff --git a/bin/generate.dart b/bin/generate.dart new file mode 100644 index 0000000000..7f52e5cec5 --- /dev/null +++ b/bin/generate.dart @@ -0,0 +1,113 @@ +import 'dart:io'; + +import 'package:args/args.dart'; + +import 'package:flutter_launcher_icons/constants.dart'; +import 'package:flutter_launcher_icons/src/version.dart'; + +const _defaultConfigFileName = './flutter_launcher_icons.yaml'; + +/// The function will be called from command line +/// using the following command: +/// ```sh +/// flutter pub run flutter_launcher_icons:generate +/// ``` +/// +/// Calling this function will generate a flutter_launcher_icons.yaml file +/// with a default config template. +/// +/// This command can take 2 optional arguments: +/// - --override: This will override the current `flutter_launcher_icons.yaml` +/// file if it exists, if not provided, the file will not be overridden and +/// a message will be printed to the console. +/// +/// - --fileName: This flag will take a file name as an argument and +/// will generate the config format in that file instead of the default +/// `flutter_launcher_icons.yaml` file, if not provided, +/// the default file will be used. +void main(List arguments) { + print(introMessage(packageVersion)); + + final parser = ArgParser() + ..addFlag('override', abbr: 'o', defaultsTo: false) + ..addOption( + 'fileName', + abbr: 'f', + defaultsTo: _defaultConfigFileName, + ); + + final results = parser.parse(arguments); + final override = results['override'] as bool; + final fileName = results['fileName'] as String; + + // Check if fileName is valid and has a .yaml extension + if (!fileName.endsWith('.yaml')) { + print('Invalid file name, please provide a valid file name'); + return; + } + + final file = File(fileName); + if (file.existsSync()) { + if (override) { + print('File already exists, overriding...'); + _generateConfigFile(file); + } else { + print( + 'File already exists, use --override flag to override the file, or use --fileName flag to use a different file name', + ); + } + } else { + try { + file.createSync(recursive: true); + _generateConfigFile(file); + } on Exception catch (e) { + print('Error creating file: $e'); + } + } +} + +void _generateConfigFile(File configFile) { + try { + configFile.writeAsStringSync(_configFileTemplate); + + print('\nConfig file generated successfully šŸŽ‰'); + print( + 'You can now use this new config file by using the command below:\n\n' + 'flutter pub run flutter_launcher_icons' + '${configFile.path == _defaultConfigFileName ? '' : ' -f ${configFile.path}'}\n', + ); + } on Exception catch (e) { + print('Error generating config file: $e'); + } +} + +const _configFileTemplate = ''' +# flutter pub run flutter_launcher_icons +flutter_launcher_icons: + image_path: "assets/icon/icon.png" + + android: "launcher_icon" + # image_path_android: "assets/icon/icon.png" + min_sdk_android: 21 # android min sdk min:16, default 21 + # adaptive_icon_background: "assets/icon/background.png" + # adaptive_icon_foreground: "assets/icon/foreground.png" + + ios: true + # image_path_ios: "assets/icon/icon.png" + remove_alpha_channel_ios: true + + web: + generate: true + image_path: "path/to/image.png" + background_color: "#hexcode" + theme_color: "#hexcode" + + windows: + generate: true + image_path: "path/to/image.png" + icon_size: 48 # min:48, max:256, default: 48 + + macos: + generate: true + image_path: "path/to/image.png" +'''; diff --git a/example/default_example/.metadata b/example/default_example/.metadata index f1a97ba1df..87fe9740e7 100644 --- a/example/default_example/.metadata +++ b/example/default_example/.metadata @@ -1,10 +1,45 @@ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # -# This file should be version controlled and should not be manually edited. +# This file should be version controlled. version: - revision: ce40de69b7b4f89c66d19c8dbd3bd86ae30f1bc6 - channel: dev + revision: f72efea43c3013323d1b95cff571f3c1caa37583 + channel: stable project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: f72efea43c3013323d1b95cff571f3c1caa37583 + base_revision: f72efea43c3013323d1b95cff571f3c1caa37583 + - platform: android + create_revision: f72efea43c3013323d1b95cff571f3c1caa37583 + base_revision: f72efea43c3013323d1b95cff571f3c1caa37583 + - platform: ios + create_revision: f72efea43c3013323d1b95cff571f3c1caa37583 + base_revision: f72efea43c3013323d1b95cff571f3c1caa37583 + - platform: linux + create_revision: f72efea43c3013323d1b95cff571f3c1caa37583 + base_revision: f72efea43c3013323d1b95cff571f3c1caa37583 + - platform: macos + create_revision: f72efea43c3013323d1b95cff571f3c1caa37583 + base_revision: f72efea43c3013323d1b95cff571f3c1caa37583 + - platform: web + create_revision: f72efea43c3013323d1b95cff571f3c1caa37583 + base_revision: f72efea43c3013323d1b95cff571f3c1caa37583 + - platform: windows + create_revision: f72efea43c3013323d1b95cff571f3c1caa37583 + base_revision: f72efea43c3013323d1b95cff571f3c1caa37583 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/example/default_example/pubspec.yaml b/example/default_example/pubspec.yaml index d0e9d4d88b..549e2d9df9 100644 --- a/example/default_example/pubspec.yaml +++ b/example/default_example/pubspec.yaml @@ -4,7 +4,7 @@ description: A new Flutter project to quickly test flutter_launcher_icons. version: 1.0.0+1 environment: - sdk: ">=2.13.0 <3.0.0" + sdk: ">=2.17.0 <3.0.0" dependencies: flutter: @@ -13,7 +13,7 @@ dependencies: flutter_launcher_icons: path: ../.. -flutter_icons: +flutter_launcher_icons: # image_path: "assets/images/icon-128x128.png" image_path_android: "assets/images/icon-710x599-android.png" image_path_ios: "assets/images/icon-1024x1024.png" diff --git a/example/flavors/flutter_launcher_icons-development.yaml b/example/flavors/flutter_launcher_icons-development.yaml index e279676332..51b2bc301b 100644 --- a/example/flavors/flutter_launcher_icons-development.yaml +++ b/example/flavors/flutter_launcher_icons-development.yaml @@ -1,4 +1,4 @@ -flutter_icons: +flutter_launcher_icons: android: true ios: true image_path: "assets/launcher_icon/demo-icon-dev.png" diff --git a/example/flavors/flutter_launcher_icons-integration.yaml b/example/flavors/flutter_launcher_icons-integration.yaml index fe0ab76687..6532eeaa03 100644 --- a/example/flavors/flutter_launcher_icons-integration.yaml +++ b/example/flavors/flutter_launcher_icons-integration.yaml @@ -1,4 +1,4 @@ -flutter_icons: +flutter_launcher_icons: android: true ios: true image_path: "assets/launcher_icon/demo-icon-int.png" diff --git a/example/flavors/flutter_launcher_icons-production.yaml b/example/flavors/flutter_launcher_icons-production.yaml index be5ac8bca7..ceeefa0245 100644 --- a/example/flavors/flutter_launcher_icons-production.yaml +++ b/example/flavors/flutter_launcher_icons-production.yaml @@ -1,4 +1,4 @@ -flutter_icons: +flutter_launcher_icons: android: true ios: true image_path: "assets/launcher_icon/demo-icon.png" \ No newline at end of file diff --git a/lib/abs/icon_generator.dart b/lib/abs/icon_generator.dart index 8e70a9d2b4..96c8871395 100644 --- a/lib/abs/icon_generator.dart +++ b/lib/abs/icon_generator.dart @@ -1,6 +1,9 @@ import 'dart:io'; -import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart'; +import 'package:flutter_launcher_icons/config/config.dart'; +import 'package:flutter_launcher_icons/config/macos_config.dart'; +import 'package:flutter_launcher_icons/config/web_config.dart'; +import 'package:flutter_launcher_icons/config/windows_config.dart'; import 'package:flutter_launcher_icons/logger.dart'; /// A base class to generate icons @@ -34,7 +37,7 @@ abstract class IconGenerator { /// Provides easy access to user arguments and configuration class IconGeneratorContext { /// Contains configuration from configuration file - final FlutterLauncherIconsConfig config; + final Config config; /// A logger final FLILogger logger; @@ -65,7 +68,7 @@ class IconGeneratorContext { /// Generates Icon for given platforms void generateIconsFor({ - required FlutterLauncherIconsConfig config, + required Config config, required String? flavor, required String prefixPath, required FLILogger logger, @@ -111,7 +114,7 @@ void generateIconsFor({ } } } catch (e, st) { - // todo: better error handling + // TODO(RatakondalaArun): better error handling // stacktrace should only print when verbose is turned on // else a normal help line logger diff --git a/lib/android.dart b/lib/android.dart index 864ec55dd1..a94d7ae773 100644 --- a/lib/android.dart +++ b/lib/android.dart @@ -1,10 +1,12 @@ +// ignore_for_file: public_member_api_docs + import 'dart:io'; +import 'package:flutter_launcher_icons/config/config.dart'; import 'package:flutter_launcher_icons/constants.dart'; import 'package:flutter_launcher_icons/constants.dart' as constants; import 'package:flutter_launcher_icons/custom_exceptions.dart'; -import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart'; -import 'package:flutter_launcher_icons/utils.dart'; +import 'package:flutter_launcher_icons/utils.dart' as utils; import 'package:flutter_launcher_icons/xml_templates.dart' as xml_template; import 'package:image/image.dart'; import 'package:path/path.dart' as path; @@ -33,23 +35,23 @@ List androidIcons = [ ]; void createDefaultIcons( - FlutterLauncherIconsConfig flutterLauncherIconsConfig, + Config config, String? flavor, ) { - printStatus('Creating default icons Android'); - // todo: support prefixPath - final String? filePath = flutterLauncherIconsConfig.getImagePathAndroid(); + utils.printStatus('Creating default icons Android'); + // TODO(p-mazhnik): support prefixPath + final String? filePath = config.getImagePathAndroid(); if (filePath == null) { throw const InvalidConfigException(errorMissingImagePath); } - final Image? image = decodeImageFile(filePath); + final Image? image = utils.decodeImageFile(filePath); if (image == null) { return; } final File androidManifestFile = File(constants.androidManifestFile); - if (flutterLauncherIconsConfig.isCustomAndroidFile) { - printStatus('Adding a new Android launcher icon'); - final String iconName = flutterLauncherIconsConfig.android; + if (config.isCustomAndroidFile) { + utils.printStatus('Adding a new Android launcher icon'); + final String iconName = config.android; isAndroidIconNameCorrectFormat(iconName); final String iconPath = '$iconName.png'; for (AndroidIconTemplate template in androidIcons) { @@ -57,7 +59,7 @@ void createDefaultIcons( } overwriteAndroidManifestWithNewLauncherIcon(iconName, androidManifestFile); } else { - printStatus( + utils.printStatus( 'Overwriting the default Android launcher icon with a new icon', ); for (AndroidIconTemplate template in androidIcons) { @@ -87,20 +89,18 @@ bool isAndroidIconNameCorrectFormat(String iconName) { } void createAdaptiveIcons( - FlutterLauncherIconsConfig flutterLauncherIconsConfig, + Config config, String? flavor, ) { - printStatus('Creating adaptive icons Android'); + utils.printStatus('Creating adaptive icons Android'); // Retrieve the necessary Flutter Launcher Icons configuration from the pubspec.yaml file - final String? backgroundConfig = - flutterLauncherIconsConfig.adaptiveIconBackground; - final String? foregroundImagePath = - flutterLauncherIconsConfig.adaptiveIconForeground; + final String? backgroundConfig = config.adaptiveIconBackground; + final String? foregroundImagePath = config.adaptiveIconForeground; if (backgroundConfig == null || foregroundImagePath == null) { throw const InvalidConfigException(errorMissingImagePath); } - final Image? foregroundImage = decodeImageFile(foregroundImagePath); + final Image? foregroundImage = utils.decodeImageFile(foregroundImagePath); if (foregroundImage == null) { return; } @@ -118,12 +118,12 @@ void createAdaptiveIcons( // Create adaptive icon background if (isAdaptiveIconConfigPngFile(backgroundConfig)) { _createAdaptiveBackgrounds( - flutterLauncherIconsConfig, + config, backgroundConfig, flavor, ); } else { - createAdaptiveIconMipmapXmlFile(flutterLauncherIconsConfig, flavor); + createAdaptiveIconMipmapXmlFile(config, flavor); updateColorsXmlFile(backgroundConfig, flavor); } } @@ -138,11 +138,13 @@ void createAdaptiveIcons( void updateColorsXmlFile(String backgroundConfig, String? flavor) { final File colorsXml = File(constants.androidColorsFile(flavor)); if (colorsXml.existsSync()) { - printStatus('Updating colors.xml with color for adaptive icon background'); + utils.printStatus( + 'Updating colors.xml with color for adaptive icon background', + ); updateColorsFile(colorsXml, backgroundConfig); } else { - printStatus('No colors.xml file found in your Android project'); - printStatus( + utils.printStatus('No colors.xml file found in your Android project'); + utils.printStatus( 'Creating colors.xml file and adding it to your Android project', ); createNewColorsFile(backgroundConfig, flavor); @@ -152,14 +154,12 @@ void updateColorsXmlFile(String backgroundConfig, String? flavor) { /// Creates the xml file required for the adaptive launcher icon /// FILE LOCATED HERE: res/mipmap-anydpi/{icon-name-from-yaml-config}.xml void createAdaptiveIconMipmapXmlFile( - FlutterLauncherIconsConfig flutterLauncherIconsConfig, + Config config, String? flavor, ) { - if (flutterLauncherIconsConfig.isCustomAndroidFile) { + if (config.isCustomAndroidFile) { File( - constants.androidAdaptiveXmlFolder(flavor) + - flutterLauncherIconsConfig.android + - '.xml', + constants.androidAdaptiveXmlFolder(flavor) + config.android + '.xml', ).create(recursive: true).then((File adaptiveIcon) { adaptiveIcon.writeAsString(xml_template.icLauncherXml); }); @@ -176,12 +176,12 @@ void createAdaptiveIconMipmapXmlFile( /// creates adaptive background using png image void _createAdaptiveBackgrounds( - FlutterLauncherIconsConfig flutterLauncherIconsConfig, + Config config, String adaptiveIconBackgroundImagePath, String? flavor, ) { final String filePath = adaptiveIconBackgroundImagePath; - final Image? image = decodeImageFile(filePath); + final Image? image = utils.decodeImageFile(filePath); if (image == null) { return; } @@ -199,11 +199,9 @@ void _createAdaptiveBackgrounds( // Creates the xml file required for the adaptive launcher icon // FILE LOCATED HERE: res/mipmap-anydpi/{icon-name-from-yaml-config}.xml - if (flutterLauncherIconsConfig.isCustomAndroidFile) { + if (config.isCustomAndroidFile) { File( - constants.androidAdaptiveXmlFolder(flavor) + - flutterLauncherIconsConfig.android + - '.xml', + constants.androidAdaptiveXmlFolder(flavor) + config.android + '.xml', ).create(recursive: true).then((File adaptiveIcon) { adaptiveIcon.writeAsString(xml_template.icLauncherDrawableBackgroundXml); }); @@ -266,7 +264,7 @@ void overwriteExistingIcons( String filename, String? flavor, ) { - final Image newFile = createResizedImage(template.size, image); + final Image newFile = utils.createResizedImage(template.size, image); File( constants.androidResFolder(flavor) + template.directoryName + @@ -286,7 +284,7 @@ void _saveNewImages( String iconFilePath, String? flavor, ) { - final Image newFile = createResizedImage(template.size, image); + final Image newFile = utils.createResizedImage(template.size, image); File( constants.androidResFolder(flavor) + template.directoryName + diff --git a/lib/config/config.dart b/lib/config/config.dart new file mode 100644 index 0000000000..db28cc559d --- /dev/null +++ b/lib/config/config.dart @@ -0,0 +1,204 @@ +import 'dart:io'; + +import 'package:checked_yaml/checked_yaml.dart' as yaml; +import 'package:flutter_launcher_icons/config/macos_config.dart'; +import 'package:flutter_launcher_icons/config/web_config.dart'; +import 'package:flutter_launcher_icons/config/windows_config.dart'; +import 'package:flutter_launcher_icons/constants.dart' as constants; +import 'package:flutter_launcher_icons/custom_exceptions.dart'; +import 'package:flutter_launcher_icons/utils.dart' as utils; +import 'package:json_annotation/json_annotation.dart'; +import 'package:path/path.dart' as path; + +part 'config.g.dart'; + +/// A model representing the flutter_launcher_icons configuration +@JsonSerializable( + anyMap: true, + checked: true, +) +class Config { + /// Creates an instance of [Config] + const Config({ + this.imagePath, + this.android = false, + this.ios = false, + this.imagePathAndroid, + this.imagePathIOS, + this.adaptiveIconForeground, + this.adaptiveIconBackground, + this.minSdkAndroid = constants.androidDefaultAndroidMinSDK, + this.removeAlphaIOS = false, + this.backgroundColorIOS = '#ffffff', + this.webConfig, + this.windowsConfig, + this.macOSConfig, + }); + + /// Creates [Config] for given [flavor] and [prefixPath] + static Config? loadConfigFromFlavor( + String flavor, + String prefixPath, + ) { + return _getConfigFromPubspecYaml( + prefix: prefixPath, + pathToPubspecYamlFile: utils.flavorConfigFile(flavor), + ); + } + + /// Loads flutter launcher icons configs from given [filePath] + static Config? loadConfigFromPath(String filePath, String prefixPath) { + return _getConfigFromPubspecYaml( + prefix: prefixPath, + pathToPubspecYamlFile: filePath, + ); + } + + /// Loads flutter launcher icons config from `pubspec.yaml` file + static Config? loadConfigFromPubSpec(String prefix) { + return _getConfigFromPubspecYaml( + prefix: prefix, + pathToPubspecYamlFile: constants.pubspecFilePath, + ); + } + + static Config? _getConfigFromPubspecYaml({ + required String pathToPubspecYamlFile, + required String prefix, + }) { + final configFile = File(path.join(prefix, pathToPubspecYamlFile)); + if (!configFile.existsSync()) { + return null; + } + final configContent = configFile.readAsStringSync(); + try { + return yaml.checkedYamlDecode( + configContent, + (Map? json) { + if (json != null) { + // if we have flutter_icons configuration ... + if (json['flutter_icons'] != null) { + stderr.writeln('\nāš  Warning: flutter_icons has been deprecated ' + 'please use flutter_launcher_icons instead in your yaml files'); + return Config.fromJson(json['flutter_icons']); + } + // if we have flutter_launcher_icons configuration ... + if (json['flutter_launcher_icons'] != null) { + return Config.fromJson(json['flutter_launcher_icons']); + } + } + return null; + }, + allowNull: true, + ); + } on yaml.ParsedYamlException catch (e) { + throw InvalidConfigException(e.formattedMessage); + } catch (e) { + rethrow; + } + } + + /// Generic image_path + @JsonKey(name: 'image_path') + final String? imagePath; + + /// Returns true or path if android config is enabled + final dynamic android; // path or bool + + /// Returns true or path if ios config is enabled + final dynamic ios; // path or bool + + /// Image path specific to android + @JsonKey(name: 'image_path_android') + final String? imagePathAndroid; + + /// Image path specific to ios + @JsonKey(name: 'image_path_ios') + final String? imagePathIOS; + + /// android adaptive icon foreground image + @JsonKey(name: 'adaptive_icon_foreground') + final String? adaptiveIconForeground; + + /// android adaptive_icon_background image + @JsonKey(name: 'adaptive_icon_background') + final String? adaptiveIconBackground; + + /// Android min_sdk_android + @JsonKey(name: 'min_sdk_android') + final int minSdkAndroid; + + /// IOS remove_alpha_ios + @JsonKey(name: 'remove_alpha_ios') + final bool removeAlphaIOS; + + /// IOS background_color_ios + @JsonKey(name: 'background_color_ios') + final String backgroundColorIOS; + + /// Web platform config + @JsonKey(name: 'web') + final WebConfig? webConfig; + + /// Windows platform config + @JsonKey(name: 'windows') + final WindowsConfig? windowsConfig; + + /// MacOS platform config + @JsonKey(name: 'macos') + final MacOSConfig? macOSConfig; + + /// Creates [Config] icons from [json] + factory Config.fromJson(Map json) => _$ConfigFromJson(json); + + /// whether or not there is configuration for adaptive icons for android + bool get hasAndroidAdaptiveConfig => + isNeedingNewAndroidIcon && + adaptiveIconForeground != null && + adaptiveIconBackground != null; + + /// Checks if contains any platform config + bool get hasPlatformConfig { + return ios != false || + android != false || + webConfig != null || + windowsConfig != null || + macOSConfig != null; + } + + /// Whether or not configuration for generating Web icons exist + bool get hasWebConfig => webConfig != null; + + /// Whether or not configuration for generating Windows icons exist + bool get hasWindowsConfig => windowsConfig != null; + + /// Whether or not configuration for generating MacOS icons exists + bool get hasMacOSConfig => macOSConfig != null; + + /// Check to see if specified Android config is a string or bool + /// String - Generate new launcher icon with the string specified + /// bool - override the default flutter project icon + bool get isCustomAndroidFile => android is String; + + /// if we are needing a new Android icon + bool get isNeedingNewAndroidIcon => android != false; + + /// if we are needing a new iOS icon + bool get isNeedingNewIOSIcon => ios != false; + + /// Method for the retrieval of the Android icon path + /// If image_path_android is found, this will be prioritised over the image_path + /// value. + String? getImagePathAndroid() => imagePathAndroid ?? imagePath; + + // TODO(RatakondalaArun): refactor after Android & iOS configs will be refactored to the new schema + // https://github.com/fluttercommunity/flutter_launcher_icons/issues/394 + /// get the image path for IOS + String? getImagePathIOS() => imagePathIOS ?? imagePath; + + /// Converts config to [Map] + Map toJson() => _$ConfigToJson(this); + + @override + String toString() => 'FlutterLauncherIconsConfig: ${toJson()}'; +} diff --git a/lib/config/config.g.dart b/lib/config/config.g.dart new file mode 100644 index 0000000000..9e18dc1675 --- /dev/null +++ b/lib/config/config.g.dart @@ -0,0 +1,64 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'config.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +Config _$ConfigFromJson(Map json) => $checkedCreate( + 'Config', + json, + ($checkedConvert) { + final val = Config( + imagePath: $checkedConvert('image_path', (v) => v as String?), + android: $checkedConvert('android', (v) => v ?? false), + ios: $checkedConvert('ios', (v) => v ?? false), + imagePathAndroid: + $checkedConvert('image_path_android', (v) => v as String?), + imagePathIOS: $checkedConvert('image_path_ios', (v) => v as String?), + adaptiveIconForeground: + $checkedConvert('adaptive_icon_foreground', (v) => v as String?), + adaptiveIconBackground: + $checkedConvert('adaptive_icon_background', (v) => v as String?), + minSdkAndroid: $checkedConvert('min_sdk_android', + (v) => v as int? ?? constants.androidDefaultAndroidMinSDK), + removeAlphaIOS: + $checkedConvert('remove_alpha_ios', (v) => v as bool? ?? false), + webConfig: $checkedConvert( + 'web', (v) => v == null ? null : WebConfig.fromJson(v as Map)), + windowsConfig: $checkedConvert('windows', + (v) => v == null ? null : WindowsConfig.fromJson(v as Map)), + macOSConfig: $checkedConvert('macos', + (v) => v == null ? null : MacOSConfig.fromJson(v as Map)), + ); + return val; + }, + fieldKeyMap: const { + 'imagePath': 'image_path', + 'imagePathAndroid': 'image_path_android', + 'imagePathIOS': 'image_path_ios', + 'adaptiveIconForeground': 'adaptive_icon_foreground', + 'adaptiveIconBackground': 'adaptive_icon_background', + 'minSdkAndroid': 'min_sdk_android', + 'removeAlphaIOS': 'remove_alpha_ios', + 'webConfig': 'web', + 'windowsConfig': 'windows', + 'macOSConfig': 'macos' + }, + ); + +Map _$ConfigToJson(Config instance) => { + 'image_path': instance.imagePath, + 'android': instance.android, + 'ios': instance.ios, + 'image_path_android': instance.imagePathAndroid, + 'image_path_ios': instance.imagePathIOS, + 'adaptive_icon_foreground': instance.adaptiveIconForeground, + 'adaptive_icon_background': instance.adaptiveIconBackground, + 'min_sdk_android': instance.minSdkAndroid, + 'remove_alpha_ios': instance.removeAlphaIOS, + 'web': instance.webConfig, + 'windows': instance.windowsConfig, + 'macos': instance.macOSConfig, + }; diff --git a/lib/config/macos_config.dart b/lib/config/macos_config.dart new file mode 100644 index 0000000000..ee267efb64 --- /dev/null +++ b/lib/config/macos_config.dart @@ -0,0 +1,33 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'macos_config.g.dart'; + +/// The flutter_launcher_icons configuration set for MacOS +@JsonSerializable( + anyMap: true, + checked: true, +) +class MacOSConfig { + /// Specifies weather to generate icons for macos + @JsonKey() + final bool generate; + + /// Image path for macos + @JsonKey(name: 'image_path') + final String? imagePath; + + /// Creates a instance of [MacOSConfig] + const MacOSConfig({ + this.generate = false, + this.imagePath, + }); + + /// Creates [WebConfig] from [json] + factory MacOSConfig.fromJson(Map json) => _$MacOSConfigFromJson(json); + + /// Creates [Map] from [WebConfig] + Map toJson() => _$MacOSConfigToJson(this); + + @override + String toString() => '$runtimeType: ${toJson()}'; +} diff --git a/lib/config/macos_config.g.dart b/lib/config/macos_config.g.dart new file mode 100644 index 0000000000..ee22327acb --- /dev/null +++ b/lib/config/macos_config.g.dart @@ -0,0 +1,26 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'macos_config.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +MacOSConfig _$MacOSConfigFromJson(Map json) => $checkedCreate( + 'MacOSConfig', + json, + ($checkedConvert) { + final val = MacOSConfig( + generate: $checkedConvert('generate', (v) => v as bool? ?? false), + imagePath: $checkedConvert('image_path', (v) => v as String?), + ); + return val; + }, + fieldKeyMap: const {'imagePath': 'image_path'}, + ); + +Map _$MacOSConfigToJson(MacOSConfig instance) => + { + 'generate': instance.generate, + 'image_path': instance.imagePath, + }; diff --git a/lib/config/web_config.dart b/lib/config/web_config.dart new file mode 100644 index 0000000000..c0130375c3 --- /dev/null +++ b/lib/config/web_config.dart @@ -0,0 +1,42 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'web_config.g.dart'; + +/// The flutter_launcher_icons configuration set for Web +@JsonSerializable( + anyMap: true, + checked: true, +) +class WebConfig { + /// Specifies weather to generate icons for web + final bool generate; + + /// Image path for web + @JsonKey(name: 'image_path') + final String? imagePath; + + /// manifest.json's background_color + @JsonKey(name: 'background_color') + final String? backgroundColor; + + /// manifest.json's theme_color + @JsonKey(name: 'theme_color') + final String? themeColor; + + /// Creates an instance of [WebConfig] + const WebConfig({ + this.generate = false, + this.imagePath, + this.backgroundColor, + this.themeColor, + }); + + /// Creates [WebConfig] from [json] + factory WebConfig.fromJson(Map json) => _$WebConfigFromJson(json); + + /// Creates [Map] from [WebConfig] + Map toJson() => _$WebConfigToJson(this); + + @override + String toString() => 'WebConfig: ${toJson()}'; +} diff --git a/lib/config/web_config.g.dart b/lib/config/web_config.g.dart new file mode 100644 index 0000000000..d1451c0b35 --- /dev/null +++ b/lib/config/web_config.g.dart @@ -0,0 +1,34 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'web_config.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +WebConfig _$WebConfigFromJson(Map json) => $checkedCreate( + 'WebConfig', + json, + ($checkedConvert) { + final val = WebConfig( + generate: $checkedConvert('generate', (v) => v as bool? ?? false), + imagePath: $checkedConvert('image_path', (v) => v as String?), + backgroundColor: + $checkedConvert('background_color', (v) => v as String?), + themeColor: $checkedConvert('theme_color', (v) => v as String?), + ); + return val; + }, + fieldKeyMap: const { + 'imagePath': 'image_path', + 'backgroundColor': 'background_color', + 'themeColor': 'theme_color' + }, + ); + +Map _$WebConfigToJson(WebConfig instance) => { + 'generate': instance.generate, + 'image_path': instance.imagePath, + 'background_color': instance.backgroundColor, + 'theme_color': instance.themeColor, + }; diff --git a/lib/config/windows_config.dart b/lib/config/windows_config.dart new file mode 100644 index 0000000000..0c94e2e585 --- /dev/null +++ b/lib/config/windows_config.dart @@ -0,0 +1,37 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'windows_config.g.dart'; + +/// The flutter_launcher_icons configuration set for Windows +@JsonSerializable( + anyMap: true, + checked: true, +) +class WindowsConfig { + /// Specifies weather to generate icons for web + final bool generate; + + /// Image path for web + @JsonKey(name: 'image_path') + final String? imagePath; + + /// Size of the icon to generate + @JsonKey(name: 'icon_size') + final int? iconSize; + + /// Creates a instance of [WindowsConfig] + const WindowsConfig({ + this.generate = false, + this.imagePath, + this.iconSize, + }); + + /// Creates [WindowsConfig] from [json] + factory WindowsConfig.fromJson(Map json) => _$WindowsConfigFromJson(json); + + /// Creates [Map] from [WindowsConfig] + Map toJson() => _$WindowsConfigToJson(this); + + @override + String toString() => 'WindowsConfig: ${toJson()}'; +} diff --git a/lib/config/windows_config.g.dart b/lib/config/windows_config.g.dart new file mode 100644 index 0000000000..ef7a20e1ec --- /dev/null +++ b/lib/config/windows_config.g.dart @@ -0,0 +1,28 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'windows_config.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +WindowsConfig _$WindowsConfigFromJson(Map json) => $checkedCreate( + 'WindowsConfig', + json, + ($checkedConvert) { + final val = WindowsConfig( + generate: $checkedConvert('generate', (v) => v as bool? ?? false), + imagePath: $checkedConvert('image_path', (v) => v as String?), + iconSize: $checkedConvert('icon_size', (v) => v as int?), + ); + return val; + }, + fieldKeyMap: const {'imagePath': 'image_path', 'iconSize': 'icon_size'}, + ); + +Map _$WindowsConfigToJson(WindowsConfig instance) => + { + 'generate': instance.generate, + 'image_path': instance.imagePath, + 'icon_size': instance.iconSize, + }; diff --git a/lib/constants.dart b/lib/constants.dart index 897f4230b3..9f51dab39b 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -1,3 +1,5 @@ +// ignore_for_file: public_member_api_docs + import 'package:path/path.dart' as path; /// Relative path to android resource folder @@ -44,7 +46,7 @@ String webIconsDirPath = path.join(webDirPath, 'icons'); /// Relative web manifest.json file path String webManifestFilePath = path.join(webDirPath, 'manifest.json'); -// todo: support for other images formats +// TODO(RatakondalaArun): support for other images formats /// Relative favicon.png path String webFaviconFilePath = path.join(webDirPath, 'favicon.png'); diff --git a/lib/custom_exceptions.dart b/lib/custom_exceptions.dart index 82cbe2b746..8b72813efa 100644 --- a/lib/custom_exceptions.dart +++ b/lib/custom_exceptions.dart @@ -1,7 +1,11 @@ import 'package:flutter_launcher_icons/utils.dart'; -class InvalidAndroidIconNameException implements Exception { - const InvalidAndroidIconNameException([this.message]); +/// Exception to be thrown whenever we have an invalid configuration +class InvalidConfigException implements Exception { + /// Constructs instance + const InvalidConfigException([this.message]); + + /// Message for the exception final String? message; @override @@ -10,8 +14,12 @@ class InvalidAndroidIconNameException implements Exception { } } -class InvalidConfigException implements Exception { - const InvalidConfigException([this.message]); +/// Exception to be thrown whenever using an invalid Android icon name +class InvalidAndroidIconNameException implements Exception { + /// Constructs instance of this exception + const InvalidAndroidIconNameException([this.message]); + + /// Message for the exception final String? message; @override @@ -20,8 +28,12 @@ class InvalidConfigException implements Exception { } } +/// Exception to be thrown whenever no config is found class NoConfigFoundException implements Exception { + /// Constructs instance of this exception const NoConfigFoundException([this.message]); + + /// Message for the exception final String? message; @override @@ -30,8 +42,12 @@ class NoConfigFoundException implements Exception { } } +/// Exception to be thrown whenever there is no decoder for the image format class NoDecoderForImageFormatException implements Exception { + /// Constructs instance of this exception const NoDecoderForImageFormatException([this.message]); + + /// Message for the exception final String? message; @override diff --git a/lib/flutter_launcher_icons_config.dart b/lib/flutter_launcher_icons_config.dart deleted file mode 100644 index d12c2afd87..0000000000 --- a/lib/flutter_launcher_icons_config.dart +++ /dev/null @@ -1,293 +0,0 @@ -import 'dart:io'; - -import 'package:checked_yaml/checked_yaml.dart' as yaml; -import 'package:json_annotation/json_annotation.dart'; -import 'package:path/path.dart' as path; - -import 'constants.dart' as constants; -import 'custom_exceptions.dart'; -import 'utils.dart' as utils; - -part 'flutter_launcher_icons_config.g.dart'; - -/// A Config parsed from flutter_launcher_config.yaml -@JsonSerializable( - anyMap: true, - checked: true, -) -class FlutterLauncherIconsConfig { - /// Generic imagepath - @JsonKey(name: 'image_path') - final String? imagePath; - - /// Returns true or path if android config is enabled - final dynamic android; // path or bool - - /// Returns true or path if ios config is enabled - final dynamic ios; // path or bool - - /// Image path specific to android - @JsonKey(name: 'image_path_android') - final String? imagePathAndroid; - - /// Image path specific to ios - @JsonKey(name: 'image_path_ios') - final String? imagePathIOS; - - /// android adaptive icon foreground image - @JsonKey(name: 'adaptive_icon_foreground') - final String? adaptiveIconForeground; - - /// android adaptive_icon_background image - @JsonKey(name: 'adaptive_icon_background') - final String? adaptiveIconBackground; - - /// Android min_sdk_android - @JsonKey(name: 'min_sdk_android') - final int minSdkAndroid; - - /// IOS remove_alpha_ios - @JsonKey(name: 'remove_alpha_ios') - final bool removeAlphaIOS; - - /// IOS background_color_ios - @JsonKey(name: 'background_color_ios') - final String backgroundColorIOS; - - /// Web platform config - @JsonKey(name: 'web') - final WebConfig? webConfig; - - /// Windows platform config - @JsonKey(name: 'windows') - final WindowsConfig? windowsConfig; - - /// MacOS platform config - @JsonKey(name: 'macos') - final MacOSConfig? macOSConfig; - - /// Creates an instance of [FlutterLauncherIconsConfig] - const FlutterLauncherIconsConfig({ - this.imagePath, - this.android = false, - this.ios = false, - this.imagePathAndroid, - this.imagePathIOS, - this.adaptiveIconForeground, - this.adaptiveIconBackground, - this.minSdkAndroid = constants.androidDefaultAndroidMinSDK, - this.removeAlphaIOS = false, - this.backgroundColorIOS = '#ffffff', - this.webConfig, - this.windowsConfig, - this.macOSConfig, - }); - - /// Creates [FlutterLauncherIconsConfig] icons from [json] - factory FlutterLauncherIconsConfig.fromJson(Map json) => - _$FlutterLauncherIconsConfigFromJson(json); - - bool get hasAndroidAdaptiveConfig => - isNeedingNewAndroidIcon && - adaptiveIconForeground != null && - adaptiveIconBackground != null; - - /// Checks if contains any platform config - bool get hasPlatformConfig { - return ios != false || - android != false || - webConfig != null || - windowsConfig != null || - macOSConfig != null; - } - - /// Check to see if specified Android config is a string or bool - /// String - Generate new launcher icon with the string specified - /// bool - override the default flutter project icon - bool get isCustomAndroidFile => android is String; - - bool get isNeedingNewAndroidIcon => android != false; - - bool get isNeedingNewIOSIcon => ios != false; - - /// Method for the retrieval of the Android icon path - /// If image_path_android is found, this will be prioritised over the image_path - /// value. - String? getImagePathAndroid() => imagePathAndroid ?? imagePath; - // todo: refactor after Android & iOS configs will be refactored to the new schema - // https://github.com/fluttercommunity/flutter_launcher_icons/issues/394 - String? getImagePathIOS() => imagePathIOS ?? imagePath; - - /// Converts config to [Map] - Map toJson() => _$FlutterLauncherIconsConfigToJson(this); - - @override - String toString() => 'FlutterLauncherIconsConfig: ${toJson()}'; - - /// Creates [FlutterLauncherIconsConfig] for given [flavor] and [prefixPath] - static FlutterLauncherIconsConfig? loadConfigFromFlavor( - String flavor, - String prefixPath, - ) { - return FlutterLauncherIconsConfig.loadConfigFromPath( - utils.flavorConfigFile(flavor), - prefixPath, - ); - } - - /// Loads flutter launcher icons configs from given [filePath] - static FlutterLauncherIconsConfig? loadConfigFromPath( - String filePath, - String prefixPath, - ) { - final configFile = File(path.join(prefixPath, filePath)); - if (!configFile.existsSync()) { - return null; - } - final configContent = configFile.readAsStringSync(); - try { - return yaml.checkedYamlDecode( - configContent, - (json) { - // todo: add support for new scheme https://github.com/fluttercommunity/flutter_launcher_icons/issues/373 - return json == null || json['flutter_icons'] == null - ? null - : FlutterLauncherIconsConfig.fromJson(json['flutter_icons']); - }, - allowNull: true, - ); - } on yaml.ParsedYamlException catch (e) { - throw InvalidConfigException(e.formattedMessage); - } catch (e) { - rethrow; - } - } - - /// Loads flutter launcher icons config from `pubspec.yaml` file - static FlutterLauncherIconsConfig? loadConfigFromPubSpec(String prefix) { - try { - final pubspecFile = File(path.join(prefix, constants.pubspecFilePath)); - if (!pubspecFile.existsSync()) { - return null; - } - final pubspecContent = pubspecFile.readAsStringSync(); - return yaml.checkedYamlDecode( - pubspecContent, - (json) { - // todo: add support for new scheme https://github.com/fluttercommunity/flutter_launcher_icons/issues/373 - return json == null || json['flutter_icons'] == null - ? null - : FlutterLauncherIconsConfig.fromJson(json['flutter_icons']); - }, - allowNull: true, - ); - } on yaml.ParsedYamlException catch (e) { - throw InvalidConfigException(e.formattedMessage); - } catch (e) { - rethrow; - } - } -} - -/// A Configs for Windows -@JsonSerializable( - anyMap: true, - checked: true, -) -class MacOSConfig { - /// Specifies weather to generate icons for macos - @JsonKey() - final bool generate; - - /// Image path for macos - @JsonKey(name: 'image_path') - final String? imagePath; - - /// Creates a instance of [MacOSConfig] - const MacOSConfig({ - this.generate = false, - this.imagePath, - }); - - /// Creates [WebConfig] from [json] - factory MacOSConfig.fromJson(Map json) => _$MacOSConfigFromJson(json); - - /// Creates [Map] from [WebConfig] - Map toJson() => _$MacOSConfigToJson(this); - - @override - String toString() => '$runtimeType: ${toJson()}'; -} - -/// Parse `web` config from `flutter_launcher_icons.yaml` -@JsonSerializable( - anyMap: true, - checked: true, -) -class WebConfig { - /// Specifies weather to generate icons for web - final bool generate; - - /// Image path for web - @JsonKey(name: 'image_path') - final String? imagePath; - - /// manifest.json's background_color - @JsonKey(name: 'background_color') - final String? backgroundColor; - - /// manifest.json's theme_color - @JsonKey(name: 'theme_color') - final String? themeColor; - - /// Creates an instance of [WebConfig] - const WebConfig({ - this.generate = false, - this.imagePath, - this.backgroundColor, - this.themeColor, - }); - - /// Creates [WebConfig] from [json] - factory WebConfig.fromJson(Map json) => _$WebConfigFromJson(json); - - /// Creates [Map] from [WebConfig] - Map toJson() => _$WebConfigToJson(this); - - @override - String toString() => 'WebConfig: ${toJson()}'; -} - -/// A Configs for Windows -@JsonSerializable( - anyMap: true, - checked: true, -) -class WindowsConfig { - /// Specifies weather to generate icons for web - final bool generate; - - /// Image path for web - @JsonKey(name: 'image_path') - final String? imagePath; - - /// Size of the icon to generate - @JsonKey(name: 'icon_size') - final int? iconSize; - - /// Creates a instance of [WindowsConfig] - const WindowsConfig({ - this.generate = false, - this.imagePath, - this.iconSize, - }); - - /// Creates [WindowsConfig] from [json] - factory WindowsConfig.fromJson(Map json) => _$WindowsConfigFromJson(json); - - /// Creates [Map] from [WindowsConfig] - Map toJson() => _$WindowsConfigToJson(this); - - @override - String toString() => 'WindowsConfig: ${toJson()}'; -} diff --git a/lib/flutter_launcher_icons_config.g.dart b/lib/flutter_launcher_icons_config.g.dart deleted file mode 100644 index cc290c760c..0000000000 --- a/lib/flutter_launcher_icons_config.g.dart +++ /dev/null @@ -1,138 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'flutter_launcher_icons_config.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -FlutterLauncherIconsConfig _$FlutterLauncherIconsConfigFromJson(Map json) => - $checkedCreate( - 'FlutterLauncherIconsConfig', - json, - ($checkedConvert) { - final val = FlutterLauncherIconsConfig( - imagePath: $checkedConvert('image_path', (v) => v as String?), - android: $checkedConvert('android', (v) => v ?? false), - ios: $checkedConvert('ios', (v) => v ?? false), - imagePathAndroid: - $checkedConvert('image_path_android', (v) => v as String?), - imagePathIOS: $checkedConvert('image_path_ios', (v) => v as String?), - adaptiveIconForeground: - $checkedConvert('adaptive_icon_foreground', (v) => v as String?), - adaptiveIconBackground: - $checkedConvert('adaptive_icon_background', (v) => v as String?), - minSdkAndroid: $checkedConvert('min_sdk_android', - (v) => v as int? ?? constants.androidDefaultAndroidMinSDK), - removeAlphaIOS: - $checkedConvert('remove_alpha_ios', (v) => v as bool? ?? false), - backgroundColorIOS: $checkedConvert( - 'background_color_ios', (v) => v as String? ?? '#ffffff'), - webConfig: $checkedConvert( - 'web', (v) => v == null ? null : WebConfig.fromJson(v as Map)), - windowsConfig: $checkedConvert('windows', - (v) => v == null ? null : WindowsConfig.fromJson(v as Map)), - macOSConfig: $checkedConvert('macos', - (v) => v == null ? null : MacOSConfig.fromJson(v as Map)), - ); - return val; - }, - fieldKeyMap: const { - 'imagePath': 'image_path', - 'imagePathAndroid': 'image_path_android', - 'imagePathIOS': 'image_path_ios', - 'adaptiveIconForeground': 'adaptive_icon_foreground', - 'adaptiveIconBackground': 'adaptive_icon_background', - 'minSdkAndroid': 'min_sdk_android', - 'removeAlphaIOS': 'remove_alpha_ios', - 'backgroundColorIOS': 'background_color_ios', - 'webConfig': 'web', - 'windowsConfig': 'windows', - 'macOSConfig': 'macos' - }, - ); - -Map _$FlutterLauncherIconsConfigToJson( - FlutterLauncherIconsConfig instance) => - { - 'image_path': instance.imagePath, - 'android': instance.android, - 'ios': instance.ios, - 'image_path_android': instance.imagePathAndroid, - 'image_path_ios': instance.imagePathIOS, - 'adaptive_icon_foreground': instance.adaptiveIconForeground, - 'adaptive_icon_background': instance.adaptiveIconBackground, - 'min_sdk_android': instance.minSdkAndroid, - 'remove_alpha_ios': instance.removeAlphaIOS, - 'background_color_ios': instance.backgroundColorIOS, - 'web': instance.webConfig, - 'windows': instance.windowsConfig, - 'macos': instance.macOSConfig, - }; - -MacOSConfig _$MacOSConfigFromJson(Map json) => $checkedCreate( - 'MacOSConfig', - json, - ($checkedConvert) { - final val = MacOSConfig( - generate: $checkedConvert('generate', (v) => v as bool? ?? false), - imagePath: $checkedConvert('image_path', (v) => v as String?), - ); - return val; - }, - fieldKeyMap: const {'imagePath': 'image_path'}, - ); - -Map _$MacOSConfigToJson(MacOSConfig instance) => - { - 'generate': instance.generate, - 'image_path': instance.imagePath, - }; - -WebConfig _$WebConfigFromJson(Map json) => $checkedCreate( - 'WebConfig', - json, - ($checkedConvert) { - final val = WebConfig( - generate: $checkedConvert('generate', (v) => v as bool? ?? false), - imagePath: $checkedConvert('image_path', (v) => v as String?), - backgroundColor: - $checkedConvert('background_color', (v) => v as String?), - themeColor: $checkedConvert('theme_color', (v) => v as String?), - ); - return val; - }, - fieldKeyMap: const { - 'imagePath': 'image_path', - 'backgroundColor': 'background_color', - 'themeColor': 'theme_color' - }, - ); - -Map _$WebConfigToJson(WebConfig instance) => { - 'generate': instance.generate, - 'image_path': instance.imagePath, - 'background_color': instance.backgroundColor, - 'theme_color': instance.themeColor, - }; - -WindowsConfig _$WindowsConfigFromJson(Map json) => $checkedCreate( - 'WindowsConfig', - json, - ($checkedConvert) { - final val = WindowsConfig( - generate: $checkedConvert('generate', (v) => v as bool? ?? false), - imagePath: $checkedConvert('image_path', (v) => v as String?), - iconSize: $checkedConvert('icon_size', (v) => v as int?), - ); - return val; - }, - fieldKeyMap: const {'imagePath': 'image_path', 'iconSize': 'icon_size'}, - ); - -Map _$WindowsConfigToJson(WindowsConfig instance) => - { - 'generate': instance.generate, - 'image_path': instance.imagePath, - 'icon_size': instance.iconSize, - }; diff --git a/lib/ios.dart b/lib/ios.dart index 939f687f36..f878f876cd 100644 --- a/lib/ios.dart +++ b/lib/ios.dart @@ -1,20 +1,27 @@ +// ignore_for_file: public_member_api_docs + import 'dart:convert'; import 'dart:io'; +import 'package:flutter_launcher_icons/config/config.dart'; import 'package:flutter_launcher_icons/constants.dart'; import 'package:flutter_launcher_icons/custom_exceptions.dart'; -import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart'; import 'package:flutter_launcher_icons/utils.dart'; import 'package:image/image.dart'; /// File to handle the creation of icons for iOS platform class IosIconTemplate { + /// constructs an instance of [IosIconTemplate] IosIconTemplate({required this.size, required this.name}); + /// suffix of the icon name final String name; + + /// the size of the icon final int size; } +/// details of the ios icons which need to be generated List iosIcons = [ IosIconTemplate(name: '-20x20@1x', size: 20), IosIconTemplate(name: '-20x20@2x', size: 40), @@ -39,32 +46,29 @@ List iosIcons = [ IosIconTemplate(name: '-1024x1024@1x', size: 1024), ]; -void createIcons(FlutterLauncherIconsConfig config, String? flavor) { - // todo: support prefixPath +/// create the ios icons +void createIcons(Config config, String? flavor) { + // TODO(p-mazhnik): support prefixPath final String? filePath = config.getImagePathIOS(); if (filePath == null) { throw const InvalidConfigException(errorMissingImagePath); } // decodeImageFile shows error message if null // so can return here if image is null - final Image? image = decodeImage(File(filePath).readAsBytesSync()); + Image? image = decodeImage(File(filePath).readAsBytesSync()); if (image == null) { return; } - if (config.removeAlphaIOS) { - final backgroundColorHex = config.backgroundColorIOS.startsWith('#') ? config.backgroundColorIOS.substring(1) : config.backgroundColorIOS; - if (backgroundColorHex.length != 6) { - throw Exception('background_color_ios hex should be 6 characters long'); - } - final backgroundByte = int.parse(backgroundColorHex, radix: 16); - final data = image.data; - for (var i = 0; i < data.length; i++) { - data[i] = alphaBlendColors(backgroundByte, data[i]); - } - image.channels = Channels.rgb; - + if (config.removeAlphaIOS && image.hasAlpha) { + final backgroundColor = _getBackgroundColor(config); + final pixel = image.getPixel(0, 0); + do { + pixel.set(_alphaBlend(pixel, backgroundColor)); + } while (pixel.moveNext()); + + image = image.convert(numChannels: 3); } - if (image.channels == Channels.rgba) { + if (image.hasAlpha) { print( '\nWARNING: Icons with alpha channel are not allowed in the Apple App Store.\nSet "remove_alpha_ios: true" to remove it.\n', ); @@ -126,6 +130,7 @@ void saveNewIcons(IosIconTemplate template, Image image, String newIconName) { }); } +/// create resized icon image Image createResizedImage(IosIconTemplate template, Image image) { if (image.width >= template.size) { return copyResize( @@ -144,6 +149,7 @@ Image createResizedImage(IosIconTemplate template, Image image) { } } +/// Change the iOS launcher icon Future changeIosLauncherIcon(String iconName, String? flavor) async { final File iOSConfigFile = File(iosConfigFile); final List lines = await iOSConfigFile.readAsLines(); @@ -388,3 +394,34 @@ List> createImageList(String fileNamePrefix) { ]; return imageList; } + +Color _getBackgroundColor(Config config) { + final backgroundColorHex = config.backgroundColorIOS.startsWith('#') + ? config.backgroundColorIOS.substring(1) + : config.backgroundColorIOS; + if (backgroundColorHex.length != 6) { + throw Exception('background_color_ios hex should be 6 characters long'); + } + + final backgroundByte = int.parse(backgroundColorHex, radix: 16); + return = ColorRgba8( + (backgroundByte >> 16) & 0xff, + (backgroundByte >> 8) & 0xff, + (backgroundByte >> 0) & 0xff, + 0xff, + ); +} + +Color _alphaBlend(Color fg, Color bg) { + if (fg.a == 0) { + return bg; + } else { + final invAlpha = 0xff - fg.a; + return ColorRgba8( + (fg.g * fg.r + invAlpha * bg.g) ~/ 0xff, + (fg.a * fg.r + invAlpha * bg.a) ~/ 0xff, + (fg.b * fg.r + invAlpha * bg.b) ~/ 0xff, + 0xff, + ); + } +} diff --git a/lib/macos/macos_icon_generator.dart b/lib/macos/macos_icon_generator.dart index 7e954224ae..8968250ab8 100644 --- a/lib/macos/macos_icon_generator.dart +++ b/lib/macos/macos_icon_generator.dart @@ -65,11 +65,11 @@ class MacOSIconGenerator extends IconGenerator { if (macOSConfig.imagePath == null && context.config.imagePath == null) { context.logger ..verbose({ - 'flutter_icons.macos.image_path': macOSConfig.imagePath, - 'flutter_icons.image_path': context.config.imagePath, + 'flutter_launcher_icons.macos.image_path': macOSConfig.imagePath, + 'flutter_launcher_icons.image_path': context.config.imagePath, }) ..error( - 'Missing image_path. Either provide "flutter_icons.macos.image_path" or "flutter_icons.image_path"', + 'Missing image_path. Either provide "flutter_launcher_icons.macos.image_path" or "flutter_launcher_icons.image_path"', ); return false; diff --git a/lib/main.dart b/lib/main.dart index 1ac232b3a7..ef957ad565 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,12 +1,14 @@ +// ignore_for_file: public_member_api_docs + import 'dart:io'; import 'package:args/args.dart'; import 'package:flutter_launcher_icons/abs/icon_generator.dart'; import 'package:flutter_launcher_icons/android.dart' as android_launcher_icons; +import 'package:flutter_launcher_icons/config/config.dart'; import 'package:flutter_launcher_icons/constants.dart' as constants; import 'package:flutter_launcher_icons/constants.dart'; import 'package:flutter_launcher_icons/custom_exceptions.dart'; -import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart'; import 'package:flutter_launcher_icons/ios.dart' as ios_launcher_icons; import 'package:flutter_launcher_icons/logger.dart'; import 'package:flutter_launcher_icons/macos/macos_icon_generator.dart'; @@ -101,7 +103,7 @@ Future createIconsFromArguments(List arguments) async { for (String flavor in flavors) { print('\nFlavor: $flavor'); final flutterLauncherIconsConfigs = - FlutterLauncherIconsConfig.loadConfigFromFlavor(flavor, prefixPath); + Config.loadConfigFromFlavor(flavor, prefixPath); if (flutterLauncherIconsConfigs == null) { throw NoConfigFoundException( 'No configuration found for $flavor flavor.', @@ -124,7 +126,7 @@ Future createIconsFromArguments(List arguments) async { } Future createIconsFromConfig( - FlutterLauncherIconsConfig flutterConfigs, + Config flutterConfigs, FLILogger logger, String prefixPath, [ String? flavor, @@ -149,24 +151,30 @@ Future createIconsFromConfig( logger: logger, prefixPath: prefixPath, flavor: flavor, - platforms: (context) => [ - WebIconGenerator(context), - WindowsIconGenerator(context), - MacOSIconGenerator(context), - // todo: add other platforms - ], + platforms: (context) { + final platforms = []; + if (flutterConfigs.hasWebConfig) { + platforms.add(WebIconGenerator(context)); + } + if (flutterConfigs.hasWindowsConfig) { + platforms.add(WindowsIconGenerator(context)); + } + if (flutterConfigs.hasMacOSConfig) { + platforms.add(MacOSIconGenerator(context)); + } + return platforms; + }, ); } -FlutterLauncherIconsConfig? loadConfigFileFromArgResults( +Config? loadConfigFileFromArgResults( ArgResults argResults, ) { final String prefixPath = argResults[prefixOption]; - final flutterLauncherIconsConfigs = - FlutterLauncherIconsConfig.loadConfigFromPath( - argResults[fileOption], - prefixPath, - ) ?? - FlutterLauncherIconsConfig.loadConfigFromPubSpec(prefixPath); + final flutterLauncherIconsConfigs = Config.loadConfigFromPath( + argResults[fileOption], + prefixPath, + ) ?? + Config.loadConfigFromPubSpec(prefixPath); return flutterLauncherIconsConfigs; } diff --git a/lib/src/version.dart b/lib/src/version.dart index 884cfa9548..c7632752c7 100644 --- a/lib/src/version.dart +++ b/lib/src/version.dart @@ -1,2 +1,2 @@ // Generated code. Do not modify. -const packageVersion = '0.11.0'; +const packageVersion = '0.13.1'; diff --git a/lib/utils.dart b/lib/utils.dart index 98824815f6..8a35d88c45 100644 --- a/lib/utils.dart +++ b/lib/utils.dart @@ -1,3 +1,5 @@ +// ignore_for_file: public_member_api_docs + import 'dart:convert'; import 'dart:io'; diff --git a/lib/web/web_icon_generator.dart b/lib/web/web_icon_generator.dart index f3567e5d8e..ebc60694ed 100644 --- a/lib/web/web_icon_generator.dart +++ b/lib/web/web_icon_generator.dart @@ -75,7 +75,7 @@ class WebIconGenerator extends IconGenerator { ); _updateManifestFile(); - // todo: update index.html in web/index.html + // TODO(RatakondalaArun): update index.html in web/index.html // as we are using flutter default config we no need // to update index.html for now // _updateIndexFile(); @@ -138,14 +138,6 @@ class WebIconGenerator extends IconGenerator { } } - // void _updateIndexFile() { - // todo - // final indexFile = File(constants.webIndexFilePath); - // if (!indexFile.existsSync()) { - // throw FileNotFoundException(constants.webFaviconFilePath); - // } - // } - void _updateManifestFile() { final manifestFile = utils.createFileIfNotExist( path.join(context.prefixPath, constants.webManifestFilePath), diff --git a/lib/xml_templates.dart b/lib/xml_templates.dart index 0ece2e87b9..9f6282e148 100644 --- a/lib/xml_templates.dart +++ b/lib/xml_templates.dart @@ -1,3 +1,5 @@ +// ignore_for_file: public_member_api_docs + const String icLauncherXml = ''' diff --git a/pubspec.yaml b/pubspec.yaml index e4807ff690..f35f8462a8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,30 +1,29 @@ name: flutter_launcher_icons description: A package which simplifies the task of updating your Flutter app's launcher icon. -version: 0.11.0 +version: 0.13.1 maintainer: Mark O'Sullivan (@MarkOSullivan94) homepage: https://github.com/fluttercommunity/flutter_launcher_icons repository: https://github.com/fluttercommunity/flutter_launcher_icons/ issue_tracker: https://github.com/fluttercommunity/flutter_launcher_icons/issues dependencies: - args: ^2.2.0 - checked_yaml: ^2.0.1 - cli_util: ^0.3.5 - image: ^3.0.2 - json_annotation: ^4.5.0 - path: ^1.8.0 - yaml: ^3.1.0 + args: ^2.3.2 + checked_yaml: ^2.0.2 + cli_util: ^0.4.0 + image: ^4.0.15 + json_annotation: ^4.8.0 + path: ^1.8.2 + yaml: ^3.1.1 environment: - sdk: '>=2.13.0 <3.0.0' + sdk: '>=2.18.0 <3.0.0' dev_dependencies: # Needed by build_version - build_runner: ^2.2.0 - # allows us to get version number from pubspec yaml which we can pass to Sentry + build_runner: ^2.3.3 # https://pub.dev/packages/build_version build_version: ^2.1.1 - json_serializable: ^6.5.4 + json_serializable: ^6.6.1 mockito: ^5.3.2 - test: ^1.22.0 + test: ^1.23.1 test_descriptor: ^2.0.1 diff --git a/test/abs/icon_generator_test.dart b/test/abs/icon_generator_test.dart index c93f44a463..384ee1bffe 100644 --- a/test/abs/icon_generator_test.dart +++ b/test/abs/icon_generator_test.dart @@ -1,5 +1,5 @@ import 'package:flutter_launcher_icons/abs/icon_generator.dart'; -import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart'; +import 'package:flutter_launcher_icons/config/config.dart'; import 'package:flutter_launcher_icons/logger.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; @@ -9,16 +9,16 @@ import 'package:test_descriptor/test_descriptor.dart' as d; import 'icon_generator_test.mocks.dart'; -@GenerateMocks([FlutterLauncherIconsConfig, IconGenerator]) +@GenerateMocks([Config, IconGenerator]) void main() { group('#generateIconsFor', () { late String prefixPath; late FLILogger logger; late IconGenerator mockGenerator; - late FlutterLauncherIconsConfig mockFLIConfig; + late Config mockFLIConfig; setUp(() async { prefixPath = path.join(d.sandbox, 'fli_test'); - mockFLIConfig = MockFlutterLauncherIconsConfig(); + mockFLIConfig = MockConfig(); logger = FLILogger(false); mockGenerator = MockIconGenerator(); when(mockGenerator.platformName).thenReturn('Mock'); diff --git a/test/abs/icon_generator_test.mocks.dart b/test/abs/icon_generator_test.mocks.dart index 63a79ae815..adcbe83cf5 100644 --- a/test/abs/icon_generator_test.mocks.dart +++ b/test/abs/icon_generator_test.mocks.dart @@ -4,8 +4,7 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:flutter_launcher_icons/abs/icon_generator.dart' as _i2; -import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart' - as _i3; +import 'package:flutter_launcher_icons/config/config.dart' as _i3; import 'package:mockito/mockito.dart' as _i1; // ignore_for_file: type=lint @@ -30,12 +29,11 @@ class _FakeIconGeneratorContext_0 extends _i1.SmartFake ); } -/// A class which mocks [FlutterLauncherIconsConfig]. +/// A class which mocks [Config]. /// /// See the documentation for Mockito's code generation for more information. -class MockFlutterLauncherIconsConfig extends _i1.Mock - implements _i3.FlutterLauncherIconsConfig { - MockFlutterLauncherIconsConfig() { +class MockConfig extends _i1.Mock implements _i3.Config { + MockConfig() { _i1.throwOnMissingStub(this); } @@ -65,6 +63,21 @@ class MockFlutterLauncherIconsConfig extends _i1.Mock returnValue: false, ) as bool); @override + bool get hasWebConfig => (super.noSuchMethod( + Invocation.getter(#hasWebConfig), + returnValue: false, + ) as bool); + @override + bool get hasWindowsConfig => (super.noSuchMethod( + Invocation.getter(#hasWindowsConfig), + returnValue: false, + ) as bool); + @override + bool get hasMacOSConfig => (super.noSuchMethod( + Invocation.getter(#hasMacOSConfig), + returnValue: false, + ) as bool); + @override bool get isCustomAndroidFile => (super.noSuchMethod( Invocation.getter(#isCustomAndroidFile), returnValue: false, diff --git a/test/all_tests.dart b/test/all_tests.dart index 8867e8c645..ca1a98aaf8 100644 --- a/test/all_tests.dart +++ b/test/all_tests.dart @@ -2,7 +2,7 @@ import 'package:test/test.dart'; import 'abs/icon_generator_test.dart' as icon_generator_test; import 'android_test.dart' as android_test; -import 'flutter_launcher_icons_config_test.dart' as fli_config; +import 'config_test.dart' as fli_config; import 'macos/macos_icon_generator_test.dart' as macos_icons_gen_test; import 'macos/macos_icon_template_test.dart' as macos_template_test; import 'main_test.dart' as main_test; diff --git a/test/android_test.dart b/test/android_test.dart index 4e8e9bcdfb..c621998d0a 100644 --- a/test/android_test.dart +++ b/test/android_test.dart @@ -1,8 +1,8 @@ import 'dart:io'; import 'package:flutter_launcher_icons/android.dart' as android; +import 'package:flutter_launcher_icons/config/config.dart'; import 'package:flutter_launcher_icons/constants.dart'; -import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart'; import 'package:test/test.dart'; // unit tests for android.dart @@ -35,8 +35,7 @@ void main() { 'ios': true }; expect( - FlutterLauncherIconsConfig.fromJson(flutterIconsConfig) - .isCustomAndroidFile, + Config.fromJson(flutterIconsConfig).isCustomAndroidFile, isFalse, ); @@ -46,8 +45,7 @@ void main() { 'ios': true }; expect( - FlutterLauncherIconsConfig.fromJson(flutterIconsNewIconConfig) - .isCustomAndroidFile, + Config.fromJson(flutterIconsNewIconConfig).isCustomAndroidFile, isTrue, ); }); @@ -60,8 +58,7 @@ void main() { 'ios': true }; expect( - FlutterLauncherIconsConfig.fromJson(flutterIconsNewIconConfig) - .getImagePathAndroid(), + Config.fromJson(flutterIconsNewIconConfig).getImagePathAndroid(), equals('assets/images/icon-android.png'), ); }); diff --git a/test/config/test_pubspec.yaml b/test/config/test_pubspec.yaml index 7ae8605c59..54c988689a 100644 --- a/test/config/test_pubspec.yaml +++ b/test/config/test_pubspec.yaml @@ -3,7 +3,7 @@ dev_dependencies: flutter_launcher_icons: path: ../../ -flutter_icons: +flutter_launcher_icons: image_path: "assets/images/icon-710x599.png" android: true # can specify file name here e.g. "ic_launcher" ios: true # can specify file name here e.g. "My-Launcher-Icon" diff --git a/test/flutter_launcher_icons_config_test.dart b/test/config_test.dart similarity index 93% rename from test/flutter_launcher_icons_config_test.dart rename to test/config_test.dart index a65a7cfb46..acd8b1f8b8 100644 --- a/test/flutter_launcher_icons_config_test.dart +++ b/test/config_test.dart @@ -1,5 +1,5 @@ +import 'package:flutter_launcher_icons/config/config.dart'; import 'package:flutter_launcher_icons/custom_exceptions.dart'; -import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart'; import 'package:path/path.dart' as path; import 'package:test/test.dart'; import 'package:test_descriptor/test_descriptor.dart' as d; @@ -7,7 +7,7 @@ import 'package:test_descriptor/test_descriptor.dart' as d; import './templates.dart' as templates; void main() { - group('FlutterLauncherIconsConfig', () { + group('Config', () { late String prefixPath; setUpAll(() { prefixPath = path.join(d.sandbox, 'fli_test'); @@ -20,7 +20,7 @@ void main() { ]).create(); }); test('should return valid configs', () { - final configs = FlutterLauncherIconsConfig.loadConfigFromPath( + final configs = Config.loadConfigFromPath( 'flutter_launcher_icons.yaml', prefixPath, ); @@ -78,7 +78,7 @@ void main() { }); test('should return null when invalid filePath is given', () { - final configs = FlutterLauncherIconsConfig.loadConfigFromPath( + final configs = Config.loadConfigFromPath( 'file_that_dont_exist.yaml', prefixPath, ); @@ -87,7 +87,7 @@ void main() { test('should throw InvalidConfigException when config is invalid', () { expect( - () => FlutterLauncherIconsConfig.loadConfigFromPath( + () => Config.loadConfigFromPath( 'invalid_fli_config.yaml', prefixPath, ), @@ -98,8 +98,7 @@ void main() { group('#loadConfigFromTestPubSpec', () { test('should return valid configs', () { const String path = 'test/config/test_pubspec.yaml'; - final configs = - FlutterLauncherIconsConfig.loadConfigFromPath(path, '.'); + final configs = Config.loadConfigFromPath(path, '.'); expect(configs, isNotNull); const String imagePath = 'assets/images/icon-710x599.png'; expect(configs!.imagePath, equals(imagePath)); @@ -132,8 +131,7 @@ void main() { ]).create(); }); test('should return valid configs', () { - final configs = - FlutterLauncherIconsConfig.loadConfigFromPubSpec(prefixPath); + final configs = Config.loadConfigFromPubSpec(prefixPath); expect(configs, isNotNull); // android configs expect(configs!.android, isTrue); @@ -200,7 +198,7 @@ void main() { }); test('InvalidConfigException when config is invalid', () { expect( - () => FlutterLauncherIconsConfig.loadConfigFromPubSpec(prefixPath), + () => Config.loadConfigFromPubSpec(prefixPath), throwsA(isA()), ); }); @@ -216,7 +214,7 @@ void main() { ]).create(); }); test('should return valid config', () { - final configs = FlutterLauncherIconsConfig.loadConfigFromFlavor( + final configs = Config.loadConfigFromFlavor( 'development', prefixPath, ); diff --git a/test/macos/macos_icon_generator_test.dart b/test/macos/macos_icon_generator_test.dart index 15a79e8b06..9af9f65dc6 100644 --- a/test/macos/macos_icon_generator_test.dart +++ b/test/macos/macos_icon_generator_test.dart @@ -1,7 +1,8 @@ import 'dart:io'; import 'package:flutter_launcher_icons/abs/icon_generator.dart'; -import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart'; +import 'package:flutter_launcher_icons/config/config.dart'; +import 'package:flutter_launcher_icons/config/macos_config.dart'; import 'package:flutter_launcher_icons/logger.dart'; import 'package:flutter_launcher_icons/macos/macos_icon_generator.dart'; import 'package:mockito/annotations.dart'; @@ -13,18 +14,17 @@ import 'package:test_descriptor/test_descriptor.dart' as d; import '../templates.dart' as templates; @GenerateNiceMocks([ - MockSpec(), + MockSpec(), MockSpec(), MockSpec(), ]) - import 'macos_icon_generator_test.mocks.dart'; void main() { group('MacOSIconGenerator', () { late IconGeneratorContext context; late IconGenerator generator; - late FlutterLauncherIconsConfig mockConfig; + late Config mockConfig; late MacOSConfig mockMacOSConfig; late String prefixPath; late File testImageFile; @@ -38,7 +38,7 @@ void main() { }); setUp(() { prefixPath = path.join(d.sandbox, 'fli_test'); - mockConfig = MockFlutterLauncherIconsConfig(); + mockConfig = MockConfig(); mockMacOSConfig = MockMacOSConfig(); mockLogger = MockFLILogger(); context = IconGeneratorContext( @@ -115,7 +115,7 @@ void main() { group('MacOSIconGenerator end-to-end', () { late IconGeneratorContext context; late IconGenerator generator; - late FlutterLauncherIconsConfig config; + late Config config; late String prefixPath; final assetPath = path.join(Directory.current.path, 'test', 'assets'); @@ -130,7 +130,7 @@ void main() { d.file('app_icon.png', imageFile.readAsBytesSync()), ]).create(); prefixPath = path.join(d.sandbox, 'fli_test'); - config = FlutterLauncherIconsConfig.loadConfigFromPath( + config = Config.loadConfigFromPath( 'flutter_launcher_icons.yaml', prefixPath, )!; diff --git a/test/macos/macos_icon_generator_test.mocks.dart b/test/macos/macos_icon_generator_test.mocks.dart index aecb3b4c85..49de9a8f4a 100644 --- a/test/macos/macos_icon_generator_test.mocks.dart +++ b/test/macos/macos_icon_generator_test.mocks.dart @@ -4,9 +4,9 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:cli_util/cli_logging.dart' as _i2; -import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart' - as _i3; -import 'package:flutter_launcher_icons/logger.dart' as _i4; +import 'package:flutter_launcher_icons/config/config.dart' as _i3; +import 'package:flutter_launcher_icons/config/macos_config.dart' as _i4; +import 'package:flutter_launcher_icons/logger.dart' as _i5; import 'package:mockito/mockito.dart' as _i1; // ignore_for_file: type=lint @@ -40,11 +40,10 @@ class _FakeProgress_1 extends _i1.SmartFake implements _i2.Progress { ); } -/// A class which mocks [FlutterLauncherIconsConfig]. +/// A class which mocks [Config]. /// /// See the documentation for Mockito's code generation for more information. -class MockFlutterLauncherIconsConfig extends _i1.Mock - implements _i3.FlutterLauncherIconsConfig { +class MockConfig extends _i1.Mock implements _i3.Config { @override int get minSdkAndroid => (super.noSuchMethod( Invocation.getter(#minSdkAndroid), @@ -76,6 +75,24 @@ class MockFlutterLauncherIconsConfig extends _i1.Mock returnValueForMissingStub: false, ) as bool); @override + bool get hasWebConfig => (super.noSuchMethod( + Invocation.getter(#hasWebConfig), + returnValue: false, + returnValueForMissingStub: false, + ) as bool); + @override + bool get hasWindowsConfig => (super.noSuchMethod( + Invocation.getter(#hasWindowsConfig), + returnValue: false, + returnValueForMissingStub: false, + ) as bool); + @override + bool get hasMacOSConfig => (super.noSuchMethod( + Invocation.getter(#hasMacOSConfig), + returnValue: false, + returnValueForMissingStub: false, + ) as bool); + @override bool get isCustomAndroidFile => (super.noSuchMethod( Invocation.getter(#isCustomAndroidFile), returnValue: false, @@ -107,7 +124,7 @@ class MockFlutterLauncherIconsConfig extends _i1.Mock /// A class which mocks [MacOSConfig]. /// /// See the documentation for Mockito's code generation for more information. -class MockMacOSConfig extends _i1.Mock implements _i3.MacOSConfig { +class MockMacOSConfig extends _i1.Mock implements _i4.MacOSConfig { @override bool get generate => (super.noSuchMethod( Invocation.getter(#generate), @@ -128,7 +145,7 @@ class MockMacOSConfig extends _i1.Mock implements _i3.MacOSConfig { /// A class which mocks [FLILogger]. /// /// See the documentation for Mockito's code generation for more information. -class MockFLILogger extends _i1.Mock implements _i4.FLILogger { +class MockFLILogger extends _i1.Mock implements _i5.FLILogger { @override bool get isVerbose => (super.noSuchMethod( Invocation.getter(#isVerbose), diff --git a/test/main_test.dart b/test/main_test.dart index 4064d5c0c3..581cf8a565 100644 --- a/test/main_test.dart +++ b/test/main_test.dart @@ -2,7 +2,7 @@ import 'dart:io'; import 'package:args/args.dart'; import 'package:flutter_launcher_icons/android.dart' as android; -import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart'; +import 'package:flutter_launcher_icons/config/config.dart'; import 'package:flutter_launcher_icons/ios.dart' as ios; import 'package:flutter_launcher_icons/main.dart' show defaultConfigFile; import 'package:flutter_launcher_icons/main.dart' as main_dart; @@ -54,29 +54,28 @@ void main() { tearDown(() { Directory.current = currentDirectory; }); + test('default', () async { await setCurrentDirectory('default'); await File('flutter_launcher_icons.yaml').writeAsString(''' -flutter_icons: +flutter_launcher_icons: android: true ios: false '''); final ArgResults argResults = parser.parse([]); - final FlutterLauncherIconsConfig? config = - main_dart.loadConfigFileFromArgResults(argResults); + final Config? config = main_dart.loadConfigFileFromArgResults(argResults); expect(config, isNotNull); expect(config!.android, isTrue); }); test('default_use_pubspec', () async { await setCurrentDirectory('pubspec_only'); await File('pubspec.yaml').writeAsString(''' -flutter_icons: +flutter_launcher_icons: android: true ios: false '''); ArgResults argResults = parser.parse([]); - final FlutterLauncherIconsConfig? config = - main_dart.loadConfigFileFromArgResults(argResults); + final Config? config = main_dart.loadConfigFileFromArgResults(argResults); expect(config, isNotNull); expect(config!.ios, isFalse); @@ -88,14 +87,13 @@ flutter_icons: test('custom', () async { await setCurrentDirectory('custom'); await File('custom.yaml').writeAsString(''' -flutter_icons: +flutter_launcher_icons: android: true ios: true '''); // if no argument set, should fail ArgResults argResults = parser.parse(['-f', 'custom.yaml']); - final FlutterLauncherIconsConfig? config = - main_dart.loadConfigFileFromArgResults(argResults); + final Config? config = main_dart.loadConfigFileFromArgResults(argResults); expect(config, isNotNull); expect(config!.ios, isTrue); @@ -115,7 +113,7 @@ flutter_icons: 'android': true, 'ios': true }; - final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); + final config = Config.fromJson(flutterIconsConfig); expect( config.getImagePathAndroid(), equals('assets/images/icon-710x599.png'), @@ -126,8 +124,7 @@ flutter_icons: 'android': true, 'ios': true }; - final configAndroid = - FlutterLauncherIconsConfig.fromJson(flutterIconsConfigAndroid); + final configAndroid = Config.fromJson(flutterIconsConfigAndroid); expect( configAndroid.getImagePathAndroid(), equals('assets/images/icon-710x599.png'), @@ -139,8 +136,7 @@ flutter_icons: 'android': true, 'ios': true }; - final configBoth = - FlutterLauncherIconsConfig.fromJson(flutterIconsConfigBoth); + final configBoth = Config.fromJson(flutterIconsConfigBoth); expect( configBoth.getImagePathAndroid(), equals('assets/images/icon-android.png'), @@ -154,7 +150,7 @@ flutter_icons: 'android': true, 'ios': true }; - final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); + final config = Config.fromJson(flutterIconsConfig); expect(config.hasPlatformConfig, isTrue); }); @@ -162,7 +158,7 @@ flutter_icons: final Map flutterIconsConfig = { 'image_path': 'assets/images/icon-710x599.png' }; - final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); + final config = Config.fromJson(flutterIconsConfig); expect(config.hasPlatformConfig, isFalse); }); @@ -172,7 +168,7 @@ flutter_icons: 'android': false, 'ios': true }; - final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); + final config = Config.fromJson(flutterIconsConfig); expect(config.isNeedingNewAndroidIcon, isFalse); }); @@ -181,7 +177,7 @@ flutter_icons: 'image_path': 'assets/images/icon-710x599.png', 'ios': true }; - final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); + final config = Config.fromJson(flutterIconsConfig); expect(config.isNeedingNewAndroidIcon, isFalse); }); @@ -191,7 +187,7 @@ flutter_icons: 'android': true, 'ios': false }; - final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); + final config = Config.fromJson(flutterIconsConfig); expect(config.isNeedingNewIOSIcon, isFalse); }); @@ -200,7 +196,7 @@ flutter_icons: 'image_path': 'assets/images/icon-710x599.png', 'android': true }; - final config = FlutterLauncherIconsConfig.fromJson(flutterIconsConfig); + final config = Config.fromJson(flutterIconsConfig); expect(config.isNeedingNewIOSIcon, isFalse); }); } diff --git a/test/templates.dart b/test/templates.dart index 655e5b621b..aa1537a168 100644 --- a/test/templates.dart +++ b/test/templates.dart @@ -1,5 +1,5 @@ const fliConfigTemplate = r''' -flutter_icons: +flutter_launcher_icons: android: true ios: true image_path: "assets/images/icon-128x128.png" @@ -28,7 +28,7 @@ flutter_icons: const flavorFLIConfigTemplate = fliConfigTemplate; const fliWebConfig = r''' -flutter_icons: +flutter_launcher_icons: web: generate: true image_path: "app_icon.png" # filepath @@ -39,7 +39,7 @@ flutter_icons: '''; const fliWindowsConfig = r''' -flutter_icons: +flutter_launcher_icons: windows: generate: true image_path: "app_icon.png" @@ -47,7 +47,7 @@ flutter_icons: '''; const invalidfliConfigTemplate = r''' -# flutter_icons +# flutter_launcher_icons android: true ios: true image_path: "assets/images/icon-128x128.png" @@ -103,7 +103,7 @@ flutter: - asset: fonts/TrajanPro_Bold.ttf weight: 700 -flutter_icons: +flutter_launcher_icons: android: true ios: true image_path: "assets/images/icon-128x128.png" @@ -167,7 +167,7 @@ flutter: - asset: fonts/TrajanPro_Bold.ttf weight: 700 -flutter_icons: +flutter_launcher_icons: android: true invalid_indented_key_key ios: true diff --git a/test/web/web_icon_generator_test.dart b/test/web/web_icon_generator_test.dart index c3a2226586..6872ffa6a0 100644 --- a/test/web/web_icon_generator_test.dart +++ b/test/web/web_icon_generator_test.dart @@ -1,7 +1,7 @@ import 'dart:io'; import 'package:flutter_launcher_icons/abs/icon_generator.dart'; -import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart'; +import 'package:flutter_launcher_icons/config/config.dart'; import 'package:flutter_launcher_icons/logger.dart'; import 'package:flutter_launcher_icons/web/web_icon_generator.dart'; import 'package:path/path.dart' as path; @@ -14,7 +14,7 @@ void main() { group('WebIconGenerator', () { late IconGeneratorContext context; late IconGenerator generator; - late FlutterLauncherIconsConfig config; + late Config config; late String prefixPath; final assetPath = path.join(Directory.current.path, 'test', 'assets'); @@ -32,7 +32,7 @@ void main() { d.file('app_icon.png', imageFile.readAsBytesSync()), ]).create(); prefixPath = path.join(d.sandbox, 'fli_test'); - config = FlutterLauncherIconsConfig.loadConfigFromPath( + config = Config.loadConfigFromPath( 'flutter_launcher_icons.yaml', prefixPath, )!; diff --git a/test/windows/windows_icon_generator_test.dart b/test/windows/windows_icon_generator_test.dart index 8bc3c8c2ec..2aa520acdd 100644 --- a/test/windows/windows_icon_generator_test.dart +++ b/test/windows/windows_icon_generator_test.dart @@ -1,7 +1,8 @@ import 'dart:io'; import 'package:flutter_launcher_icons/abs/icon_generator.dart'; -import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart'; +import 'package:flutter_launcher_icons/config/config.dart'; +import 'package:flutter_launcher_icons/config/windows_config.dart'; import 'package:flutter_launcher_icons/logger.dart'; import 'package:flutter_launcher_icons/windows/windows_icon_generator.dart'; import 'package:mockito/annotations.dart'; @@ -13,12 +14,12 @@ import 'package:test_descriptor/test_descriptor.dart' as d; import '../templates.dart' as templates; import 'windows_icon_generator_test.mocks.dart'; -@GenerateMocks([FlutterLauncherIconsConfig, WindowsConfig, FLILogger]) +@GenerateMocks([Config, WindowsConfig, FLILogger]) void main() { group('WindowsIconGenerator', () { late IconGeneratorContext context; late IconGenerator generator; - late FlutterLauncherIconsConfig mockConfig; + late Config mockConfig; late WindowsConfig mockWindowsConfig; late String prefixPath; late File testImageFile; @@ -33,7 +34,7 @@ void main() { }); setUp(() async { prefixPath = path.join(d.sandbox, 'fli_test'); - mockConfig = MockFlutterLauncherIconsConfig(); + mockConfig = MockConfig(); mockWindowsConfig = MockWindowsConfig(); mockLogger = MockFLILogger(); context = IconGeneratorContext( @@ -122,7 +123,7 @@ void main() { group('WindowsIconGenerator end-to-end', () { late IconGeneratorContext context; late IconGenerator generator; - late FlutterLauncherIconsConfig config; + late Config config; late String prefixPath; final assetPath = path.join(Directory.current.path, 'test', 'assets'); @@ -136,7 +137,7 @@ void main() { d.file('app_icon.png', imageFile.readAsBytesSync()), ]).create(); prefixPath = path.join(d.sandbox, 'fli_test'); - config = FlutterLauncherIconsConfig.loadConfigFromPath( + config = Config.loadConfigFromPath( 'flutter_launcher_icons.yaml', prefixPath, )!; diff --git a/test/windows/windows_icon_generator_test.mocks.dart b/test/windows/windows_icon_generator_test.mocks.dart index 590c18d8dd..8c7a5d02b2 100644 --- a/test/windows/windows_icon_generator_test.mocks.dart +++ b/test/windows/windows_icon_generator_test.mocks.dart @@ -4,9 +4,9 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:cli_util/cli_logging.dart' as _i2; -import 'package:flutter_launcher_icons/flutter_launcher_icons_config.dart' - as _i3; -import 'package:flutter_launcher_icons/logger.dart' as _i4; +import 'package:flutter_launcher_icons/config/config.dart' as _i3; +import 'package:flutter_launcher_icons/config/windows_config.dart' as _i4; +import 'package:flutter_launcher_icons/logger.dart' as _i5; import 'package:mockito/mockito.dart' as _i1; // ignore_for_file: type=lint @@ -40,12 +40,11 @@ class _FakeProgress_1 extends _i1.SmartFake implements _i2.Progress { ); } -/// A class which mocks [FlutterLauncherIconsConfig]. +/// A class which mocks [Config]. /// /// See the documentation for Mockito's code generation for more information. -class MockFlutterLauncherIconsConfig extends _i1.Mock - implements _i3.FlutterLauncherIconsConfig { - MockFlutterLauncherIconsConfig() { +class MockConfig extends _i1.Mock implements _i3.Config { + MockConfig() { _i1.throwOnMissingStub(this); } @@ -75,6 +74,21 @@ class MockFlutterLauncherIconsConfig extends _i1.Mock returnValue: false, ) as bool); @override + bool get hasWebConfig => (super.noSuchMethod( + Invocation.getter(#hasWebConfig), + returnValue: false, + ) as bool); + @override + bool get hasWindowsConfig => (super.noSuchMethod( + Invocation.getter(#hasWindowsConfig), + returnValue: false, + ) as bool); + @override + bool get hasMacOSConfig => (super.noSuchMethod( + Invocation.getter(#hasMacOSConfig), + returnValue: false, + ) as bool); + @override bool get isCustomAndroidFile => (super.noSuchMethod( Invocation.getter(#isCustomAndroidFile), returnValue: false, @@ -102,7 +116,7 @@ class MockFlutterLauncherIconsConfig extends _i1.Mock /// A class which mocks [WindowsConfig]. /// /// See the documentation for Mockito's code generation for more information. -class MockWindowsConfig extends _i1.Mock implements _i3.WindowsConfig { +class MockWindowsConfig extends _i1.Mock implements _i4.WindowsConfig { MockWindowsConfig() { _i1.throwOnMissingStub(this); } @@ -125,7 +139,7 @@ class MockWindowsConfig extends _i1.Mock implements _i3.WindowsConfig { /// A class which mocks [FLILogger]. /// /// See the documentation for Mockito's code generation for more information. -class MockFLILogger extends _i1.Mock implements _i4.FLILogger { +class MockFLILogger extends _i1.Mock implements _i5.FLILogger { MockFLILogger() { _i1.throwOnMissingStub(this); } From 8769389cd5cba35234a949cbcc9a599fbaf1e239 Mon Sep 17 00:00:00 2001 From: Hao-Cher Hong Date: Fri, 5 May 2023 18:39:24 +0800 Subject: [PATCH 3/4] fix ios.dart error --- lib/ios.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ios.dart b/lib/ios.dart index f878f876cd..48c7f9227e 100644 --- a/lib/ios.dart +++ b/lib/ios.dart @@ -404,7 +404,7 @@ Color _getBackgroundColor(Config config) { } final backgroundByte = int.parse(backgroundColorHex, radix: 16); - return = ColorRgba8( + return ColorRgba8( (backgroundByte >> 16) & 0xff, (backgroundByte >> 8) & 0xff, (backgroundByte >> 0) & 0xff, From 0d2cc408853504b3dd819c093e60d5a7b5aaec18 Mon Sep 17 00:00:00 2001 From: Hao-Cher Hong Date: Fri, 5 May 2023 19:00:48 +0800 Subject: [PATCH 4/4] ensure color format --- lib/ios.dart | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/ios.dart b/lib/ios.dart index 48c7f9227e..1339de35e3 100644 --- a/lib/ios.dart +++ b/lib/ios.dart @@ -395,7 +395,7 @@ List> createImageList(String fileNamePrefix) { return imageList; } -Color _getBackgroundColor(Config config) { +ColorUint8 _getBackgroundColor(Config config) { final backgroundColorHex = config.backgroundColorIOS.startsWith('#') ? config.backgroundColorIOS.substring(1) : config.backgroundColorIOS; @@ -404,7 +404,7 @@ Color _getBackgroundColor(Config config) { } final backgroundByte = int.parse(backgroundColorHex, radix: 16); - return ColorRgba8( + return ColorUint8.rgba( (backgroundByte >> 16) & 0xff, (backgroundByte >> 8) & 0xff, (backgroundByte >> 0) & 0xff, @@ -412,15 +412,18 @@ Color _getBackgroundColor(Config config) { ); } -Color _alphaBlend(Color fg, Color bg) { +Color _alphaBlend(Color fg, ColorUint8 bg) { + if (fg.format != Format.uint8) { + fg = fg.convert(format: Format.uint8); + } if (fg.a == 0) { return bg; } else { final invAlpha = 0xff - fg.a; - return ColorRgba8( - (fg.g * fg.r + invAlpha * bg.g) ~/ 0xff, - (fg.a * fg.r + invAlpha * bg.a) ~/ 0xff, - (fg.b * fg.r + invAlpha * bg.b) ~/ 0xff, + return ColorUint8.rgba( + (fg.a * fg.r + invAlpha * bg.g) ~/ 0xff, + (fg.a * fg.g + invAlpha * bg.a) ~/ 0xff, + (fg.a * fg.b + invAlpha * bg.b) ~/ 0xff, 0xff, ); }