Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI Command that generates all flavors with single flag #752

Merged
merged 3 commits into from
Dec 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## [2.4.4] - ()

- Added the ability to generate all flavors with a single flag. Closes [#751](https://github.com/jonbhanson/flutter_native_splash/issues/751)

## [2.4.3] - (2024-Nov-17)

- Add Swift Package Manager support. Closes [#749](https://github.com/jonbhanson/flutter_native_splash/issues/749).
Expand Down
40 changes: 34 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,10 +194,20 @@ When the package finishes running, your splash screen is ready.

(Optionally), If you added your config to a separate YAML file instead of `pubspec.yaml`, just add --path with the command in the terminal:

```
```bash
dart run flutter_native_splash:create --path=path/to/my/file.yaml
```

| Command | Description |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| -h, --[no-]help | Show help |
| -p, --path | Path to the flutter project, if the project is not in it's default location. |
| -f, --flavor | Flavor to create the splash for. The flavor must match the pattern flutter_native_splash-*.yaml (where * is the flavor name). |
| -F, --flavors | Comma separated list of flavors to create the splash screens for. Match the pattern flutter_native_splash-*.yaml (where * is the flavor name). |
| -A, --[no-]all-flavors | Create the splash screens for all flavors that match the pattern flutter_native_splash-*.yaml (where * is the flavor name). |

> Note: Only one flavor option is allowed.

## 3. Set up app initialization (optional)

By default, the splash screen will be removed when Flutter has drawn the first frame. If you would like the splash screen to remain while your app initializes, you can use the `preserve()` and `remove()` methods together. Pass the `preserve()` method the value returned from `WidgetsFlutterBinding.ensureInitialized()` to keep the splash on screen. Later, when your app has initialized, make a call to `remove()` to remove the splash screen.
Expand Down Expand Up @@ -255,23 +265,23 @@ If you have a project setup that contains multiple flavors or environments, and

Instead of maintaining multiple files and copy/pasting images, you can now, using this tool, create different splash screens for different environments.

### Pre-requirements
## Pre-requirements

In order to use the new feature, and generate the desired splash images for you app, a couple of changes are required.
In order to use this feature, and generate the desired splash images for your app, a couple of changes are required.

If you want to generate just one flavor and one file you would use either options as described in Step 1. But in order to setup the flavors, you will then be required to move all your setup values to the `flutter_native_splash.yaml` file, but with a prefix.

Let's assume for the rest of the setup that you have 3 different flavors, `Production`, `Acceptance`, `Development`.

First this you will need to do is to create a different setup file for all 3 flavors with a suffix like so:
First thing you will need to do is to create a different setup file for all 3 flavors with a suffix like so:

```bash
flutter_native_splash-production.yaml
flutter_native_splash-acceptance.yaml
flutter_native_splash-development.yaml
```

You would setup those 3 files the same way as you would the one, but with different assets depending on which environment you would be generating. For example (Note: these are just examples, you can use whatever setup you need for your project that is already supported by the package):
You would setup those 3 files the same way as you would the one, but with different assets depending on which environment you would be generating. For example:

```yaml
# flutter_native_splash-development.yaml
Expand Down Expand Up @@ -328,6 +338,10 @@ flutter_native_splash:
web: false
```

> Note: these are just example values. You should substitute them with real values.

## One by one

If you'd like to generate only a single flavor (maybe you are
testing something out), you can use only the single command like this:

Expand All @@ -342,14 +356,28 @@ dart run flutter_native_splash:create --flavor acceptance
dart run flutter_native_splash:create --flavor development
```

## More than one

You also have the ability to specify all the flavors in one command
as shown bellow:

```bash
dart run flutter_native_splash:create --flavors development,staging,production
```

Note: the available flavors need to be comma separated for this option to work.
> Note: the available flavors need to be comma separated for this option to work.

## All flavors

And if you have many different flavors available in your project, and wish to generate the splash screen for all of them, you can use this command (starting from 2.4.4):

```bash
dart run flutter_native_splash:create --all-flavors
# OR you can use the shorthand option
dart run flutter_native_splash:create -A
```

This will take all files from the root of the project, scan through them and match for the pattern `flutter_native_splash-*.yaml` where the value at the place of the star will be used as the flavor name and will be consumed to generate the files.

### Android setup

Expand Down
89 changes: 76 additions & 13 deletions bin/create.dart
Original file line number Diff line number Diff line change
@@ -1,35 +1,98 @@
import 'dart:io';

import 'package:args/args.dart';
import 'package:flutter_native_splash/cli_commands.dart';
import 'package:flutter_native_splash/enums.dart';
import 'package:flutter_native_splash/helper_utils.dart';

void main(List<String> args) {
final parser = ArgParser();

parser.addOption('path');
parser.addOption('flavor');
parser.addOption('flavors');
parser
..addFlag(
ArgEnums.help.name,
abbr: ArgEnums.help.abbr,
help: 'Show help',
)
..addOption(
ArgEnums.path.name,
abbr: ArgEnums.path.abbr,
help:
'Path to the flutter project, if the project is not in it\'s default location.',
)
..addOption(
ArgEnums.flavor.name,
abbr: ArgEnums.flavor.abbr,
help:
'Flavor to create the splash for. The flavor must match the pattern flutter_native_splash-*.yaml (where * is the flavor name).',
)
..addOption(
ArgEnums.flavors.name,
abbr: ArgEnums.flavors.abbr,
help:
'Comma separated list of flavors to create the splash screens for. Match the pattern flutter_native_splash-*.yaml (where * is the flavor name).',
)
..addFlag(
ArgEnums.allFlavors.name,
abbr: ArgEnums.allFlavors.abbr,
help:
'Create the splash screens for all flavors that match the pattern flutter_native_splash-*.yaml (where * is the flavor name).',
);

final parsedArgs = parser.parse(args);

if (parsedArgs['flavor'] != null && parsedArgs['flavors'] != null) {
throw Exception('Cannot use both flavor and flavors arguments');
final helpArg = parsedArgs[ArgEnums.help.name] as bool?;

if (helpArg == true) {
print(parser.usage);
return;
}

if (parsedArgs['flavor'] != null) {
final pathArg = parsedArgs[ArgEnums.path.name]?.toString();
final flavorArg = parsedArgs[ArgEnums.flavor.name]?.toString();
final flavorsArg = parsedArgs[ArgEnums.flavors.name]?.toString();
final allFlavorsArg = parsedArgs[ArgEnums.allFlavors.name] as bool?;

// Validate the flavor arguments
HelperUtils.validateFlavorArgs(
flavorArg: flavorArg,
flavorsArg: flavorsArg,
allFlavorsArg: allFlavorsArg,
);

if (flavorArg != null) {
createSplash(
path: parsedArgs['path']?.toString(),
flavor: parsedArgs['flavor']?.toString(),
path: pathArg,
flavor: flavorArg,
);
} else if (parsedArgs['flavors'] != null) {
final flavors = parsedArgs['flavors']?.toString().split(',');
for (final flavor in flavors!) {
} else if (flavorsArg != null) {
for (final flavor in flavorsArg.split(',')) {
createSplash(
path: pathArg,
flavor: flavor,
);
}
} else if (allFlavorsArg == true) {
// Find all flavor configurations in current project directory
final flavors = Directory.current
.listSync()
.whereType<File>()
.map((entity) => entity.path.split(Platform.pathSeparator).last)
.where(HelperUtils.isValidFlavorConfigFileName)
.map(HelperUtils.getFlavorNameFromFileName)
.toList();

print('Found ${flavors.length} flavor configurations: $flavors');

for (final flavor in flavors) {
createSplash(
path: parsedArgs['path']?.toString(),
path: pathArg,
flavor: flavor,
);
}
} else {
createSplash(
path: parsedArgs['path']?.toString(),
path: pathArg,
flavor: null,
);
}
Expand Down
31 changes: 27 additions & 4 deletions bin/remove.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,39 @@
import 'package:args/args.dart';
import 'package:flutter_native_splash/cli_commands.dart';
import 'package:flutter_native_splash/enums.dart';

void main(List<String> args) {
final parser = ArgParser();

parser.addOption('path');
parser.addOption('flavor');
parser
..addFlag(
ArgEnums.help.name,
abbr: ArgEnums.help.abbr,
help: 'Show help',
)
..addOption(
ArgEnums.path.name,
abbr: ArgEnums.path.abbr,
help:
'Path to the flutter project, if the project is not in it\'s default location.',
)
..addOption(
ArgEnums.flavor.name,
abbr: ArgEnums.flavor.abbr,
help: 'Flavor to remove the splash for.',
);

final parsedArgs = parser.parse(args);

final helpArg = parsedArgs[ArgEnums.help.name];

if (helpArg != null) {
print(parser.usage);
return;
}

removeSplash(
path: parsedArgs['path']?.toString(),
flavor: parsedArgs['flavor']?.toString(),
path: parsedArgs[ArgEnums.path.name]?.toString(),
flavor: parsedArgs[ArgEnums.flavor.name]?.toString(),
);
}
1 change: 1 addition & 0 deletions example/ios/Flutter/Debug.xcconfig
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
1 change: 1 addition & 0 deletions example/ios/Flutter/Release.xcconfig
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
44 changes: 44 additions & 0 deletions example/ios/Podfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '12.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}

def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end

File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end

require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)

flutter_ios_podfile_setup

target 'Runner' do
use_frameworks!
use_modular_headers!

flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end

post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end
12 changes: 12 additions & 0 deletions lib/enums.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
enum ArgEnums {
help(name: 'help', abbr: 'h'),
path(name: 'path', abbr: 'p'),
flavor(name: 'flavor', abbr: 'f'),
flavors(name: 'flavors', abbr: 'F'),
allFlavors(name: 'all-flavors', abbr: 'A');

final String name;
final String abbr;

const ArgEnums({required this.name, required this.abbr});
}
46 changes: 46 additions & 0 deletions lib/helper_utils.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import 'package:flutter_native_splash/enums.dart';

class HelperUtils {
const HelperUtils._();

/// Checks if a given filename matches the flutter native splash flavor config pattern
/// The pattern is: flutter_native_splash-*.yaml where * is the flavor name
///
/// Returns true if the filename matches the pattern, false otherwise
static bool isValidFlavorConfigFileName(String fileName) {
return RegExp(r'^flutter_native_splash-[^-]+\.yaml$').hasMatch(fileName);
}

/// Extracts the flavor name from a valid flavor config filename
///
/// Throws an exception if the filename is not a valid flavor config filename
static String getFlavorNameFromFileName(String fileName) {
final flavorMatch =
RegExp(r'^flutter_native_splash-(.+)\.yaml$').firstMatch(fileName);

final flavorName = flavorMatch?.group(1);

if (flavorName == null) {
throw Exception('Invalid flavor config filename: $fileName');
}

return flavorName;
}

/// Validate the flavor arguments
///
/// Throws an exception if the arguments are invalid.
static void validateFlavorArgs({
required String? flavorArg,
required String? flavorsArg,
required bool? allFlavorsArg,
}) {
if ((flavorArg != null && flavorsArg != null) ||
(flavorArg != null && allFlavorsArg == true) ||
(flavorsArg != null && allFlavorsArg == true)) {
throw Exception(
'Cannot use multiple flavor options together. Please use only one of: --${ArgEnums.flavor.name}, --${ArgEnums.flavors.name}, or --${ArgEnums.allFlavors.name}.',
);
}
}
}
Loading