├── lib ├── app_starter.dart └── src │ ├── logger.dart │ ├── utils.dart │ ├── models │ └── app_model.dart │ └── command_runner.dart ├── example ├── lib │ ├── core │ │ ├── core.dart │ │ └── config │ │ │ ├── flavor.dart │ │ │ ├── config.dart │ │ │ └── config_manager.dart │ ├── app.dart │ ├── main-dev.dart │ ├── main-prod.dart │ └── template_home.dart ├── ios │ ├── Flutter │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── AppFrameworkInfo.plist │ ├── Runner │ │ ├── Runner-Bridging-Header.h │ │ ├── Assets.xcassets │ │ │ ├── LaunchImage.imageset │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ ├── README.md │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ │ └── Contents.json │ │ ├── AppDelegate.swift │ │ ├── Base.lproj │ │ │ ├── Main.storyboard │ │ │ └── LaunchScreen.storyboard │ │ └── Info.plist │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── xcshareddata │ │ │ └── xcschemes │ │ │ │ └── Runner.xcscheme │ │ └── project.pbxproj │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ └── IDEWorkspaceChecks.plist │ └── .gitignore ├── macos │ ├── Flutter │ │ ├── Flutter-Debug.xcconfig │ │ ├── Flutter-Release.xcconfig │ │ └── GeneratedPluginRegistrant.swift │ ├── Runner │ │ ├── Configs │ │ │ ├── Debug.xcconfig │ │ │ ├── Release.xcconfig │ │ │ ├── Warnings.xcconfig │ │ │ └── AppInfo.xcconfig │ │ ├── Assets.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ ├── app_icon_16.png │ │ │ │ ├── app_icon_32.png │ │ │ │ ├── app_icon_64.png │ │ │ │ ├── app_icon_1024.png │ │ │ │ ├── app_icon_128.png │ │ │ │ ├── app_icon_256.png │ │ │ │ ├── app_icon_512.png │ │ │ │ └── Contents.json │ │ ├── AppDelegate.swift │ │ ├── Release.entitlements │ │ ├── DebugProfile.entitlements │ │ ├── MainFlutterWindow.swift │ │ ├── Info.plist │ │ └── Base.lproj │ │ │ └── MainMenu.xib │ ├── .gitignore │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── xcshareddata │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ │ └── project.pbxproj ├── web │ ├── favicon.png │ ├── icons │ │ ├── Icon-192.png │ │ └── Icon-512.png │ ├── manifest.json │ └── index.html ├── android │ ├── gradle.properties │ ├── app │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── drawable │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ ├── drawable-v21 │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ ├── values │ │ │ │ │ │ └── styles.xml │ │ │ │ │ └── values-night │ │ │ │ │ │ └── styles.xml │ │ │ │ ├── kotlin │ │ │ │ │ └── com │ │ │ │ │ │ └── example │ │ │ │ │ │ └── example │ │ │ │ │ │ └── MainActivity.kt │ │ │ │ └── AndroidManifest.xml │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ └── profile │ │ │ │ └── AndroidManifest.xml │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── .gitignore │ ├── settings.gradle │ └── build.gradle ├── .metadata ├── README.md ├── .gitignore ├── pubspec.yaml └── pubspec.lock ├── bin └── app_starter.dart ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── .gitignore ├── pubspec.yaml ├── pubspec.lock └── README.md /lib/app_starter.dart: -------------------------------------------------------------------------------- 1 | export 'src/command_runner.dart'; 2 | -------------------------------------------------------------------------------- /example/lib/core/core.dart: -------------------------------------------------------------------------------- 1 | export 'config/config.dart'; 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/lib/core/config/flavor.dart: -------------------------------------------------------------------------------- 1 | enum Flavor { 2 | dev, 3 | prod, 4 | } 5 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/lib/core/config/config.dart: -------------------------------------------------------------------------------- 1 | export 'config_manager.dart'; 2 | export 'flavor.dart'; 3 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/web/favicon.png -------------------------------------------------------------------------------- /example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/xcuserdata/ 7 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /bin/app_starter.dart: -------------------------------------------------------------------------------- 1 | import 'package:app_starter/app_starter.dart'; 2 | 3 | /// Root of the executable 4 | void main(List arguments) { 5 | CommandRunner().create(arguments); 6 | } 7 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasEcalle/app_starter/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/example/example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | 9 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 10 | } 11 | -------------------------------------------------------------------------------- /example/macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @NSApplicationMain 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip 7 | -------------------------------------------------------------------------------- /example/macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/lib/app.dart: -------------------------------------------------------------------------------- 1 | import 'package:example/template_home.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class App extends StatelessWidget { 5 | @override 6 | Widget build(BuildContext context) { 7 | return MaterialApp( 8 | home: TemplateHome(), 9 | ); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /example/lib/main-dev.dart: -------------------------------------------------------------------------------- 1 | import 'package:example/app.dart'; 2 | import 'package:example/core/core.dart'; 3 | import 'package:flutter/cupertino.dart'; 4 | 5 | void main() { 6 | runApp(ConfigManager( 7 | apiBaseUrl: "dev_api_base_url", 8 | flavor: Flavor.dev, 9 | child: App(), 10 | )); 11 | } 12 | -------------------------------------------------------------------------------- /example/lib/main-prod.dart: -------------------------------------------------------------------------------- 1 | import 'package:example/app.dart'; 2 | import 'package:example/core/core.dart'; 3 | import 'package:flutter/cupertino.dart'; 4 | 5 | void main() { 6 | runApp(ConfigManager( 7 | apiBaseUrl: "prod_api_base_url", 8 | flavor: Flavor.prod, 9 | child: App(), 10 | )); 11 | } 12 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: c5a4b4029c0798f37c4a39b479d7cb75daa7b05c 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 8962f6dc68ec8e2206ac2fa874da4a453856c7d3 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController.init() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/lib/template_home.dart: -------------------------------------------------------------------------------- 1 | import 'package:example/core/core.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class TemplateHome extends StatelessWidget { 5 | @override 6 | Widget build(BuildContext context) { 7 | return Scaffold( 8 | body: Center( 9 | child: Column( 10 | mainAxisAlignment: MainAxisAlignment.center, 11 | children: [ 12 | Text("Hello from Flappy Template"), 13 | Text(ConfigManager.of(context).apiBaseUrl), 14 | ], 15 | ), 16 | ), 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "short_name": "example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = example 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2021 com.example. All rights reserved. 15 | -------------------------------------------------------------------------------- /example/lib/core/config/config_manager.dart: -------------------------------------------------------------------------------- 1 | import 'package:example/core/config/flavor.dart'; 2 | import 'package:flutter/cupertino.dart'; 3 | 4 | class ConfigManager extends InheritedWidget { 5 | ConfigManager({ 6 | Key key, 7 | @required Widget child, 8 | this.apiBaseUrl, 9 | this.flavor, 10 | }) : super(key: key, child: child); 11 | 12 | final String apiBaseUrl; 13 | final Flavor flavor; 14 | 15 | static ConfigManager of(BuildContext context) { 16 | return context.dependOnInheritedWidgetOfExactType(aspect: ConfigManager); 17 | } 18 | 19 | @override 20 | bool updateShouldNotify(ConfigManager oldWidget) => 21 | oldWidget.apiBaseUrl != apiBaseUrl; 22 | } 23 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /lib/src/logger.dart: -------------------------------------------------------------------------------- 1 | /// Simple Logging class 2 | class Logger { 3 | /// Simple info log 4 | static void logInfo(String message, {bool lineBreak = false}) { 5 | if (lineBreak) { 6 | print("\n[INFO] $message"); 7 | } else { 8 | print("[INFO] $message"); 9 | } 10 | } 11 | 12 | /// Simple warning log 13 | static void logWarning(String message) { 14 | print("[WARNING] $message"); 15 | } 16 | 17 | /// Simple error log 18 | static void logError(String message) { 19 | print("[ERROR] $message"); 20 | } 21 | 22 | /// Log configuration key/value pair 23 | static void logConfigKeyValue(String key, String? value) { 24 | print("[CONFIG] $key = $value"); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/src/utils.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | /// Simple Utils class 4 | class Utils { 5 | /// A valid Dart identifier that can be used for a package, i.e. no 6 | /// capital letters. 7 | /// https://dart.dev/guides/language/language-tour#important-concepts 8 | static final RegExp identifierRegExp = RegExp("[a-z_][a-z0-9_]*"); 9 | 10 | /// Name of the config file used to store information 11 | static const String configFileName = ".app_starter_config"; 12 | 13 | /// Return the config file 14 | static File getConfigFile() { 15 | final envVarMap = Platform.environment; 16 | final String home = envVarMap["HOME"] ?? ""; 17 | 18 | return File("$home/${Utils.configFileName}"); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.1.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.0.1] - Initial version 2 | 3 | First release ! 4 | 5 | ## [0.0.2] - Documentation fixes version 6 | 7 | Just some documentation fixes 8 | 9 | ## [0.0.3] - Fix dependencies versions 10 | 11 | Lower dependencies versions needed and remove flutter sdk dependency 12 | 13 | ## [0.0.4] - Fix dart executable 14 | 15 | Add missing executable and fix some Readme issues 16 | 17 | ## [1.0.0] - First usable version 18 | 19 | * Add storable configuration values 20 | * Add configuration displaying command 21 | * Add help displaying command 22 | * Add better documentation in Readme 23 | 24 | ## [1.0.0+1] - Readme update 25 | 26 | * Just fix Readme table format 27 | 28 | ## [1.0.0+2] - Readme update 29 | 30 | * Trying to fix pub.dev markdown table format -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 Thomas Ecalle https://www.groupe-cyllene.com/ 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /example/macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | example 30 | 31 | 32 | 33 | 36 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | build/ 32 | 33 | # Android related 34 | **/android/**/gradle-wrapper.jar 35 | **/android/.gradle 36 | **/android/captures/ 37 | **/android/gradlew 38 | **/android/gradlew.bat 39 | **/android/local.properties 40 | **/android/**/GeneratedPluginRegistrant.java 41 | 42 | # iOS/XCode related 43 | **/ios/**/*.mode1v3 44 | **/ios/**/*.mode2v3 45 | **/ios/**/*.moved-aside 46 | **/ios/**/*.pbxuser 47 | **/ios/**/*.perspectivev3 48 | **/ios/**/*sync/ 49 | **/ios/**/.sconsign.dblite 50 | **/ios/**/.tags* 51 | **/ios/**/.vagrant/ 52 | **/ios/**/DerivedData/ 53 | **/ios/**/Icon? 54 | **/ios/**/Pods/ 55 | **/ios/**/.symlinks/ 56 | **/ios/**/profile 57 | **/ios/**/xcuserdata 58 | **/ios/.generated/ 59 | **/ios/Flutter/App.framework 60 | **/ios/Flutter/Flutter.framework 61 | **/ios/Flutter/Flutter.podspec 62 | **/ios/Flutter/Generated.xcconfig 63 | **/ios/Flutter/app.flx 64 | **/ios/Flutter/app.zip 65 | **/ios/Flutter/flutter_assets/ 66 | **/ios/Flutter/flutter_export_environment.sh 67 | **/ios/ServiceDefinitions.json 68 | **/ios/Runner/GeneratedPluginRegistrant.* 69 | 70 | # Exceptions to above rules. 71 | !**/ios/**/default.mode1v3 72 | !**/ios/**/default.mode2v3 73 | !**/ios/**/default.pbxuser 74 | !**/ios/**/default.perspectivev3 75 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: app_starter 2 | description: A simple dart package to start any flutter application based on a model git repository 3 | version: 1.0.0+2 4 | homepage: https://github.com/ThomasEcalle/app_starter 5 | 6 | environment: 7 | sdk: ">=2.12.0 <3.0.0" 8 | 9 | dependencies: 10 | yaml: ^3.1.0 11 | args: ^2.0.0 12 | 13 | dev_dependencies: 14 | flutter_test: 15 | sdk: flutter 16 | 17 | executables: 18 | app_starter: 19 | 20 | # For information on the generic Dart part of this file, see the 21 | # following page: https://dart.dev/tools/pub/pubspec 22 | 23 | # The following section is specific to Flutter. 24 | flutter: 25 | 26 | # To add assets to your package, add an assets section, like this: 27 | # assets: 28 | # - images/a_dot_burr.jpeg 29 | # - images/a_dot_ham.jpeg 30 | # 31 | # For details regarding assets in packages, see 32 | # https://flutter.dev/assets-and-images/#from-packages 33 | # 34 | # An image asset can refer to one or more resolution-specific "variants", see 35 | # https://flutter.dev/assets-and-images/#resolution-aware. 36 | 37 | # To add custom fonts to your package, add a fonts section here, 38 | # in this "flutter" section. Each entry in this list should have a 39 | # "family" key with the font family name, and a "fonts" key with a 40 | # list giving the asset and other descriptors for the font. For 41 | # example: 42 | # fonts: 43 | # - family: Schyler 44 | # fonts: 45 | # - asset: fonts/Schyler-Regular.ttf 46 | # - asset: fonts/Schyler-Italic.ttf 47 | # style: italic 48 | # - family: Trajan Pro 49 | # fonts: 50 | # - asset: fonts/TrajanPro.ttf 51 | # - asset: fonts/TrajanPro_Bold.ttf 52 | # weight: 700 53 | # 54 | # For details regarding fonts in packages, see 55 | # https://flutter.dev/custom-fonts/#from-packages 56 | -------------------------------------------------------------------------------- /lib/src/models/app_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io'; 3 | 4 | import 'package:app_starter/src/utils.dart'; 5 | 6 | /// Model representing app information 7 | class AppModel { 8 | final String? name; 9 | final String? organization; 10 | final String? templateRepository; 11 | 12 | AppModel({ 13 | required this.name, 14 | required this.organization, 15 | required this.templateRepository, 16 | }); 17 | 18 | /// Generate AppModel instance from configuration file 19 | factory AppModel.fromConfigFile() { 20 | final File configFile = Utils.getConfigFile(); 21 | if (configFile.existsSync()) { 22 | final Map json = 23 | jsonDecode(configFile.readAsStringSync()); 24 | return AppModel( 25 | name: json["name"], 26 | organization: json["organization"], 27 | templateRepository: json["template"], 28 | ); 29 | } 30 | 31 | return AppModel(name: null, organization: null, templateRepository: null); 32 | } 33 | 34 | /// Write information in config file 35 | void writeInConfigFile() { 36 | final String jsonText = _toJsonText(); 37 | final File configFile = Utils.getConfigFile(); 38 | configFile.writeAsStringSync(jsonText, mode: FileMode.write); 39 | } 40 | 41 | /// Return if package identifier is a valid one or not, base on dart specifications 42 | bool hasValidPackageName() { 43 | if (name != null) { 44 | final match = Utils.identifierRegExp.matchAsPrefix(name!); 45 | return match != null && match.end == name!.length; 46 | } 47 | return false; 48 | } 49 | 50 | /// Returns Json-String formatted AppModel 51 | String _toJsonText() { 52 | final map = { 53 | "name": name, 54 | "organization": organization, 55 | "template": templateRepository, 56 | }; 57 | 58 | return jsonEncode(map); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 30 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | defaultConfig { 36 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 37 | applicationId "com.example.example" 38 | minSdkVersion 16 39 | targetSdkVersion 30 40 | versionCode flutterVersionCode.toInteger() 41 | versionName flutterVersionName 42 | } 43 | 44 | buildTypes { 45 | release { 46 | // TODO: Add your own signing config for the release build. 47 | // Signing with the debug keys for now, so `flutter run --release` works. 48 | signingConfig signingConfigs.debug 49 | } 50 | } 51 | } 52 | 53 | flutter { 54 | source '../..' 55 | } 56 | 57 | dependencies { 58 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 59 | } 60 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 13 | 17 | 21 | 26 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 64 | 65 | 71 | 73 | 79 | 80 | 81 | 82 | 84 | 85 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: example 2 | description: A new Flutter project. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | # The following defines the version and build number for your application. 9 | # A version number is three numbers separated by dots, like 1.2.43 10 | # followed by an optional build number separated by a +. 11 | # Both the version and the builder number may be overridden in flutter 12 | # build by specifying --build-name and --build-number, respectively. 13 | # In Android, build-name is used as versionName while build-number used as versionCode. 14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 16 | # Read more about iOS versioning at 17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 18 | version: 1.0.0+1 19 | 20 | flavorizr: 21 | app: 22 | android: 23 | flavorDimensions: "flavor-type" 24 | ios: 25 | flavors: 26 | 27 | dev: 28 | app: 29 | name: "App-dev" 30 | android: 31 | applicationId: "com.example.dev" 32 | ios: 33 | bundleId: "com.example.dev" 34 | 35 | prod: 36 | app: 37 | name: "App-prod" 38 | android: 39 | applicationId: "com.example.prod" 40 | ios: 41 | bundleId: "com.example.prod" 42 | 43 | instructions: [ 44 | "assets:download", 45 | "assets:extract", 46 | "android:buildGradle", 47 | "android:androidManifest", 48 | "android:dummyAssets", 49 | "ios:xcconfig", 50 | "ios:buildTargets", 51 | "ios:schema", 52 | "ios:dummyAssets", 53 | "ios:plist", 54 | "ide:config", 55 | "assets:clean", 56 | ] 57 | 58 | 59 | 60 | environment: 61 | sdk: ">=2.7.0 <3.0.0" 62 | 63 | dependencies: 64 | flutter: 65 | sdk: flutter 66 | 67 | 68 | # The following adds the Cupertino Icons font to your application. 69 | # Use with the CupertinoIcons class for iOS style icons. 70 | cupertino_icons: ^1.0.2 71 | 72 | dev_dependencies: 73 | flutter_test: 74 | sdk: flutter 75 | flutter_flavorizr: 1.0.10 76 | 77 | # For information on the generic Dart part of this file, see the 78 | # following page: https://dart.dev/tools/pub/pubspec 79 | 80 | # The following section is specific to Flutter. 81 | flutter: 82 | 83 | # The following line ensures that the Material Icons font is 84 | # included with your application, so that you can use the icons in 85 | # the material Icons class. 86 | uses-material-design: true 87 | 88 | # To add assets to your application, add an assets section, like this: 89 | # assets: 90 | # - images/a_dot_burr.jpeg 91 | # - images/a_dot_ham.jpeg 92 | 93 | # An image asset can refer to one or more resolution-specific "variants", see 94 | # https://flutter.dev/assets-and-images/#resolution-aware. 95 | 96 | # For details regarding adding assets from package dependencies, see 97 | # https://flutter.dev/assets-and-images/#from-packages 98 | 99 | # To add custom fonts to your application, add a fonts section here, 100 | # in this "flutter" section. Each entry in this list should have a 101 | # "family" key with the font family name, and a "fonts" key with a 102 | # list giving the asset and other descriptors for the font. For 103 | # example: 104 | # fonts: 105 | # - family: Schyler 106 | # fonts: 107 | # - asset: fonts/Schyler-Regular.ttf 108 | # - asset: fonts/Schyler-Italic.ttf 109 | # style: italic 110 | # - family: Trajan Pro 111 | # fonts: 112 | # - asset: fonts/TrajanPro.ttf 113 | # - asset: fonts/TrajanPro_Bold.ttf 114 | # weight: 700 115 | # 116 | # For details regarding fonts from package dependencies, 117 | # see https://flutter.dev/custom-fonts/#from-packages 118 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | args: 5 | dependency: "direct main" 6 | description: 7 | name: args 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.0.0" 11 | async: 12 | dependency: transitive 13 | description: 14 | name: async 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.5.0" 18 | boolean_selector: 19 | dependency: transitive 20 | description: 21 | name: boolean_selector 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.1.0" 25 | characters: 26 | dependency: transitive 27 | description: 28 | name: characters 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.1.0" 32 | charcode: 33 | dependency: transitive 34 | description: 35 | name: charcode 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.2.0" 39 | clock: 40 | dependency: transitive 41 | description: 42 | name: clock 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.1.0" 46 | collection: 47 | dependency: transitive 48 | description: 49 | name: collection 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.15.0" 53 | fake_async: 54 | dependency: transitive 55 | description: 56 | name: fake_async 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.2.0" 60 | flutter: 61 | dependency: transitive 62 | description: flutter 63 | source: sdk 64 | version: "0.0.0" 65 | flutter_test: 66 | dependency: "direct dev" 67 | description: flutter 68 | source: sdk 69 | version: "0.0.0" 70 | matcher: 71 | dependency: transitive 72 | description: 73 | name: matcher 74 | url: "https://pub.dartlang.org" 75 | source: hosted 76 | version: "0.12.10" 77 | meta: 78 | dependency: transitive 79 | description: 80 | name: meta 81 | url: "https://pub.dartlang.org" 82 | source: hosted 83 | version: "1.3.0" 84 | path: 85 | dependency: transitive 86 | description: 87 | name: path 88 | url: "https://pub.dartlang.org" 89 | source: hosted 90 | version: "1.8.0" 91 | sky_engine: 92 | dependency: transitive 93 | description: flutter 94 | source: sdk 95 | version: "0.0.99" 96 | source_span: 97 | dependency: transitive 98 | description: 99 | name: source_span 100 | url: "https://pub.dartlang.org" 101 | source: hosted 102 | version: "1.8.0" 103 | stack_trace: 104 | dependency: transitive 105 | description: 106 | name: stack_trace 107 | url: "https://pub.dartlang.org" 108 | source: hosted 109 | version: "1.10.0" 110 | stream_channel: 111 | dependency: transitive 112 | description: 113 | name: stream_channel 114 | url: "https://pub.dartlang.org" 115 | source: hosted 116 | version: "2.1.0" 117 | string_scanner: 118 | dependency: transitive 119 | description: 120 | name: string_scanner 121 | url: "https://pub.dartlang.org" 122 | source: hosted 123 | version: "1.1.0" 124 | term_glyph: 125 | dependency: transitive 126 | description: 127 | name: term_glyph 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "1.2.0" 131 | test_api: 132 | dependency: transitive 133 | description: 134 | name: test_api 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "0.2.19" 138 | typed_data: 139 | dependency: transitive 140 | description: 141 | name: typed_data 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "1.3.0" 145 | vector_math: 146 | dependency: transitive 147 | description: 148 | name: vector_math 149 | url: "https://pub.dartlang.org" 150 | source: hosted 151 | version: "2.1.0" 152 | yaml: 153 | dependency: "direct main" 154 | description: 155 | name: yaml 156 | url: "https://pub.dartlang.org" 157 | source: hosted 158 | version: "3.1.0" 159 | sdks: 160 | dart: ">=2.12.0 <3.0.0" 161 | -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | archive: 5 | dependency: transitive 6 | description: 7 | name: archive 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.0.13" 11 | args: 12 | dependency: transitive 13 | description: 14 | name: args 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "1.6.0" 18 | async: 19 | dependency: transitive 20 | description: 21 | name: async 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.5.0" 25 | boolean_selector: 26 | dependency: transitive 27 | description: 28 | name: boolean_selector 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "2.1.0" 32 | characters: 33 | dependency: transitive 34 | description: 35 | name: characters 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.1.0" 39 | charcode: 40 | dependency: transitive 41 | description: 42 | name: charcode 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.2.0" 46 | checked_yaml: 47 | dependency: transitive 48 | description: 49 | name: checked_yaml 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.0.4" 53 | clock: 54 | dependency: transitive 55 | description: 56 | name: clock 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.1.0" 60 | collection: 61 | dependency: transitive 62 | description: 63 | name: collection 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "1.15.0" 67 | convert: 68 | dependency: transitive 69 | description: 70 | name: convert 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "2.1.1" 74 | crypto: 75 | dependency: transitive 76 | description: 77 | name: crypto 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "2.1.5" 81 | cupertino_icons: 82 | dependency: "direct main" 83 | description: 84 | name: cupertino_icons 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "1.0.2" 88 | fake_async: 89 | dependency: transitive 90 | description: 91 | name: fake_async 92 | url: "https://pub.dartlang.org" 93 | source: hosted 94 | version: "1.2.0" 95 | flutter: 96 | dependency: "direct main" 97 | description: flutter 98 | source: sdk 99 | version: "0.0.0" 100 | flutter_flavorizr: 101 | dependency: "direct dev" 102 | description: 103 | name: flutter_flavorizr 104 | url: "https://pub.dartlang.org" 105 | source: hosted 106 | version: "1.0.10" 107 | flutter_test: 108 | dependency: "direct dev" 109 | description: flutter 110 | source: sdk 111 | version: "0.0.0" 112 | io: 113 | dependency: transitive 114 | description: 115 | name: io 116 | url: "https://pub.dartlang.org" 117 | source: hosted 118 | version: "0.3.5" 119 | json_annotation: 120 | dependency: transitive 121 | description: 122 | name: json_annotation 123 | url: "https://pub.dartlang.org" 124 | source: hosted 125 | version: "3.1.1" 126 | matcher: 127 | dependency: transitive 128 | description: 129 | name: matcher 130 | url: "https://pub.dartlang.org" 131 | source: hosted 132 | version: "0.12.10" 133 | meta: 134 | dependency: transitive 135 | description: 136 | name: meta 137 | url: "https://pub.dartlang.org" 138 | source: hosted 139 | version: "1.3.0" 140 | path: 141 | dependency: transitive 142 | description: 143 | name: path 144 | url: "https://pub.dartlang.org" 145 | source: hosted 146 | version: "1.8.0" 147 | petitparser: 148 | dependency: transitive 149 | description: 150 | name: petitparser 151 | url: "https://pub.dartlang.org" 152 | source: hosted 153 | version: "3.1.0" 154 | sky_engine: 155 | dependency: transitive 156 | description: flutter 157 | source: sdk 158 | version: "0.0.99" 159 | source_span: 160 | dependency: transitive 161 | description: 162 | name: source_span 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "1.8.0" 166 | stack_trace: 167 | dependency: transitive 168 | description: 169 | name: stack_trace 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "1.10.0" 173 | stream_channel: 174 | dependency: transitive 175 | description: 176 | name: stream_channel 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "2.1.0" 180 | string_scanner: 181 | dependency: transitive 182 | description: 183 | name: string_scanner 184 | url: "https://pub.dartlang.org" 185 | source: hosted 186 | version: "1.1.0" 187 | term_glyph: 188 | dependency: transitive 189 | description: 190 | name: term_glyph 191 | url: "https://pub.dartlang.org" 192 | source: hosted 193 | version: "1.2.0" 194 | test_api: 195 | dependency: transitive 196 | description: 197 | name: test_api 198 | url: "https://pub.dartlang.org" 199 | source: hosted 200 | version: "0.2.19" 201 | typed_data: 202 | dependency: transitive 203 | description: 204 | name: typed_data 205 | url: "https://pub.dartlang.org" 206 | source: hosted 207 | version: "1.3.0" 208 | vector_math: 209 | dependency: transitive 210 | description: 211 | name: vector_math 212 | url: "https://pub.dartlang.org" 213 | source: hosted 214 | version: "2.1.0" 215 | xml: 216 | dependency: transitive 217 | description: 218 | name: xml 219 | url: "https://pub.dartlang.org" 220 | source: hosted 221 | version: "4.5.1" 222 | yaml: 223 | dependency: transitive 224 | description: 225 | name: yaml 226 | url: "https://pub.dartlang.org" 227 | source: hosted 228 | version: "2.2.1" 229 | sdks: 230 | dart: ">=2.12.0-0.0 <3.0.0" 231 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # app_starter 🚀 2 | A package that helps you start a flutter application from a specific template 3 | 4 | ## Getting Started 5 | 6 | Simply activate the package: 7 | ```sh 8 | flutter pub global activate app_starter 9 | ``` 10 | ## How to use it ? 11 | Place yourself where you want to create your app and then simply run: 12 | 13 | ```sh 14 | app_starter --name --org --template 15 | ``` 16 | 17 | For example: 18 | 19 | ```sh 20 | app_starter --name toto --org io.example --template https://github.com/ThomasEcalle/flappy_template 21 | ``` 22 | Or, more concise, using abbreviations: 23 | ```sh 24 | app_starter -n toto -o io.example -t https://github.com/ThomasEcalle/flappy_template 25 | ``` 26 | Showing configuration file store values: 27 | ```sh 28 | app_starter --config 29 | ``` 30 | Showing help: 31 | ```sh 32 | app_starter --help 33 | ``` 34 | 35 | ## Arguments 36 | 37 | Here are the list of arguments you could use : 38 | 39 | | key | abbreviation | description | example | 40 | | :--- | :---: | :--- | :--- | 41 | | name | n | the dart package identifier | example | 42 | | org | o | the organisation identifier | com.example | 43 | | template | t | the git repository of your template | https://github.com/ThomasEcalle/flappy_template | 44 | | config | c | shows values stored in configuration file | --config | 45 | | save | s | save values in configuration file | --save | 46 | | help | h | shows help | --help | 47 | 48 | 49 | ## How does it works ? 50 | 51 | 1. This tool **creates** a fresh new flutter application using the basic `flutter create` command from the flutter version installed on your computer. 52 | 53 | 2. It will get your model repository and **clone** it. 54 | 55 | 3. Then, it will ***copy and paste*** the `lib` and `test` folders, as well as the `pubspec.yaml` file from your model repository to your new app. 56 | 57 | 4. Fourth step: it will **change all imports** in these directories (and in pubspec.yaml) in order to put the right new dart package identifier. 58 | 59 | 5. Finally, the tool will delete temporary cloned repository and... 60 | 61 | **you are good to go** ! 62 | 63 | 64 | ## Motivation 65 | As a Flutter developper, you may have to create new apps very often. 66 | Each time you create an application, you usually have to do the same things: 67 | 68 | - create the app with the right name and organization 69 | - put on the architecture you are used to work with 70 | - put all the dependencies you are used to work with 71 | - (depending on your needs): create several flavors 72 | - etc. 73 | 74 | Being a freelance developer and having multiple customers or being a tech lead in a company always creating new apps, this kind of scenario may happen a lot in your life. 75 | 76 | This package is here to make you **save some time** on these processes. 77 | 78 | ## Several philosophies 79 | Now that you want to automate these processes, you have to choose **how** to do it. 80 | 81 | ### Using an already existing "starter"❓ 82 | You could use an already existing starter as the famous one from very good ventures : [very_good_cli](https://github.com/VeryGoodOpenSource/very_good_cli) 83 | 84 | Let's be honest : **this is a good starter** ! 85 | 86 | But you can't really customize it depending on your needs.. and developers often have different needs ! 87 | 88 | Different philosophies on architecture, on dependencies, etc. 89 | 90 | ### Cloning a repository and "change the name"❓ 91 | 92 | An other option that I previously used was to create a model repository. 93 | This repository would implement all I need for a "basic" app. 94 | Then, I just had to clone it and change the app's name. 95 | 96 | But... that was **never so simple**. 97 | 98 | Creating a flutter app with the command line automate a bunch of things for you. 99 | From putting the right packages on Android & iOS to the right names in configurations files, and a lot of other things. 100 | 101 | So, to "just change the name of your app" is never simple. 102 | Without mentioning the fact that the number of configuration files which need to be update may evolve as Flutter evolves itself ! 103 | 104 | ### Using app_starter 🚀 105 | I wanted to create a way to reunite the best of the 2 worlds: 106 | 107 | - creating the app using flutter's command-line `flutter create` prevents developer from putting his hands in all configuration files 108 | 109 | - cloning architecture from a model repository enables developer to build his own architecture and template 110 | 111 | Flutter evolves ? 112 | 113 | No problem, you will still be able to create a new app cloning your base architecture without any effort 🎉 114 | ## About app flavors 115 | Flavors are really important in app develoment. 116 | Most of the time, apps have at least a `dev` and a `prod` flavor, some times more. 117 | But creating flavors is not really simple (see the [official doc](https://flutter.dev/docs/deployment/flavors)) 118 | 119 | On Android, it is quite simple. 120 | 121 | On iOS ... well... it is not "hard", but it takes you a little bit of time to be sure everything is ok. 122 | 123 | I didn't want to force app_starter users to use flavors. 124 | At first because app_starter should be really generic to fit with every developer needs. 125 | Also because automating flavors creation is not really easy. 126 | 127 | **BUT**, app_starter can still help you handling flavors easily in your templates 🔥 128 | 129 | For example, in the default template, I use the great package [flutter_flavorizr](https://pub.dev/packages/flutter_flavorizr). 130 | 131 | Thanks to this package, I just have to say which flavors I would like to create in the pubspec.yaml. 132 | 133 | Then, after app_starter run, I can generate these flavors using the [flutter_flavorizr](https://pub.dev/packages/flutter_flavorizr) command-line 🎉 134 | As you can see, the way app_starter works enable each developer to make its own starter easily, without the constraint to base itself on someone else "template". 135 | 136 | Feel free to create your own templates and to play with it ! -------------------------------------------------------------------------------- /lib/src/command_runner.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:app_starter/src/logger.dart'; 4 | import 'package:args/args.dart'; 5 | import 'package:yaml/yaml.dart'; 6 | 7 | import 'models/app_model.dart'; 8 | 9 | /// Base app_starter class to launch app creation 10 | class CommandRunner { 11 | /// Method called on app creation 12 | void create(List args) async { 13 | final ArgParser parser = ArgParser() 14 | ..addOption( 15 | "name", 16 | abbr: "n", 17 | defaultsTo: null, 18 | ) 19 | ..addOption( 20 | "template", 21 | abbr: "t", 22 | defaultsTo: null, 23 | ) 24 | ..addOption( 25 | "org", 26 | abbr: "o", 27 | defaultsTo: null, 28 | ) 29 | ..addFlag( 30 | "config", 31 | abbr: "c", 32 | negatable: false, 33 | defaultsTo: false, 34 | ) 35 | ..addFlag( 36 | "save", 37 | abbr: "s", 38 | negatable: false, 39 | defaultsTo: false, 40 | ) 41 | ..addFlag( 42 | "help", 43 | abbr: "h", 44 | negatable: false, 45 | defaultsTo: false, 46 | ); 47 | 48 | final results = parser.parse(args); 49 | 50 | final bool save = results["save"]; 51 | final bool showConfig = results["config"]; 52 | final bool showHelp = results["help"]; 53 | 54 | if (showHelp) { 55 | _showHelp(); 56 | return; 57 | } 58 | 59 | final AppModel appModelFomConfig = AppModel.fromConfigFile(); 60 | 61 | if (showConfig) { 62 | Logger.logConfigKeyValue("name", appModelFomConfig.name); 63 | Logger.logConfigKeyValue("organization", appModelFomConfig.organization); 64 | Logger.logConfigKeyValue( 65 | "template", appModelFomConfig.templateRepository); 66 | 67 | return; 68 | } 69 | 70 | final AppModel appModel = AppModel( 71 | name: results["name"] ?? appModelFomConfig.name, 72 | organization: results["org"] ?? appModelFomConfig.organization, 73 | templateRepository: 74 | results["template"] ?? appModelFomConfig.templateRepository, 75 | ); 76 | 77 | bool hasOneFiledNull = false; 78 | 79 | if (appModel.name == null) { 80 | Logger.logError( 81 | "Package identifier argument not found, neither in config. --name or -n to add one."); 82 | hasOneFiledNull = true; 83 | } 84 | 85 | if (appModel.organization == null) { 86 | Logger.logError( 87 | "Organization identifier not found, neither in config. --org or -o to add one."); 88 | hasOneFiledNull = true; 89 | } 90 | 91 | if (appModel.templateRepository == null) { 92 | Logger.logError( 93 | "Template url not found, neither in config. --template or -t to use one."); 94 | hasOneFiledNull = true; 95 | } 96 | 97 | if (!appModel.hasValidPackageName()) { 98 | Logger.logError("${appModel.name} is not a dart valid package name"); 99 | hasOneFiledNull = true; 100 | } 101 | 102 | if (hasOneFiledNull) return; 103 | 104 | if (save) { 105 | appModel.writeInConfigFile(); 106 | } 107 | 108 | Logger.logInfo("Let's create ${appModel.name} application !"); 109 | 110 | final Directory current = Directory.current; 111 | final String workingDirectoryPath = current.path; 112 | 113 | try { 114 | Logger.logInfo( 115 | "Creating flutter project using your current flutter version..."); 116 | 117 | Process.runSync( 118 | "flutter", 119 | [ 120 | "create", 121 | "--org", 122 | appModel.organization!, 123 | appModel.name!, 124 | ], 125 | workingDirectory: workingDirectoryPath, 126 | runInShell: true, 127 | ); 128 | 129 | Logger.logInfo( 130 | "Retrieving your template from ${appModel.templateRepository}..."); 131 | 132 | Process.runSync( 133 | "git", 134 | [ 135 | "clone", 136 | appModel.templateRepository!, 137 | "temp", 138 | ], 139 | workingDirectory: "$workingDirectoryPath", 140 | runInShell: true, 141 | ); 142 | 143 | final String content = 144 | await File("$workingDirectoryPath/temp/pubspec.yaml").readAsString(); 145 | final mapData = loadYaml(content); 146 | final String templatePackageName = mapData["name"]; 147 | 148 | _copyPasteDirectory( 149 | "$workingDirectoryPath/temp/lib", 150 | "$workingDirectoryPath/${appModel.name}/lib", 151 | ); 152 | 153 | _copyPasteDirectory( 154 | "$workingDirectoryPath/temp/test", 155 | "$workingDirectoryPath/${appModel.name}/test", 156 | ); 157 | 158 | await _copyPasteFileContent( 159 | "$workingDirectoryPath/temp/pubspec.yaml", 160 | "$workingDirectoryPath/${appModel.name}/pubspec.yaml", 161 | ); 162 | 163 | await _changeAllInFile( 164 | "$workingDirectoryPath/${appModel.name}/pubspec.yaml", 165 | templatePackageName, 166 | appModel.name!, 167 | ); 168 | 169 | await _changeAllInDirectory( 170 | "$workingDirectoryPath/${appModel.name}/lib", 171 | templatePackageName, 172 | appModel.name!, 173 | ); 174 | 175 | await _changeAllInDirectory( 176 | "$workingDirectoryPath/${appModel.name}/test", 177 | templatePackageName, 178 | appModel.name!, 179 | ); 180 | 181 | Process.runSync( 182 | "flutter", 183 | [ 184 | "pub", 185 | "get", 186 | ], 187 | workingDirectory: "$workingDirectoryPath/${appModel.name}", 188 | ); 189 | 190 | Logger.logInfo("Deleting temp files used for generation..."); 191 | 192 | Process.runSync( 193 | "rm", 194 | [ 195 | "-rf", 196 | "$workingDirectoryPath/temp", 197 | ], 198 | ); 199 | 200 | Logger.logInfo("You are good to go ! :)", lineBreak: true); 201 | } catch (error) { 202 | Logger.logError("Error creating project : $error"); 203 | 204 | Process.runSync( 205 | "rm", 206 | [ 207 | "-rf", 208 | "$workingDirectoryPath/${appModel.name}", 209 | ], 210 | ); 211 | Process.runSync( 212 | "rm", 213 | [ 214 | "-rf", 215 | "$workingDirectoryPath/temp", 216 | ], 217 | ); 218 | } 219 | } 220 | 221 | /// Copy all the content of [sourceFilePath] and paste it in [targetFilePath] 222 | Future _copyPasteFileContent( 223 | String sourceFilePath, String targetFilePath) async { 224 | try { 225 | final File sourceFile = File(sourceFilePath); 226 | final File targetFile = File(targetFilePath); 227 | 228 | final String sourceContent = sourceFile.readAsStringSync(); 229 | targetFile.writeAsStringSync(sourceContent); 230 | } catch (error) { 231 | Logger.logError("Error copying file contents : $error"); 232 | } 233 | } 234 | 235 | /// Copy all the content of [sourceDirPath] and paste it in [targetDirPath] 236 | void _copyPasteDirectory( 237 | String sourceDirPath, 238 | String targetDirPath, 239 | ) { 240 | Process.runSync( 241 | "rm", 242 | [ 243 | "-rf", 244 | targetDirPath, 245 | ], 246 | ); 247 | 248 | Process.runSync( 249 | "cp", 250 | [ 251 | "-r", 252 | sourceDirPath, 253 | targetDirPath, 254 | ], 255 | ); 256 | } 257 | 258 | /// Update recursively all imports in [directoryPath] from [oldPackageName] to [newPackageName] 259 | Future _changeAllInDirectory(String directoryPath, 260 | String oldPackageName, String newPackageName) async { 261 | final Directory directory = Directory(directoryPath); 262 | final String dirName = directoryPath.split("/").last; 263 | if (directory.existsSync()) { 264 | final List files = directory.listSync(recursive: true); 265 | await Future.forEach( 266 | files, 267 | (FileSystemEntity fileSystemEntity) async { 268 | if (fileSystemEntity is File) { 269 | await _changeAllInFile( 270 | fileSystemEntity.path, oldPackageName, newPackageName); 271 | } 272 | }, 273 | ); 274 | Logger.logInfo( 275 | "All files in $dirName updated with new package name ($newPackageName)"); 276 | } else { 277 | Logger.logWarning( 278 | "Missing directory $dirName in your template, it will be ignored"); 279 | } 280 | } 281 | 282 | /// Update recursively all imports in [filePath] from [oldPackageName] to [newPackageName] 283 | Future _changeAllInFile( 284 | String filePath, String oldValue, String newValue) async { 285 | try { 286 | final File file = File(filePath); 287 | final String content = file.readAsStringSync(); 288 | if (content.contains(oldValue)) { 289 | final String newContent = content.replaceAll(oldValue, newValue); 290 | file.writeAsStringSync(newContent); 291 | } 292 | } catch (error) { 293 | Logger.logError("Error updating file $filePath : $error"); 294 | } 295 | } 296 | 297 | /// Simply print help message 298 | void _showHelp() { 299 | print(""" 300 | 301 | usage: app_starter [--save] [--name ] [--org ] [--template