From c84e4e4ef407521bafba89501ede8c91a6846dee Mon Sep 17 00:00:00 2001 From: Angelo Cassano Date: Sun, 2 Jan 2022 22:34:22 +0100 Subject: [PATCH] Release 2.1.2 Fixes #69 and #36: define a custom set of variables for both Android and iOS for each flavor --- CHANGELOG.md | 7 +- README.md | 74 +++++++++++++++++- example/pubspec.lock | 6 +- lib/parser/models/enums.dart | 25 +++++++ lib/parser/models/flavorizr.dart | 2 +- lib/parser/models/flavorizr.g.dart | 2 +- lib/parser/models/flavors/android.dart | 5 ++ lib/parser/models/flavors/android.g.dart | 12 ++- .../models/flavors/android/res_value.dart | 20 +++++ .../models/flavors/android/res_value.g.dart | 19 +++++ lib/parser/models/flavors/ios.dart | 5 ++ lib/parser/models/flavors/ios.g.dart | 7 +- lib/parser/models/flavors/ios/enums.dart | 26 +++++++ lib/parser/models/flavors/ios/variable.dart | 46 ++++++++++++ lib/parser/models/flavors/ios/variable.g.dart | 25 +++++++ .../android_build_gradle_processor.dart | 21 +++++- .../ide/vscode/vscode_launch_processor.dart | 11 ++- .../ios_build_configurations_processor.dart | 11 ++- .../xcconfig/ios_xcconfig_file_processor.dart | 17 +++-- .../ios_xcconfig_mode_file_processor.dart | 16 ++-- .../ios/xcconfig/ios_xcconfig_processor.dart | 31 ++++++-- .../ios_xcconfig_targets_file_processor.dart | 10 ++- pubspec.yaml | 2 +- .../ios/xcconfig_processor_test.dart | 75 ++++++++++++++++++- .../build_expected.gradle | 2 + .../build_with_variables.gradle | 69 +++++++++++++++++ .../xcconfig_processor_test/matcher.xcconfig | 6 -- .../matcher_with_variables.xcconfig | 6 ++ ...matcher_with_variables_and_target.xcconfig | 7 ++ .../matcher_without_variables.xcconfig | 5 ++ test_resources/pubspec.yaml | 14 ++++ 31 files changed, 522 insertions(+), 62 deletions(-) create mode 100644 lib/parser/models/flavors/android/res_value.dart create mode 100644 lib/parser/models/flavors/android/res_value.g.dart create mode 100644 lib/parser/models/flavors/ios/enums.dart create mode 100644 lib/parser/models/flavors/ios/variable.dart create mode 100644 lib/parser/models/flavors/ios/variable.g.dart create mode 100644 test_resources/android/build_gradle_processor_test/build_with_variables.gradle delete mode 100644 test_resources/ios/xcconfig_processor_test/matcher.xcconfig create mode 100644 test_resources/ios/xcconfig_processor_test/matcher_with_variables.xcconfig create mode 100644 test_resources/ios/xcconfig_processor_test/matcher_with_variables_and_target.xcconfig create mode 100644 test_resources/ios/xcconfig_processor_test/matcher_without_variables.xcconfig diff --git a/CHANGELOG.md b/CHANGELOG.md index 559b84c..50eec6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ +## 2.1.2 +* Added resValues directive to declare resValues in build.gradle for each flavor (Android) +* Added variables directive to declare variables in xcconfig for each flavor (iOS) +* Bumped dependencies + ## 2.1.1 -* Added icon directive to generate icons for your flavors +* Added icon directive to generate icons for each flavor * Bumped dependencies ## 2.1.0 diff --git a/README.md b/README.md index bd13830..02bdb1e 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,9 @@ A flutter utility to easily create flavors in your flutter application ![Dart CI](https://github.com/AngeloAvv/flutter_flavorizr/workflows/Dart%20CI/badge.svg) [![Star on GitHub](https://img.shields.io/github/stars/AngeloAvv/flutter_flavorizr.svg?style=flat&logo=github&colorB=deeppink&label=stars)](https://github.com/AngeloAvv/flutter_flavorizr) [![License: MIT](https://img.shields.io/badge/license-MIT-purple.svg)](https://opensource.org/licenses/MIT) + +If you want to support this project, + [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/angeloavv) ## Getting Started @@ -41,7 +44,7 @@ in your [pubspec.yaml](https://dart.dev/tools/pub/pubspec): ``` dev_dependencies: - flutter_flavorizr: ^2.1.1 + flutter_flavorizr: ^2.1.2 ``` You can install packages from the command line: @@ -101,7 +104,7 @@ flavorizr: | app | Object | | true | An object describing the general capabilities of an app | | flavors | Array | | true | An array of items. Each of them describes a flavor configuration | | [instructions](#available-instructions) | Array | | false | An array of instructions to customize the flavorizr process | -| assetsUrl | String | https://github.com/AngeloAvv/flutter_flavorizr/releases/download/v2.1.1/assets.zip | false | A string containing the URL of the zip assets file. The default points to the current release | +| assetsUrl | String | https://github.com/AngeloAvv/flutter_flavorizr/releases/download/v2.1.2/assets.zip | false | A string containing the URL of the zip assets file. The default points to the current release | | ide | String | | false | The IDE in which the app is being developed. Currently only `vscode` or `idea` | ##### Available instructions @@ -155,6 +158,7 @@ flavorizr: |:--------------------|:-------|:--------|:---------|:-------------------------------------------------------------------| | applicationId | String | | true | The applicationId of the Android App | | firebase | Object | | false | An object which contains a Firebase configuration | +| resValues | Array | | false | An array which contains a set of resValues configurations | | generateDummyAssets | bool | true | false | True if you want to generate dummy assets (icon set, strings, etc) | | icon | String | | false | The icon path for this android flavor | @@ -165,6 +169,7 @@ flavorizr: | bundleId | String | | true | The bundleId of the iOS App | | buildSettings | Dictionary | {} | false | A flavor-specific XCode build configuration dictionary [XCode Build Settings](https://xcodebuildsettings.com) | | firebase | Object | | false | An object which contains a Firebase configuration | +| variables | Array | | false | An array which contains a set of variables configurations | | generateDummyAssets | bool | true | false | True if you want to generate dummy assets (xcassets, etc) | | icon | String | | false | The icon path for this iOS flavor | @@ -174,6 +179,71 @@ flavorizr: |:-------|:-------|:--------|:---------|:--------------------------------------------------------------------------------------------------------------------| | config | String | | false | The path to the Firebase configuration file (google-services.json for Android and GoogleService-Info.plist for iOS) | +#### resValue (for Android) + +| key | type | default | required | description | +|:------|:-------|:--------|:---------|:-----------------------------------------------------------------------------------------------------------------------------------------| +| type | String | | true | The type of the [resValue](https://developer.android.com/reference/tools/gradle-api/7.0/com/android/build/api/variant/ResValue) variable | +| value | String | | true | The value of the resValue variable | + +``` +flavorizr: + app: + android: + flavorDimensions: "flavor-type" + ios: + + flavors: + apple: + app: + name: "Apple App" + + android: + applicationId: "com.example.apple" + resValues: + variable_one: + type: "string" + value: "example variable one" + variable_two: + type: "string" + value: "example variable two" + + ios: + bundleId: "com.example.apple" +``` + +#### variable (for iOS) + +| key | type | default | required | description | +|:-------|:-------|:--------|:---------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| target | String | | false | The type of the [target](https://medium.com/geekculture/what-are-debug-and-release-modes-in-xcode-how-to-check-app-is-running-in-debug-mode-8dadad6a3428) (Debug, Release, Profile). Do not specify a target if you want to apply it to all of them. | +| value | String | | true | The value of the variable | + +``` +flavorizr: + app: + android: + flavorDimensions: "flavor-type" + ios: + + flavors: + apple: + app: + name: "Apple App" + + android: + applicationId: "com.example.apple" + + ios: + bundleId: "com.example.apple" + variables: + VARIABLE_ONE: + value: "variable1" + VARIABLE_TWO: + target: "Debug" + value: "variable2" +``` + ## Usage When you finished defining the flavorizr configuration, you can proceed by running the script with: diff --git a/example/pubspec.lock b/example/pubspec.lock index e40eed3..82ea019 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -28,7 +28,7 @@ packages: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.0" characters: dependency: transitive description: @@ -96,7 +96,7 @@ packages: path: ".." relative: true source: path - version: "2.1.1" + version: "2.1.2" flutter_test: dependency: "direct dev" description: flutter @@ -183,7 +183,7 @@ packages: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.0" string_scanner: dependency: transitive description: diff --git a/lib/parser/models/enums.dart b/lib/parser/models/enums.dart index f6802e9..f0c72fa 100644 --- a/lib/parser/models/enums.dart +++ b/lib/parser/models/enums.dart @@ -1 +1,26 @@ +/* + * Copyright (c) 2022 MyLittleSuite + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + enum IDE { idea, vscode } diff --git a/lib/parser/models/flavorizr.dart b/lib/parser/models/flavorizr.dart index c09b8fa..42f7d38 100644 --- a/lib/parser/models/flavorizr.dart +++ b/lib/parser/models/flavorizr.dart @@ -44,7 +44,7 @@ class Flavorizr { @JsonKey( defaultValue: - 'https://github.com/AngeloAvv/flutter_flavorizr/releases/download/v2.1.1/assets.zip') + 'https://github.com/AngeloAvv/flutter_flavorizr/releases/download/v2.1.2/assets.zip') final String assetsUrl; @JsonKey() diff --git a/lib/parser/models/flavorizr.g.dart b/lib/parser/models/flavorizr.g.dart index 513dbaa..6005a53 100644 --- a/lib/parser/models/flavorizr.g.dart +++ b/lib/parser/models/flavorizr.g.dart @@ -21,7 +21,7 @@ Flavorizr _$FlavorizrFromJson(Map json) { ?.map((e) => e as String) .toList(), assetsUrl: json['assetsUrl'] as String? ?? - 'https://github.com/AngeloAvv/flutter_flavorizr/releases/download/v2.1.1/assets.zip', + 'https://github.com/AngeloAvv/flutter_flavorizr/releases/download/v2.1.2/assets.zip', ide: $enumDecodeNullable(_$IDEEnumMap, json['ide']), ); } diff --git a/lib/parser/models/flavors/android.dart b/lib/parser/models/flavors/android.dart index 88311fa..90eed1c 100644 --- a/lib/parser/models/flavors/android.dart +++ b/lib/parser/models/flavors/android.dart @@ -23,6 +23,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +import 'package:flutter_flavorizr/parser/models/flavors/android/res_value.dart'; import 'package:flutter_flavorizr/parser/models/flavors/commons/os.dart'; import 'package:flutter_flavorizr/parser/models/flavors/google/firebase/firebase.dart'; import 'package:json_annotation/json_annotation.dart'; @@ -34,8 +35,12 @@ class Android extends OS { @JsonKey(required: true, disallowNullValue: true) final String applicationId; + @JsonKey(disallowNullValue: true, defaultValue: {}) + final Map resValues; + Android({ required this.applicationId, + this.resValues = const {}, bool generateDummyAssets = true, Firebase? firebase, String? icon, diff --git a/lib/parser/models/flavors/android.g.dart b/lib/parser/models/flavors/android.g.dart index 807df04..b038004 100644 --- a/lib/parser/models/flavors/android.g.dart +++ b/lib/parser/models/flavors/android.g.dart @@ -10,10 +10,20 @@ Android _$AndroidFromJson(Map json) { $checkKeys( json, requiredKeys: const ['applicationId'], - disallowNullValues: const ['firebase', 'icon', 'applicationId'], + disallowNullValues: const [ + 'firebase', + 'icon', + 'applicationId', + 'resValues' + ], ); return Android( applicationId: json['applicationId'] as String, + resValues: (json['resValues'] as Map?)?.map( + (k, e) => MapEntry(k as String, + ResValue.fromJson(Map.from(e as Map))), + ) ?? + {}, generateDummyAssets: json['generateDummyAssets'] as bool? ?? true, firebase: json['firebase'] == null ? null diff --git a/lib/parser/models/flavors/android/res_value.dart b/lib/parser/models/flavors/android/res_value.dart new file mode 100644 index 0000000..488d285 --- /dev/null +++ b/lib/parser/models/flavors/android/res_value.dart @@ -0,0 +1,20 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'res_value.g.dart'; + +@JsonSerializable(anyMap: true, createToJson: false) +class ResValue { + @JsonKey(required: true, disallowNullValue: true) + final String type; + + @JsonKey(required: true, disallowNullValue: true) + final String value; + + const ResValue({ + required this.type, + required this.value, + }); + + factory ResValue.fromJson(Map json) => + _$ResValueFromJson(json); +} diff --git a/lib/parser/models/flavors/android/res_value.g.dart b/lib/parser/models/flavors/android/res_value.g.dart new file mode 100644 index 0000000..34f5b7b --- /dev/null +++ b/lib/parser/models/flavors/android/res_value.g.dart @@ -0,0 +1,19 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'res_value.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ResValue _$ResValueFromJson(Map json) { + $checkKeys( + json, + requiredKeys: const ['type', 'value'], + disallowNullValues: const ['type', 'value'], + ); + return ResValue( + type: json['type'] as String, + value: json['value'] as String, + ); +} diff --git a/lib/parser/models/flavors/ios.dart b/lib/parser/models/flavors/ios.dart index cd5e5a4..fa1d68e 100644 --- a/lib/parser/models/flavors/ios.dart +++ b/lib/parser/models/flavors/ios.dart @@ -26,6 +26,7 @@ import 'package:flutter_flavorizr/parser/mixins/build_settings_mixin.dart'; import 'package:flutter_flavorizr/parser/models/flavors/commons/os.dart'; import 'package:flutter_flavorizr/parser/models/flavors/google/firebase/firebase.dart'; +import 'package:flutter_flavorizr/parser/models/flavors/ios/variable.dart'; import 'package:json_annotation/json_annotation.dart'; part 'ios.g.dart'; @@ -35,8 +36,12 @@ class IOS extends OS with BuildSettingsMixin { @JsonKey(required: true, disallowNullValue: true) final String bundleId; + @JsonKey(disallowNullValue: true, defaultValue: {}) + final Map variables; + IOS({ required this.bundleId, + this.variables = const {}, Map buildSettings = const {}, bool generateDummyAssets = true, Firebase? firebase, diff --git a/lib/parser/models/flavors/ios.g.dart b/lib/parser/models/flavors/ios.g.dart index 73e942c..7ab30d1 100644 --- a/lib/parser/models/flavors/ios.g.dart +++ b/lib/parser/models/flavors/ios.g.dart @@ -10,10 +10,15 @@ IOS _$IOSFromJson(Map json) { $checkKeys( json, requiredKeys: const ['bundleId'], - disallowNullValues: const ['firebase', 'icon', 'bundleId'], + disallowNullValues: const ['firebase', 'icon', 'bundleId', 'variables'], ); return IOS( bundleId: json['bundleId'] as String, + variables: (json['variables'] as Map?)?.map( + (k, e) => MapEntry(k as String, + Variable.fromJson(Map.from(e as Map))), + ) ?? + {}, buildSettings: (json['buildSettings'] as Map?)?.map( (k, e) => MapEntry(k as String, e), ) ?? diff --git a/lib/parser/models/flavors/ios/enums.dart b/lib/parser/models/flavors/ios/enums.dart new file mode 100644 index 0000000..e867137 --- /dev/null +++ b/lib/parser/models/flavors/ios/enums.dart @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022 MyLittleSuite + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +enum Target { Debug, Profile, Release } diff --git a/lib/parser/models/flavors/ios/variable.dart b/lib/parser/models/flavors/ios/variable.dart new file mode 100644 index 0000000..0c40636 --- /dev/null +++ b/lib/parser/models/flavors/ios/variable.dart @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022 MyLittleSuite + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +import 'package:flutter_flavorizr/parser/models/flavors/ios/enums.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'variable.g.dart'; + +@JsonSerializable(anyMap: true, createToJson: false) +class Variable { + @JsonKey(disallowNullValue: true) + final Target? target; + + @JsonKey(required: true, disallowNullValue: true) + final String value; + + const Variable({ + required this.value, + this.target, + }); + + factory Variable.fromJson(Map json) => + _$VariableFromJson(json); +} diff --git a/lib/parser/models/flavors/ios/variable.g.dart b/lib/parser/models/flavors/ios/variable.g.dart new file mode 100644 index 0000000..46fe8ec --- /dev/null +++ b/lib/parser/models/flavors/ios/variable.g.dart @@ -0,0 +1,25 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'variable.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +Variable _$VariableFromJson(Map json) { + $checkKeys( + json, + requiredKeys: const ['value'], + disallowNullValues: const ['target', 'value'], + ); + return Variable( + value: json['value'] as String, + target: $enumDecodeNullable(_$TargetEnumMap, json['target']), + ); +} + +const _$TargetEnumMap = { + Target.Debug: 'Debug', + Target.Profile: 'Profile', + Target.Release: 'Release', +}; diff --git a/lib/processors/android/android_build_gradle_processor.dart b/lib/processors/android/android_build_gradle_processor.dart index caeca48..8d76d89 100644 --- a/lib/processors/android/android_build_gradle_processor.dart +++ b/lib/processors/android/android_build_gradle_processor.dart @@ -23,10 +23,12 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +import 'dart:collection'; + import 'package:flutter_flavorizr/exception/existing_flavor_dimensions_exception.dart'; import 'package:flutter_flavorizr/exception/malformed_resource_exception.dart'; import 'package:flutter_flavorizr/parser/models/flavorizr.dart'; -import 'package:flutter_flavorizr/parser/models/flavors/flavor.dart'; +import 'package:flutter_flavorizr/parser/models/flavors/android/res_value.dart'; import 'package:flutter_flavorizr/processors/commons/string_processor.dart'; class AndroidBuildGradleProcessor extends StringProcessor { @@ -115,14 +117,25 @@ class AndroidBuildGradleProcessor extends StringProcessor { void _appendFlavors(StringBuffer buffer) { buffer.writeln(' productFlavors {'); - this.config.flavors.forEach((String name, Flavor flavor) { + this.config.flavors.forEach((name, flavor) { buffer.writeln(' $name {'); buffer.writeln( ' dimension "${this.config.app.android.flavorDimensions}"'); buffer.writeln( ' applicationId "${flavor.android.applicationId}"'); - buffer.writeln( - ' resValue "string", "app_name", "${flavor.app.name}"'); + + final Map resValues = LinkedHashMap.from({ + 'app_name': ResValue( + type: 'string', + value: flavor.app.name, + ) + }) + ..addAll(flavor.android.resValues); + resValues.forEach((key, res) { + buffer.writeln( + ' resValue "${res.type}", "$key", "${res.value}"'); + }); + buffer.writeln(' }'); }); diff --git a/lib/processors/ide/vscode/vscode_launch_processor.dart b/lib/processors/ide/vscode/vscode_launch_processor.dart index a3c633a..1605c01 100644 --- a/lib/processors/ide/vscode/vscode_launch_processor.dart +++ b/lib/processors/ide/vscode/vscode_launch_processor.dart @@ -24,13 +24,12 @@ */ import 'package:flutter_flavorizr/parser/models/flavorizr.dart'; +import 'package:flutter_flavorizr/parser/models/flavors/ios/enums.dart'; import 'package:flutter_flavorizr/processors/commons/string_processor.dart'; import 'package:flutter_flavorizr/processors/ide/vscode/models/configuration.dart'; import 'package:flutter_flavorizr/processors/ide/vscode/models/launch.dart'; class VSCodeLaunchProcessor extends StringProcessor { - static const List modes = ['Debug', 'Profile', 'Release']; - VSCodeLaunchProcessor({ required Flavorizr config, }) : super(config: config); @@ -40,10 +39,10 @@ class VSCodeLaunchProcessor extends StringProcessor { version: '0.2.0', configurations: config.flavors.keys .expand( - (flavorName) => modes.map( - (mode) => Configuration( - name: '$flavorName $mode', - flutterMode: mode.toLowerCase(), + (flavorName) => Target.values.map( + (target) => Configuration( + name: '$flavorName ${target.name}', + flutterMode: target.name.toLowerCase(), request: 'launch', type: 'dart', args: [ diff --git a/lib/processors/ios/build_configuration/ios_build_configurations_processor.dart b/lib/processors/ios/build_configuration/ios_build_configurations_processor.dart index 37b1c67..259734e 100644 --- a/lib/processors/ios/build_configuration/ios_build_configurations_processor.dart +++ b/lib/processors/ios/build_configuration/ios_build_configurations_processor.dart @@ -26,13 +26,12 @@ import 'dart:convert'; import 'package:flutter_flavorizr/parser/models/flavorizr.dart'; +import 'package:flutter_flavorizr/parser/models/flavors/ios/enums.dart'; import 'package:flutter_flavorizr/processors/commons/queue_processor.dart'; import 'package:flutter_flavorizr/processors/commons/shell_processor.dart'; import 'package:flutter_flavorizr/utils/ios_utils.dart' as IOSUtils; class IOSBuildConfigurationsProcessor extends QueueProcessor { - static const List _modes = ['Debug', 'Profile', 'Release']; - IOSBuildConfigurationsProcessor( String process, String script, @@ -43,16 +42,16 @@ class IOSBuildConfigurationsProcessor extends QueueProcessor { Map buildConfigurations, { required Flavorizr config, }) : super( - _modes.map( - (String mode) => ShellProcessor( + Target.values.map( + (target) => ShellProcessor( process, [ script, project, - IOSUtils.flatPath('$file/$flavorName$mode.xcconfig'), + IOSUtils.flatPath('$file/$flavorName${target.name}.xcconfig'), flavorName, bundleId, - mode, + target.name, base64.encode(utf8.encode(jsonEncode(buildConfigurations))), ], config: config, diff --git a/lib/processors/ios/xcconfig/ios_xcconfig_file_processor.dart b/lib/processors/ios/xcconfig/ios_xcconfig_file_processor.dart index e898567..adb1df3 100644 --- a/lib/processors/ios/xcconfig/ios_xcconfig_file_processor.dart +++ b/lib/processors/ios/xcconfig/ios_xcconfig_file_processor.dart @@ -24,29 +24,30 @@ */ import 'package:flutter_flavorizr/parser/models/flavorizr.dart'; +import 'package:flutter_flavorizr/parser/models/flavors/flavor.dart'; +import 'package:flutter_flavorizr/parser/models/flavors/ios/enums.dart'; import 'package:flutter_flavorizr/processors/commons/queue_processor.dart'; import 'package:flutter_flavorizr/processors/ios/xcconfig/ios_xcconfig_mode_file_processor.dart'; class IOSXCConfigFileProcessor extends QueueProcessor { - static const List _modes = ['Debug', 'Release']; - IOSXCConfigFileProcessor( String process, String script, String project, String path, - String appName, - String flavorName, { + String flavorName, + Flavor flavor, { required Flavorizr config, }) : super( - _modes.map( - (String mode) => IOSXCConfigModeFileProcessor( + Target.values.map( + (target) => IOSXCConfigModeFileProcessor( process, script, project, - '$path/$flavorName$mode.xcconfig', - appName, + path, flavorName, + flavor, + target, config: config, ), ), diff --git a/lib/processors/ios/xcconfig/ios_xcconfig_mode_file_processor.dart b/lib/processors/ios/xcconfig/ios_xcconfig_mode_file_processor.dart index baf1990..036e1ab 100644 --- a/lib/processors/ios/xcconfig/ios_xcconfig_mode_file_processor.dart +++ b/lib/processors/ios/xcconfig/ios_xcconfig_mode_file_processor.dart @@ -24,6 +24,8 @@ */ import 'package:flutter_flavorizr/parser/models/flavorizr.dart'; +import 'package:flutter_flavorizr/parser/models/flavors/flavor.dart'; +import 'package:flutter_flavorizr/parser/models/flavors/ios/enums.dart'; import 'package:flutter_flavorizr/processors/commons/new_file_string_processor.dart'; import 'package:flutter_flavorizr/processors/commons/queue_processor.dart'; import 'package:flutter_flavorizr/processors/commons/shell_processor.dart'; @@ -35,17 +37,19 @@ class IOSXCConfigModeFileProcessor extends QueueProcessor { String process, String script, String project, - String file, - String appName, - String flavorName, { + String path, + String flavorName, + Flavor flavor, + Target target, { required Flavorizr config, }) : super( [ NewFileStringProcessor( - file, + '$path/$flavorName${target.name}.xcconfig', IOSXCConfigProcessor( - appName, flavorName, + flavor, + target, config: config, ), config: config, @@ -55,7 +59,7 @@ class IOSXCConfigModeFileProcessor extends QueueProcessor { [ script, project, - IOSUtils.flatPath(file), + IOSUtils.flatPath('$path/$flavorName${target.name}.xcconfig'), 'Flutter', ], config: config, diff --git a/lib/processors/ios/xcconfig/ios_xcconfig_processor.dart b/lib/processors/ios/xcconfig/ios_xcconfig_processor.dart index 3e93312..09f63e1 100644 --- a/lib/processors/ios/xcconfig/ios_xcconfig_processor.dart +++ b/lib/processors/ios/xcconfig/ios_xcconfig_processor.dart @@ -23,16 +23,24 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +import 'dart:collection'; + +import 'package:flutter_flavorizr/extensions/extensions+map.dart'; import 'package:flutter_flavorizr/parser/models/flavorizr.dart'; +import 'package:flutter_flavorizr/parser/models/flavors/flavor.dart'; +import 'package:flutter_flavorizr/parser/models/flavors/ios/enums.dart'; +import 'package:flutter_flavorizr/parser/models/flavors/ios/variable.dart'; import 'package:flutter_flavorizr/processors/commons/string_processor.dart'; class IOSXCConfigProcessor extends StringProcessor { - final String _appName; final String _flavorName; + final Flavor _flavor; + final Target? _target; IOSXCConfigProcessor( - this._appName, - this._flavorName, { + this._flavorName, + this._flavor, + this._target, { String? input, required Flavorizr config, }) : super( @@ -55,11 +63,20 @@ class IOSXCConfigProcessor extends StringProcessor { } void _appendBody(StringBuffer buffer) { + final Map variables = LinkedHashMap.from({ + 'FLUTTER_TARGET': Variable(value: 'lib/main-$_flavorName.dart'), + 'ASSET_PREFIX': Variable(value: _flavorName), + 'BUNDLE_NAME': Variable(value: _flavor.app.name), + }) + ..addAll( + _flavor.ios.variables.where((_, variable) => + variable.target == null || variable.target == _target), + ); + buffer.writeln(); - buffer.writeln('FLUTTER_TARGET=lib/main-$_flavorName.dart'); - buffer.writeln(); - buffer.writeln('ASSET_PREFIX=$_flavorName'); - buffer.writeln('BUNDLE_NAME=$_appName'); + variables.forEach((key, variable) { + buffer.writeln('$key=${variable.value}'); + }); } @override diff --git a/lib/processors/ios/xcconfig/ios_xcconfig_targets_file_processor.dart b/lib/processors/ios/xcconfig/ios_xcconfig_targets_file_processor.dart index 8b691f7..edc70bc 100644 --- a/lib/processors/ios/xcconfig/ios_xcconfig_targets_file_processor.dart +++ b/lib/processors/ios/xcconfig/ios_xcconfig_targets_file_processor.dart @@ -24,7 +24,6 @@ */ import 'package:flutter_flavorizr/parser/models/flavorizr.dart'; -import 'package:flutter_flavorizr/parser/models/flavors/flavor.dart'; import 'package:flutter_flavorizr/processors/commons/queue_processor.dart'; import 'package:flutter_flavorizr/processors/ios/xcconfig/ios_xcconfig_file_processor.dart'; @@ -37,17 +36,20 @@ class IOSXCConfigTargetsFileProcessor extends QueueProcessor { required Flavorizr config, }) : super( config.flavors - .map((String flavorName, Flavor flavor) => MapEntry( + .map( + (flavorName, flavor) => MapEntry( flavorName, IOSXCConfigFileProcessor( process, script, project, path, - flavor.app.name, flavorName, + flavor, config: config, - ))) + ), + ), + ) .values, config: config, ); diff --git a/pubspec.yaml b/pubspec.yaml index 31c660f..29c7c47 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_flavorizr description: A flutter utility to easily create flavors in your flutter application -version: 2.1.1 +version: 2.1.2 repository: https://github.com/AngeloAvv/flutter_flavorizr issue_tracker: https://github.com/AngeloAvv/flutter_flavorizr/issues homepage: https://www.angelocassano.it diff --git a/test/processors/ios/xcconfig_processor_test.dart b/test/processors/ios/xcconfig_processor_test.dart index 3381592..83cca17 100644 --- a/test/processors/ios/xcconfig_processor_test.dart +++ b/test/processors/ios/xcconfig_processor_test.dart @@ -25,6 +25,7 @@ import 'dart:io'; +import 'package:flutter_flavorizr/parser/models/flavors/ios/enums.dart'; import 'package:flutter_flavorizr/parser/models/pubspec.dart'; import 'package:flutter_flavorizr/parser/parser.dart'; import 'package:flutter_flavorizr/processors/ios/xcconfig/ios_xcconfig_processor.dart'; @@ -47,12 +48,34 @@ void main() { tearDown(() {}); test('Test IOXCConfigProcessor', () { - String matcher = - File('test_resources/ios/xcconfig_processor_test/matcher.xcconfig') - .readAsStringSync(); + String matcher = File( + 'test_resources/ios/xcconfig_processor_test/matcher_without_variables.xcconfig') + .readAsStringSync(); + + final flavorName = pubspec!.flavorizr.flavors.keys.last; + final flavor = pubspec!.flavorizr.flavors[flavorName]; + + IOSXCConfigProcessor processor = IOSXCConfigProcessor( + flavorName, flavor!, null, + config: pubspec!.flavorizr); + String actual = processor.execute(); + + actual = TestUtils.stripEndOfLines(actual); + matcher = TestUtils.stripEndOfLines(matcher); + + expect(actual, matcher); + }); + + test('Test IOXCConfigProcessor with variables', () { + String matcher = File( + 'test_resources/ios/xcconfig_processor_test/matcher_with_variables.xcconfig') + .readAsStringSync(); + + final flavorName = pubspec!.flavorizr.flavors.keys.first; + final flavor = pubspec!.flavorizr.flavors[flavorName]; IOSXCConfigProcessor processor = IOSXCConfigProcessor( - 'Example App', 'example', + flavorName, flavor!, null, config: pubspec!.flavorizr); String actual = processor.execute(); @@ -61,4 +84,48 @@ void main() { expect(actual, matcher); }); + + test('Test IOXCConfigProcessor with variables', () { + String matcher = File( + 'test_resources/ios/xcconfig_processor_test/matcher_with_variables.xcconfig') + .readAsStringSync(); + + final flavorName = pubspec!.flavorizr.flavors.keys.first; + final flavor = pubspec!.flavorizr.flavors[flavorName]; + + IOSXCConfigProcessor processor = IOSXCConfigProcessor( + flavorName, + flavor!, + null, + config: pubspec!.flavorizr, + ); + String actual = processor.execute(); + + actual = TestUtils.stripEndOfLines(actual); + matcher = TestUtils.stripEndOfLines(matcher); + + expect(actual, matcher); + }); + + test('Test IOXCConfigProcessor with variables and target', () { + String matcher = File( + 'test_resources/ios/xcconfig_processor_test/matcher_with_variables_and_target.xcconfig') + .readAsStringSync(); + + final flavorName = pubspec!.flavorizr.flavors.keys.first; + final flavor = pubspec!.flavorizr.flavors[flavorName]; + + IOSXCConfigProcessor processor = IOSXCConfigProcessor( + flavorName, + flavor!, + Target.Debug, + config: pubspec!.flavorizr, + ); + String actual = processor.execute(); + + actual = TestUtils.stripEndOfLines(actual); + matcher = TestUtils.stripEndOfLines(matcher); + + expect(actual, matcher); + }); } diff --git a/test_resources/android/build_gradle_processor_test/build_expected.gradle b/test_resources/android/build_gradle_processor_test/build_expected.gradle index be4ecea..5d8807c 100644 --- a/test_resources/android/build_gradle_processor_test/build_expected.gradle +++ b/test_resources/android/build_gradle_processor_test/build_expected.gradle @@ -42,6 +42,8 @@ android { dimension "flavor-type" applicationId "com.example.banana" resValue "string", "app_name", "Banana App" + resValue "string", "variable_one", "test variable one" + resValue "string", "variable_two", "test variable two" } } // ----- END flavorDimensions (autogenerated by flutter_flavorizr) ----- diff --git a/test_resources/android/build_gradle_processor_test/build_with_variables.gradle b/test_resources/android/build_gradle_processor_test/build_with_variables.gradle new file mode 100644 index 0000000..51bf124 --- /dev/null +++ b/test_resources/android/build_gradle_processor_test/build_with_variables.gradle @@ -0,0 +1,69 @@ +package test_resources.android.build_gradle_processor_test + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 28 + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.mylittlesuite.flutterflavorizr_example" + minSdkVersion 16 + targetSdkVersion 28 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' +} diff --git a/test_resources/ios/xcconfig_processor_test/matcher.xcconfig b/test_resources/ios/xcconfig_processor_test/matcher.xcconfig deleted file mode 100644 index 0f57117..0000000 --- a/test_resources/ios/xcconfig_processor_test/matcher.xcconfig +++ /dev/null @@ -1,6 +0,0 @@ -#include "Generated.xcconfig" - -FLUTTER_TARGET=lib/main-example.dart - -ASSET_PREFIX=example -BUNDLE_NAME=Example App diff --git a/test_resources/ios/xcconfig_processor_test/matcher_with_variables.xcconfig b/test_resources/ios/xcconfig_processor_test/matcher_with_variables.xcconfig new file mode 100644 index 0000000..3d61a0f --- /dev/null +++ b/test_resources/ios/xcconfig_processor_test/matcher_with_variables.xcconfig @@ -0,0 +1,6 @@ +#include "Generated.xcconfig" + +FLUTTER_TARGET=lib/main-apple.dart +ASSET_PREFIX=apple +BUNDLE_NAME=Apple App +VARIABLE_ONE=variable1 diff --git a/test_resources/ios/xcconfig_processor_test/matcher_with_variables_and_target.xcconfig b/test_resources/ios/xcconfig_processor_test/matcher_with_variables_and_target.xcconfig new file mode 100644 index 0000000..f712dff --- /dev/null +++ b/test_resources/ios/xcconfig_processor_test/matcher_with_variables_and_target.xcconfig @@ -0,0 +1,7 @@ +#include "Generated.xcconfig" + +FLUTTER_TARGET=lib/main-apple.dart +ASSET_PREFIX=apple +BUNDLE_NAME=Apple App +VARIABLE_ONE=variable1 +VARIABLE_TWO=variable2 diff --git a/test_resources/ios/xcconfig_processor_test/matcher_without_variables.xcconfig b/test_resources/ios/xcconfig_processor_test/matcher_without_variables.xcconfig new file mode 100644 index 0000000..33ced77 --- /dev/null +++ b/test_resources/ios/xcconfig_processor_test/matcher_without_variables.xcconfig @@ -0,0 +1,5 @@ +#include "Generated.xcconfig" + +FLUTTER_TARGET=lib/main-banana.dart +ASSET_PREFIX=banana +BUNDLE_NAME=Banana App diff --git a/test_resources/pubspec.yaml b/test_resources/pubspec.yaml index a5eeeff..98fb577 100644 --- a/test_resources/pubspec.yaml +++ b/test_resources/pubspec.yaml @@ -37,6 +37,12 @@ flavorizr: ios: bundleId: "com.example.apple" + variables: + VARIABLE_ONE: + value: "variable1" + VARIABLE_TWO: + target: "Debug" + value: "variable2" banana: app: @@ -44,6 +50,14 @@ flavorizr: android: applicationId: "com.example.banana" + resValues: + variable_one: + type: "string" + value: "test variable one" + variable_two: + type: "string" + value: "test variable two" + ios: bundleId: "com.example.banana"