Compare commits

...

16 Commits

694 changed files with 3048 additions and 25230 deletions

View File

@ -1,5 +1,5 @@
<!--
* Copyright (C) 2022 WYATT GROUP
* Copyright (C) 2023 WYATT GROUP
* Please see the AUTHORS file for details.
*
* This program is free software: you can redistribute it and/or modify
@ -7,7 +7,7 @@
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
@ -17,30 +17,23 @@
-->
<p align="center">
<a href="https://wyattapp.io">
<img width="150px" src="resources/wyatt-campus-logo.png">
</a>
<a href="https://wyatt-studio.fr">
<img width="150px" src="resources/wyatt-studio-logo.png">
</a>
<a href="https://wyatt-studio.fr"><img width="150px" src="resources/wyatt-studio-logo.png"></a>
<h1 align="center">Wyatt Bricks</h1>
</p>
<p align="center">
<a href="https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_analysis">
<img src="https://img.shields.io/badge/Style-Wyatt%20Analysis-blue.svg?style=flat-square" alt="Style: Wyatt Analysis" />
</a>
<a href="https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_analysis"><img src="https://img.shields.io/badge/Style-Wyatt%20Analysis-blue.svg?style=flat-square" alt="Style: Wyatt Analysis" /></a>
</p>
---
## About
Generate consistent code fast.
Use reusable templates called wyatt bricks to supercharge your workflow.
---
## Quick Start
```sh
@ -53,29 +46,31 @@ mason init
## Create a Brick
- Create a **Brickgen** project in `apps/`.
* Create a **Brickgen** project in `apps/`.
```sh
mason make wyatt_brick_template -o apps/new_brick
```
- Create/Modify your compilable code in `apps/new_brick/new_brick`.
- Customize the `brickgen.yaml` config file.
- Generate the brick using `brickgen` cli tool.
* Create/Modify your compilable code in `apps/new_brick/new_brick`.
* Customize the `brickgen.yaml` config file.
* Generate the brick using `brickgen` cli tool.
```sh
dart ./tools/brick_generator/bin/brickgen.dart ./apps/new_brick/ ./bricks/
```
> More infos about generator in `./tools/brick_generator`.
> More infos about generator in `./tools/brick_generator` .
💡 You can also build all the bricks with `./tools/build.sh`
## Use
Please add your bricks in `./bricks`. (See `Create a Brick` section)
Please add your bricks in `./bricks` . (See `Create a Brick` section)
Please specify the prerequisites necessary to use the brick (The code must be able to compile directly after its integration.)
```sh
# To load all bricks (and generate mason-lock.json)
mason get
```
```

View File

@ -17,7 +17,7 @@
name: wyatt_app_template
description: New app template for Wyatt Studio projects.
version: 0.1.0
version: 0.2.2
vars:
display_name:
@ -37,6 +37,7 @@ vars:
prompt: "What is the project name?"
formats:
- snake_case
- pascal_case
bundle_id:
compilable: io.wyattapp.start

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -35,5 +35,38 @@ void removeGitKeepFiles(String targetPath) {
Future<void> run(HookContext context) async {
final workingDirectory = Directory.current.path;
/// Remove .gitkeep files
print('Removing .gitkeep files');
removeGitKeepFiles(workingDirectory);
/// dart pub get
print('Running `dart pub get`');
await Process.run('dart', ['pub', 'get'], runInShell: true);
/// dart format . --fix && dart fix . --apply
print('Running `dart format . --fix && dart fix . --apply`');
await Process.run('dart', ['format', '.', '--fix'], runInShell: true);
await Process.run('dart', ['fix', '.', '--apply'], runInShell: true);
final bundleId = context.vars['bundle_id'] as String?;
final appName = bundleId?.split('.').last;
final org = bundleId?.replaceAll('.$appName', '');
/// flutter create --platforms android,ios --org com.example --project-name example .
print(
'Running `flutter create --platforms android,ios --org $org --project-name $appName .`');
await Process.run(
'flutter',
[
'create',
'--platforms',
'android,ios',
'--org',
org ?? 'com.example',
'--project-name',
appName ?? 'example',
'.'
],
runInShell: true);
}

View File

@ -47,8 +47,17 @@ app.*.map.json
/android/app/debug
/android/app/profile
/android/app/release
.mason/
# Custom
.mason/
.env
!.env.example
node_modules/
node_modules/
lib/gen/
**/*.g.dart
**/*.freezed.dart
android/fastlane/report.xml
pubspec_overrides.yaml
.fvm/flutter_sdk
*.apk
*.apks

View File

@ -5,36 +5,12 @@
"version": "0.2.0",
"configurations": [
{
"name": "Launch development/debug:mocks",
"name": "Launch development/debug",
"request": "launch",
"type": "dart",
"program": "lib/main_development.dart",
"args": [
"--dart-define=dev_mode=mock",
"--target",
"lib/main_development.dart"
],
"flutterMode": "debug"
},
{
"name": "Launch development/debug:emulator",
"request": "launch",
"type": "dart",
"program": "lib/main_development.dart",
"args": [
"--dart-define=dev_mode=emulator",
"--target",
"lib/main_development.dart"
],
"flutterMode": "debug"
},
{
"name": "Launch development/debug:real",
"request": "launch",
"type": "dart",
"program": "lib/main_development.dart",
"args": [
"--dart-define=dev_mode=real",
"--dart-define-from-file=config.dev.json",
"--target",
"lib/main_development.dart"
],
@ -46,6 +22,7 @@
"type": "dart",
"program": "lib/main_staging.dart",
"args": [
"--dart-define-from-file=config.staging.json",
"--target",
"lib/main_staging.dart"
],
@ -55,8 +32,9 @@
"name": "Launch production/debug",
"request": "launch",
"type": "dart",
"program": "lib/main_production.dart",
"program": "lib/main_produdction.dart",
"args": [
"--dart-define-from-file=config.prod.json",
"--target",
"lib/main_production.dart"
],
@ -66,12 +44,13 @@
"name": "Launch production/release",
"request": "launch",
"type": "dart",
"program": "lib/main_production.dart",
"program": "lib/main_produdction.dart",
"args": [
"--dart-define-from-file=config.prod.json",
"--target",
"lib/main_production.dart"
],
"flutterMode": "release"
},
]
}
}

View File

@ -1,15 +1,16 @@
{
"bloc.newCubitTemplate.type": "equatable",
"psi-header.config": {
"blankLinesAfter": 0,
"forceToTop": true,
},
"psi-header.templates": [
{
"language": "*",
"template": [
"Display Name Copyright (c) <<year>>"
]
}
],
}
"dart.runPubGetOnPubspecChanges": "never",
"bloc.newCubitTemplate.type": "equatable",
"psi-header.config": {
"blankLinesAfter": 0,
"forceToTop": true,
},
"psi-header.templates": [
{
"language": "*",
"template": [
"Display Name Copyright (c) <<year>>"
]
}
],
}

View File

@ -4,5 +4,5 @@
# Name/Organization <email address>
Wyatt Group S.A.S
Hugo Pointcheval <hugo.pointcheval@wyattapp.io>
Malo Léon <malo.leon@wyattapp.io>
Hugo Pointcheval <hugo.pointcheval@wyatt-studio.fr>
Malo Léon <malo.leon@wyatt-studio.fr>

View File

@ -6,54 +6,100 @@ A short project description
* Flutter <https://flutter.dev/>
* Taskfile <https://taskfile.dev/>
* Trapeze <https://trapeze.dev/> (with `npm install` thanks to `package.json`)
### Configuration
> **Warning** Before anything, you need to generate some files
Create `.env` file with
```sh
task bootstrap # to bootstrap the project
```
## Configuration
### Environment variables
```sh
cp .env.example .env
```
### Taskfile
This file contains the secrets variables. You need to fill them.
Available tasks:
At the build time, the app will read the environment variables from `config.<ENV>.json` file.
| Command | Description | Aliases |
|----|-----|-----|
| `clean` | Cleans the environment.| `cl` |
| `format` |Formats the code.| `fmt` |
| `help` |Help dialog.| `h, default` |
| `lint` |Lints the code.| `l` |
| `start-emulators` | Start needed emulators.| `emu` |
| `build:android` | Building Android APK| `build:a` |
| `build:ios` | Building iOS IPA| `build:i` |
| `gen:build` | Running build runner| `gen:b` |
| `gen:build-delete` |Running build runner with deletion of conflicting outputs| `gen:d` |
| `gen:clean` | Cleaning build runner| `gen:c` |
| `gen:intl` |Generating internationalization file| `gen:i` |
| `gen:trapeze` | Running Trapeze config| `gen:t` |
| `gen:watch` | Running build runner in watch mode| `gen:w` |
| `pub:get` | Getting latest dependencies| `pub:g` |
| `pub:outdated` |Checking for outdated dependencies| `pub:o` |
| `pub:upgrade` | Upgrading dependencies| `pub:u` |
| `pub:upgrade-major` | Upgrading dependencies| `pub:um` |
| `pub:validate` |Running dependency validator| `pub:v` |
| `run:dev` | Run app in development environment| `run:d` |
| `run:emu` | Run app in development with emulated environment| `run:e` |
| `run:logs` |Show log output for running Flutter apps| `run:l` |
| `run:mock` |Run app in development environment with mocks| `run:m` |
| `run:prod` |Run app in production environment| `run:p` |
| `run:release` | Run app in production environment and in release mode| `run:r` |
| `run:staging` | Run app in staging environment| `run:s` |
You can enable/disable some features
### Flavors
```json
{
"FEATURE_FLAGS": "logger" // Separated by comma ","
}
```
| Flavor | Details |
|-------|--------|
| Development | Use `--dart-define="dev_mode=<MODE>"` to choose between `mock` , `emulator` and `real` |
| Staging | With a green banner. Only `real` mode available (remote data sources) |
| Production | Only `real` mode available (remote data sources) |
You can also customize data source
> In `lib/core/flavors/flavor.dart` you can customize flavors.
```json
{
"DATA_SOURCE": "mock" // Or "api" for example
}
```
### Splash and icons
To generate splash screen and icons, you need to run the following command:
```sh
task gen:splash # to generate splash screen
task gen:icons # to generate icons
```
## Taskfile
### Commands
<details>
<summary>To display available commands run <code>task help</code></summary>
| Commande | Description | Aliases |
|---------------------------|---------------------------------------------------------------|--------------------------------|
| `bootstrap` | Bootstraps the project. | `bs` |
| `clean` | Cleans the environment. | `cl` |
| `decrypt-android-keys` | Decrypt Android keys | `dak` |
| `encrypt-android-keys` | Encrypt Android keys | `eak` |
| `format` | Formats the code. | `fmt` |
| `help` | Help dialog. | `h` , `default` |
| `lint` | Lints the code. | `l` |
| `build:android` | Building Android AAB | `build:a` |
| `build:ios` | Building iOS IPA | `build:i` |
| `gen:build` | Running build runner | `gen:b` |
| `gen:build-delete` | Running build runner with deletion of conflicting outputs | `gen:d` |
| `gen:clean` | Cleaning build runner | `gen:c` |
| `gen:intl` | Generating internationalization file | `gen:i` |
| `pub:get` | Getting latest dependencies | `pub:g` |
| `pub:outdated` | Checking for outdated dependencies | `pub:o` |
| `pub:upgrade` | Upgrading dependencies | `pub:u` |
| `pub:upgrade-major` | Upgrading dependencies | `pub:um` |
| `pub:validate` | Running dependency validator | `pub:v` |
| `run:dev` | Run app in development environment | `run:d` |
| `run:logs` | Show log output for running Flutter apps | `run:l` |
| `run:prod` | Run app in production environment | `run:p` |
| `run:staging` | Run app in staging environment | `run:s` |
</details>
### Parameters
You can pass flutter options to the build and run commands.
```sh
task run:staging -- -d chrome
```
> **Note** The `--` is required to pass options to the command.
### Secrets
Use:
```sh
task decrypt-android-keys
```
to decrypt the android keys (this assumes you have the passphrase in your .env file).

View File

@ -25,14 +25,14 @@ tasks:
desc: Cleans the environment.
aliases: [cl]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Cleaning the project...{{.COLOROFF}}"
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Cleaning the project...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- flutter clean
format:
desc: Formats the code.
aliases: [fmt]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Formatting the code...{{.COLOROFF}}"
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Formatting the code...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- flutter format --fix
- dart fix --apply
@ -40,12 +40,34 @@ tasks:
desc: Lints the code.
aliases: [l]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Verifying code...{{.COLOROFF}}"
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Verifying code...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- dart analyze . || (echo "Error in project"; exit 1)
start-emulators:
desc: Start needed emulators.
aliases: [emu]
bootstrap:
desc: Bootstraps the project.
aliases: [bs]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Start Firebase emulators...{{.COLOROFF}}"
- firebase emulators:start --only auth,functions,firestore,storage --import=./functions/saved-data --export-on-exit=./functions/saved-data
- melos bs || true
- flutter pub get
- dart run build_runner build --delete-conflicting-outputs
- flutter gen-l10n
- fluttergen || true
encrypt-android-keys:
desc: Encrypt Android keys
aliases: [eak]
cmds:
- cd android && jar cfvM android_keys.zip android_keys
- source '.env' && gpg --quiet --batch --yes --symmetric --passphrase=$ANDROID_KEYS_SECRET_PASSPHRASE --output android/android_keys.zip.gpg android/android_keys.zip
- rm -rf android/android_keys
- rm android/android_keys.zip
decrypt-android-keys:
desc: Decrypt Android keys
aliases: [dak]
cmds:
- source '.env' && gpg --quiet --batch --yes --decrypt --passphrase=$ANDROID_KEYS_SECRET_PASSPHRASE --output android/android_keys.zip android/android_keys.zip.gpg
- cd android && jar xvf android_keys.zip
- mv android/android_keys/* android/
- rm -rf android/android_keys
- rm android/android_keys.zip

View File

@ -2,17 +2,17 @@ include: package:wyatt_analysis/analysis_options.flutter.yaml
analyzer:
plugins:
- dart_code_metrics
- dart_code_linter
dart_code_metrics:
dart_code_linter:
anti-patterns:
- long-method
- long-parameter-list
metrics:
cyclomatic-complexity: 20
maximum-nesting-level: 5
number-of-parameters: 4
source-lines-of-code: 50
number-of-parameters: 10
source-lines-of-code: 400
metrics-exclude:
- test/**
rules:

View File

@ -1,13 +0,0 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks

View File

@ -1,71 +0,0 @@
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "io.wyattapp.start"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}

View File

@ -1,8 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.wyattapp.start">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@ -1,25 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.wyattapp.start">
<application android:label="Display Name" android:name="${applicationName}" android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/NormalTheme" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data android:name="flutterEmbedding" android:value="2" />
</application>
</manifest>

View File

@ -1,6 +0,0 @@
package io.wyattapp.start
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
}

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -1,8 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.wyattapp.start">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@ -1,31 +0,0 @@
buildscript {
ext.kotlin_version = '1.6.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}

View File

@ -1,3 +0,0 @@
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true

View File

@ -1,5 +0,0 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip

View File

@ -1,11 +0,0 @@
include ':app'
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"

View File

@ -0,0 +1 @@
# just to keep empty folder in brick generation

View File

@ -22,17 +22,19 @@ tasks:
- flutter pub get
android:
desc: Building Android APK
desc: Building Android AAB
deps: [clean, get]
aliases: [a]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Building Android APK...{{.COLOROFF}}"
- flutter build lib/main_production apk --no-pub --no-shrink
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Building Android AAB...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- flutter build appbundle lib/main_production.dart --dart-define-from-file=config.prod.json --no-pub --obfuscate --split-debug-info="./build/app/outputs/bundle/release/" {{#mustacheCase}}.CLI_ARGS{{/mustacheCase}}
- open ./build/app/outputs/bundle/release/
ios:
desc: Building iOS IPA
deps: [clean, get]
aliases: [i]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Building iOS IPA...{{.COLOROFF}}"
- flutter build lib/main_production ipa --no-pub
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Building iOS IPA...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- flutter build ipa lib/main_production.dart --dart-define-from-file=config.prod.json --no-pub --obfuscate --split-debug-info="./build/ios/archive" {{#mustacheCase}}.CLI_ARGS{{/mustacheCase}}
- find "./build/ios/archive" -name "*.xcarchive" -exec open {} \;

View File

@ -13,7 +13,7 @@ tasks:
internal: true
desc: Gets dependencies.
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Getting the dependencies...{{.COLOROFF}}"
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Getting the dependencies...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- flutter pub get
build:
@ -21,7 +21,7 @@ tasks:
deps: [get]
aliases: [b]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Running build runner...{{.COLOROFF}}"
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Running build runner...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- flutter pub run build_runner build
intl:
@ -29,35 +29,36 @@ tasks:
deps: [get]
aliases: [i]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Running intl generation...{{.COLOROFF}}"
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Running intl generation...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- flutter gen-l10n
splash:
desc: Generating splash screen
deps: [get]
aliases: [s]
cmds:
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Running splash screen generation...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- dart run flutter_native_splash:create
icons:
desc: Generating icons
deps: [get]
aliases: [ic]
cmds:
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Running icon generation...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- dart run flutter_launcher_icons
build-delete:
desc: Running build runner with deletion of conflicting outputs
deps: [get]
aliases: [d]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Running build runner with deletion of conflicting outputs...{{.COLOROFF}}"
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Running build runner with deletion of conflicting outputs...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- flutter pub run build_runner build --delete-conflicting-outputs
clean:
desc: Cleaning build runner
aliases: [c]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Cleaning build runner...{{.COLOROFF}}"
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Cleaning build runner...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- flutter pub run build_runner clean
watch:
desc: Running build runner in watch mode
deps: [get]
aliases: [w]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Running build runner in watch mode...{{.COLOROFF}}"
- flutter pub run build_runner watch
trapeze:
desc: Running Trapeze config
aliases: [t]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Running Trapeze config...{{.COLOROFF}}"
- npx trapeze run trapeze.yaml --android-project android --ios-project ios

View File

@ -13,21 +13,21 @@ tasks:
desc: Getting latest dependencies
aliases: [g]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Getting latest dependencies...{{.COLOROFF}}"
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Getting latest dependencies...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- flutter pub get
upgrade:
desc: Upgrading dependencies
aliases: [u]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Upgrading dependencies...{{.COLOROFF}}"
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Upgrading dependencies...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- flutter pub upgrade
upgrade-major:
desc: Upgrading dependencies
aliases: [um]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Upgrading dependencies --major-versions...{{.COLOROFF}}"
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Upgrading dependencies --major-versions...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- flutter pub upgrade --major-versions
outdated:
@ -35,13 +35,5 @@ tasks:
deps: [upgrade]
aliases: [o]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Checking for outdated dependencies...{{.COLOROFF}}"
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Checking for outdated dependencies...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- flutter pub upgrade
validate:
desc: Running dependency validator
deps: [get]
aliases: [v]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Validating dependencies...{{.COLOROFF}}"
- flutter pub run dependency_validator

View File

@ -13,47 +13,26 @@ tasks:
desc: Show log output for running Flutter apps
aliases: [l]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Showing log output for running Flutter apps...{{.COLOROFF}}"
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Showing log output for running Flutter apps...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- flutter logs
mock:
desc: Run app in development environment with mocks
aliases: [m]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Running the app (development/debug:mocks)...{{.COLOROFF}}"
- flutter run --target lib/main_development.dart --dart-define="dev_mode=mock"
emu:
desc: Run app in development with emulated environment
aliases: [e]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Running the app (development/debug:emulator)...{{.COLOROFF}}"
- flutter run --target lib/main_development.dart --dart-define="dev_mode=emulator"
dev:
desc: Run app in development environment
aliases: [d]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Running the app (development/debug:real)...{{.COLOROFF}}"
- flutter run --target lib/main_development.dart --dart-define="dev_mode=real"
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Running the app (development)...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- flutter run --target lib/main_development.dart --dart-define-from-file=config.dev.json {{#mustacheCase}}.CLI_ARGS{{/mustacheCase}}
staging:
desc: Run app in staging environment
aliases: [s]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Running the app (staging/debug)...{{.COLOROFF}}"
- flutter run --target lib/main_staging.dart
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Running the app (staging)...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- flutter run --target lib/main_staging.dart --dart-define-from-file=config.staging.json {{#mustacheCase}}.CLI_ARGS{{/mustacheCase}}
prod:
desc: Run app in production environment
aliases: [p]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Running the app (production/debug)...{{.COLOROFF}}"
- flutter run --target lib/main_production.dart
release:
desc: Run app in production environment and in release mode
aliases: [r]
cmds:
- echo -e "{{.GREEN}}{{.PREFIX}} Running the app (production/release)...{{.COLOROFF}}"
- flutter run --target lib/main_production.dart --release
- echo -e "{{#mustacheCase}}.GREEN{{/mustacheCase}}{{#mustacheCase}}.PREFIX{{/mustacheCase}} Running the app (production)...{{#mustacheCase}}.COLOROFF{{/mustacheCase}}"
- flutter run --target lib/main_production.dart --dart-define-from-file=config.prod.json {{#mustacheCase}}.CLI_ARGS{{/mustacheCase}}

View File

@ -0,0 +1,6 @@
{
"ENV_NAME": "dev",
"DATA_SOURCE": "api",
"LOGGER_LEVEL": "debug",
"FEATURE_FLAGS": "logger"
}

View File

@ -0,0 +1,4 @@
{
"ENV_NAME": "prod",
"DATA_SOURCE": "api"
}

View File

@ -0,0 +1,5 @@
{
"ENV_NAME": "staging",
"DATA_SOURCE": "api",
"FEATURE_FLAGS": "logger"
}

View File

@ -1,34 +0,0 @@
**/dgph
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/ephemeral/
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>11.0</string>
</dict>
</plist>

View File

@ -1,2 +0,0 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"

View File

@ -1,2 +0,0 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"

View File

@ -1,41 +0,0 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '11.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__))
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end

View File

@ -1,28 +0,0 @@
PODS:
- Flutter (1.0.0)
- flutter_native_splash (0.0.1):
- Flutter
- url_launcher_ios (0.0.1):
- Flutter
DEPENDENCIES:
- Flutter (from `Flutter`)
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
EXTERNAL SOURCES:
Flutter:
:path: Flutter
flutter_native_splash:
:path: ".symlinks/plugins/flutter_native_splash/ios"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
SPEC CHECKSUMS:
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
url_launcher_ios: ae1517e5e344f5544fb090b079e11f399dfbe4d2
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
COCOAPODS: 1.11.3

View File

@ -1,556 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
50F1D9CF301DADBFF7F91098 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F58D6DFA5E148E9B1E5401F /* Pods_Runner.framework */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
01240B090F6ECE02483CB484 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
18B4FB2B44E101F10AB8D41B /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
1F58D6DFA5E148E9B1E5401F /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
EA780011634A6BC46817CBE0 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
50F1D9CF301DADBFF7F91098 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
10872F84FB14C7DD915284C6 /* Pods */ = {
isa = PBXGroup;
children = (
18B4FB2B44E101F10AB8D41B /* Pods-Runner.debug.xcconfig */,
01240B090F6ECE02483CB484 /* Pods-Runner.release.xcconfig */,
EA780011634A6BC46817CBE0 /* Pods-Runner.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
4204558B17A62367423769E8 /* Frameworks */ = {
isa = PBXGroup;
children = (
1F58D6DFA5E148E9B1E5401F /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
10872F84FB14C7DD915284C6 /* Pods */,
4204558B17A62367423769E8 /* Frameworks */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
);
path = Runner;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
B0C681F6443208846EBFB7D2 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
CF936C6216E6F00FB5F73F4C /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1300;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 1100;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
B0C681F6443208846EBFB7D2 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
CF936C6216E6F00FB5F73F4C /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 6Z5P8GG96U;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = io.wyattapp.start;
PRODUCT_NAME = "Display Name";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 6Z5P8GG96U;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = io.wyattapp.start;
PRODUCT_NAME = "Display Name";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 6Z5P8GG96U;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = io.wyattapp.start;
PRODUCT_NAME = "Display Name";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@ -1,87 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@ -1,13 +0,0 @@
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}

View File

@ -1,122 +0,0 @@
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -1,23 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

View File

@ -1,5 +0,0 @@
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
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.

View File

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

View File

@ -1,51 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Display Name</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Display Name</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>

View File

@ -1 +0,0 @@
#import "GeneratedPluginRegistrant.h"

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
</dict>
</plist>

View File

@ -5,4 +5,5 @@ output-dir: lib/gen/
nullable-getter: false
use-deferred-loading: true
synthetic-package: false
header: "/// Display Name, localized files. Automatically generated with `task gen:intl`."
use-escaping: false
header: "/// Display Name, localized files. Automatically generated with `task gen:intl`."

View File

@ -2,19 +2,44 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:logging/logging.dart';
import 'package:starting_template/core/dependency_injection/get_it.dart';
import 'package:starting_template/core/flavors/flavor.dart';
import 'package:starting_template/core/enums/feature_flag.dart';
import 'package:starting_template/core/logger/app_logger.dart';
import 'package:starting_template/core/logger/simple_log_printer.dart';
import 'package:starting_template/core/utils/app_bloc_observer.dart';
import 'package:starting_template/core/utils/env.dart';
Future<void> bootstrap(FutureOr<Widget> Function() builder) async {
final widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
// FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
// Initialize logging
final logger = AppLogger();
Bloc.observer = AppBlocObserver();
await runZonedGuarded(
() async {
WidgetsFlutterBinding.ensureInitialized();
debugPrint('Flavor: ${Flavor.get()}');
// Verify that we have the correct environment
Env.verify();
await GetItInitializer.init();
if (Env.isFeatureEnabled(FeatureFlag.logger)) {
logger
..level = Env.loggerLevel
..addPlugin(const SimpleLogPrinter());
} else {
logger.level = Level.OFF;
}
runApp(await builder());
debugPrint(Env.summary); // Print even if logger is disabled
Bloc.observer = AppBlocObserver();
// Intialize dependencies injection
await GetItInitializer.init();
runApp(await builder());
},
(error, stackTrace) {
logger.error(error.toString(), stackTrace);
},
);
}

View File

@ -0,0 +1,163 @@
const String _envName = 'ENV_NAME';
const String _dataSource = 'DATA_SOURCE';
const String _loggerLevel = 'LOGGER_LEVEL';
const String _featureFlags = 'FEATURE_FLAGS';
enum BuildConfigKey {
envName(_envName, isRequired: true),
dataSource(_dataSource, isRequired: true),
loggerLevel(_loggerLevel),
featureFlags(_featureFlags);
const BuildConfigKey(this.key, {this.isRequired = false});
final String key;
final bool isRequired;
/// Returns true if the environment variable is defined
///
/// Cannot use `const bool.hasEnvironment(key)` because it is not a
/// constant expression. This is why we need to use a switch statement.
bool get isDefined => switch (this) {
BuildConfigKey.envName => const bool.hasEnvironment(_envName),
BuildConfigKey.dataSource => const bool.hasEnvironment(_dataSource),
BuildConfigKey.loggerLevel => const bool.hasEnvironment(_loggerLevel),
BuildConfigKey.featureFlags => const bool.hasEnvironment(_featureFlags),
};
/// Returns the value of the environment variable
///
/// Cannot use `const String.fromEnvironment(key)` because it is not a
/// constant expression. This is why we need to use a switch statement.
String get stringFromEnv => switch (this) {
BuildConfigKey.envName => const String.fromEnvironment(_envName),
BuildConfigKey.dataSource => const String.fromEnvironment(_dataSource),
BuildConfigKey.loggerLevel =>
const String.fromEnvironment(_loggerLevel),
BuildConfigKey.featureFlags =>
const String.fromEnvironment(_featureFlags),
};
/// Returns the values of the environment variables
static String get summary {
final summary = StringBuffer();
for (final key in BuildConfigKey.values) {
if (key.isRequired && !key.isDefined) {
summary.writeln('${key.key} is not defined (required)');
continue;
}
if (key.isDefined) {
summary.writeln('${key.key}: ${key.stringFromEnv}');
continue;
}
}
return summary.toString();
}
/// Returns the value of the environment variable
///
/// If the environment variable is not defined, returns null
T? getOrNull<T>() {
try {
return get<T>();
} catch (_) {
return null;
}
}
/// Returns the value of the environment variable
///
/// If the environment variable is not defined, returns the value of [or]
T getOr<T>(T Function() or) {
switch (T) {
case String:
return _getStringOr(or as String Function()) as T;
case int:
return _getIntOr(or as int Function()) as T;
case double:
return _getDoubleOr(or as double Function()) as T;
case bool:
return _getBool() as T;
default:
throw Exception('Type $T is not supported');
}
}
/// Returns the value of the environment variable
///
/// Throws an exception if the environment variable is not defined
T get<T>() {
switch (T) {
case String:
return _getString() as T;
case int:
return _getInt() as T;
case double:
return _getDouble() as T;
case bool:
return _getBool() as T;
default:
throw Exception('Type $T is not supported');
}
}
String _getString() {
final value = stringFromEnv;
if (value.isEmpty) {
throw Exception('$key is not defined');
}
return value;
}
int _getInt() {
// Use int.tryParse instead int.fromEnvironment because we want to
// support 0 as a value too.
final value = int.tryParse(stringFromEnv);
if (value == null) {
throw Exception('$key is not defined');
}
return value;
}
double _getDouble() {
final value = double.tryParse(stringFromEnv);
if (value == null) {
throw Exception('$key is not defined');
}
return value;
}
bool _getBool() {
final value = stringFromEnv.toLowerCase();
return value == 'true' || value == '1';
}
double _getDoubleOr(double Function() or) {
try {
return _getDouble();
} catch (_) {
return or();
}
}
String _getStringOr(String Function() or) {
try {
return _getString();
} catch (_) {
return or();
}
}
int _getIntOr(int Function() or) {
try {
return _getInt();
} catch (_) {
return or();
}
}
}

View File

@ -0,0 +1 @@
const int kBlocObserverMessageLength = 100;

View File

@ -1,18 +0,0 @@
/// Firebase Emulator constants.
///
/// If you don't use Firebase, it can be safely deleted.
abstract class Emulator {
static const String firebaseCloudFunctionEnvKey =
'EMULATOR_FIREBASE_CLOUD_FUNCTION_PORT';
static const String firebaseFirestoreEnvKey =
'EMULATOR_FIREBASE_FIRESTORE_PORT';
static const String firebaseAuthEnvKey = 'EMULATOR_FIREBASE_AUTH_PORT';
static const String firebaseStorageEnvKey = 'EMULATOR_FIREBASE_STORAGE_PORT';
static const String hostEnvKey = 'EMULATOR_HOST';
static const int defaultFirebaseCloudFunctionPort = 5001;
static const int defaultFirebaseFirestorePort = 8080;
static const int defaultFirebaseAuthPort = 9099;
static const int defaultFirebaseStoragePort = 9199;
static const defaultHost = 'localhost';
}

View File

@ -1,40 +1,56 @@
import 'dart:async';
import 'package:get_it/get_it.dart';
import 'package:starting_template/core/enums/dev_mode.dart';
import 'package:starting_template/core/flavors/flavor.dart';
import 'package:starting_template/data/data_sources/local/counter_data_source_impl.dart';
import 'package:starting_template/domain/data_sources/local/counter_data_source.dart';
import 'package:starting_template/core/enums/data_source_type.dart';
import 'package:starting_template/core/logger/app_logger.dart';
import 'package:starting_template/core/utils/env.dart';
final getIt = GetIt.I;
/// Service and Data Source locator
abstract class GetItInitializer {
static AppLogger get logger => AppLogger('GetItInitializer');
static FutureOr<void> _initCommon() async {
// Initialize common sources/services
getIt.registerLazySingleton<CounterDataSource>(
CounterDataSourceImpl.new,
);
logger.info('Initializing common sources/services');
}
static FutureOr<void> _initMocks() async {
// Initialize mocked sources/services.
static FutureOr<void> _initMock() async {
logger.info('Initializing mock sources');
}
static FutureOr<void> _initReal() async {
// Initialize real sources/services
static FutureOr<void> _initApi() async {
logger.info('Initializing API sources');
}
static FutureOr<void> _initRepositories() async {
logger.info('Initializing repositories');
}
static FutureOr<void> _initUseCases() async {
logger.info('Initializing use cases');
}
static FutureOr<void> init() async {
// Initialize common sources/services
await _initCommon();
final flavor = Flavor.get();
if (flavor.devMode == DevMode.mock) {
await _initMocks();
} else {
await _initReal();
// Initialize sources/services based on data source type
switch (Env.dataSource) {
case DataSourceType.mock:
await _initMock();
break;
case DataSourceType.api:
await _initApi();
break;
}
// Initialize repositories
await _initRepositories();
// Initialize use cases
await _initUseCases();
await getIt.allReady();
}
}

View File

@ -0,0 +1,16 @@
enum DataSourceType {
mock,
api;
static DataSourceType fromString(String value) => DataSourceType.values
.firstWhere((e) => e.name == value.toLowerCase().trim());
static DataSourceType? fromStringOr(String value, {DataSourceType? or}) {
try {
return DataSourceType.values
.firstWhere((e) => e.name == value.toLowerCase().trim());
} catch (_) {
return or;
}
}
}

View File

@ -1,20 +0,0 @@
enum DevMode {
mock,
emulator,
real;
@override
String toString() => name;
/// Tries to parse String and returns mode. Fallback is returned if there
/// is an error during parsing.
static DevMode fromString(String? mode, {DevMode fallback = DevMode.mock}) {
for (final m in values) {
if (m.name == mode) {
return m;
}
}
return fallback;
}
}

View File

@ -0,0 +1,17 @@
enum EnvType {
dev,
staging,
prod;
static EnvType fromString(String value) =>
EnvType.values.firstWhere((e) => e.name == value.toLowerCase().trim());
static EnvType? fromStringOr(String value, {EnvType? or}) {
try {
return EnvType.values
.firstWhere((e) => e.name == value.toLowerCase().trim());
} catch (_) {
return or;
}
}
}

View File

@ -0,0 +1,18 @@
enum FeatureFlag {
logger;
static FeatureFlag fromString(String value) => FeatureFlag.values
.firstWhere((e) => e.name == value.toLowerCase().trim());
static FeatureFlag? fromStringOr(String value, {FeatureFlag? or}) {
try {
return FeatureFlag.values
.firstWhere((e) => e.name == value.toLowerCase().trim());
} catch (_) {
return or;
}
}
@override
String toString() => name;
}

View File

@ -2,5 +2,6 @@ import 'package:flutter/widgets.dart';
import 'package:starting_template/gen/app_localizations.dart';
extension BuildContextExtension on BuildContext {
/// Returns the [AppLocalizations] instance
AppLocalizations get l10n => AppLocalizations.of(this);
}

View File

@ -0,0 +1,19 @@
import 'package:flutter_bloc/flutter_bloc.dart';
extension DebuggableBloc on BlocBase<dynamic> {
static final _showInObserver = Expando<bool>();
bool get showInObserver => _showInObserver[this] ?? true;
set showInObserver(bool value) => _showInObserver[this] = value;
/// Show the bloc in the observer
void show() {
showInObserver = true;
}
/// Hide the bloc from the observer
void hide() {
showInObserver = false;
}
}

View File

@ -0,0 +1,26 @@
import 'package:get_it/get_it.dart';
extension GetItExtension on GetIt {
void injectInterface<T extends Object>(
T instanceToInject, {
String? instanceName,
}) {
registerSingleton(instanceToInject, instanceName: instanceName);
}
void injectRepository<T extends Object>(FactoryFunc<T> func) {
registerLazySingleton(func);
}
void injectDataSource<T extends Object>(FactoryFunc<T> func) {
registerLazySingleton(func);
}
void injectUseCase<T extends Object>(FactoryFunc<T> func) {
registerLazySingleton(func);
}
void injectBloc<T extends Object>(FactoryFunc<T> func) {
registerFactory(func);
}
}

View File

@ -1,57 +0,0 @@
import 'package:flutter/material.dart';
import 'package:starting_template/core/enums/dev_mode.dart';
abstract class Flavor {
Flavor._({
this.banner,
this.bannerColor = Colors.red,
this.devMode,
}) {
_instance = this;
}
static Flavor? _instance;
final String? banner;
final Color bannerColor;
final DevMode? devMode;
/// Returns [Flavor] instance.
static Flavor get() {
if (_instance == null) {
throw Exception('Flavor not initialized!');
}
return _instance!;
}
@override
String toString() => runtimeType.toString().replaceAll('Flavor', '');
}
class DevelopmentFlavor extends Flavor {
factory DevelopmentFlavor() {
const modeString = String.fromEnvironment('dev_mode', defaultValue: 'mock');
final mode = DevMode.fromString(modeString);
return DevelopmentFlavor._(devMode: mode);
}
DevelopmentFlavor._({
required DevMode devMode,
}) : super._(
banner: 'Dev',
devMode: devMode,
);
}
class StagingFlavor extends Flavor {
StagingFlavor()
: super._(
banner: 'Staging',
bannerColor: Colors.green,
);
}
class ProductionFlavor extends Flavor {
ProductionFlavor() : super._();
}

View File

@ -0,0 +1,81 @@
import 'package:logging/logging.dart';
import 'package:starting_template/core/logger/app_logger_plugin.dart';
import 'package:starting_template/core/logger/log_level.dart';
import 'package:starting_template/core/mixins/debuggable.dart';
class AppLogger with Debuggable {
/// Creates a top-level [AppLogger].
factory AppLogger([String namespace = rootNamespace]) {
if (!namespace.startsWith(rootNamespace)) {
namespace = '$rootNamespace.$namespace';
}
return AppLogger.activeLoggers[namespace] ??= AppLogger._(namespace);
}
AppLogger._(String namespace) : _logger = Logger(namespace);
/// The root namespace for all [AppLogger]s.
static const rootNamespace = 'StartingTemplate';
static final Map<String, AppLogger> activeLoggers = {};
String get namespace => _logger.fullName;
final Logger _logger;
AppLogger createChild(String name) {
assert(name.isNotEmpty, 'Name should not be empty');
return AppLogger('$namespace.$name');
}
Level get level => _logger.level;
set level(Level level) {
hierarchicalLoggingEnabled = true;
_logger.level = level;
}
void addPlugin(AppLoggerPlugin plugin) {
_logger.onRecord.listen(plugin.handleLogRecord);
}
/// Logs a [message] at the given [level].
void log(
Level level,
String message, [
Object? error,
StackTrace? stackTrace,
]) {
_logger.log(level, message, error, stackTrace);
}
/// Logs a message with level [LogLevel.verbose].
void verbose(String message, [Object? error, StackTrace? stackTrace]) {
log(LogLevel.verbose, message, error, stackTrace);
}
/// Logs a message with level [LogLevel.debug].
void debug(String message, [Object? error, StackTrace? stackTrace]) {
log(LogLevel.debug, message, error, stackTrace);
}
/// Logs a message with level [LogLevel.info].
void info(String message, [Object? error, StackTrace? stackTrace]) {
log(LogLevel.info, message, error, stackTrace);
}
/// Logs a message with level [LogLevel.warn].
void warn(String message, [Object? error, StackTrace? stackTrace]) {
log(LogLevel.warn, message, error, stackTrace);
}
/// Logs a message with level [LogLevel.error].
void error(String message, [Object? error, StackTrace? stackTrace]) {
log(LogLevel.error, message, error, stackTrace);
}
@override
String get debugName => 'AppLogger';
}

View File

@ -0,0 +1,7 @@
import 'package:logging/logging.dart';
abstract class AppLoggerPlugin {
const AppLoggerPlugin();
void handleLogRecord(LogRecord record);
}

View File

@ -0,0 +1,20 @@
import 'package:logging/logging.dart';
abstract class LogLevel {
static const Level verbose = Level('VERBOSE', 300);
static const Level bloc = Level('BLOC', 450);
static const Level debug = Level('DEBUG', 500);
static const Level info = Level.INFO;
static const Level warn = Level.WARNING;
static const Level error = Level('ERROR', 1000);
static Level fromString(String value) => switch (value.toLowerCase()) {
'verbose' => verbose,
'bloc' => bloc,
'debug' => debug,
'info' => info,
'warn' || 'warning' => warn,
'error' || 'fail' || 'failure' => error,
_ => throw Exception('Unknown log level: $value'),
};
}

View File

@ -0,0 +1,40 @@
import 'package:logging/logging.dart';
import 'package:starting_template/core/logger/app_logger_plugin.dart';
class SimpleLogPrinter implements AppLoggerPlugin {
const SimpleLogPrinter();
/// Formats [LogRecord] using level, namespace, and message components.
static String formatLogRecord(LogRecord record) {
final buffer = StringBuffer()
..write(record.level.name.toUpperCase())
..write(' | ');
final namespace = record.loggerName.split('.').lastOrNull;
if (namespace != null && namespace.isNotEmpty) {
buffer
..write(namespace)
..write(' | ');
}
buffer.write(record.message);
final error = record.error;
if (error != null) {
buffer
..write(': ')
..writeln(error);
}
final stackTrace = record.stackTrace;
if (stackTrace != null) {
buffer.writeln(stackTrace);
}
return buffer.toString();
}
@override
void handleLogRecord(LogRecord record) {
// ignore: avoid_print
print(formatLogRecord(record));
}
}

View File

@ -0,0 +1,3 @@
mixin Debuggable {
String get debugName;
}

View File

@ -0,0 +1,6 @@
import 'package:starting_template/core/logger/app_logger.dart';
import 'package:starting_template/core/mixins/debuggable.dart';
mixin Loggable on Debuggable {
AppLogger get logger => AppLogger().createChild(debugName);
}

View File

@ -0,0 +1,64 @@
import 'package:flutter/cupertino.dart';
import 'package:starting_template/presentation/features/home/home.dart';
import 'package:wyatt_go_router/wyatt_go_router.dart';
abstract class AppRouter {
/// Default transition for all pages
static Page<void> defaultTransition(
BuildContext context,
GoRouterState state,
Widget child,
) =>
CupertinoPage<void>(key: state.pageKey, child: child);
/// Disable transition animation
static Page<void> noTransition(
BuildContext context,
GoRouterState state,
Widget child,
) =>
NoTransitionPage(key: state.pageKey, child: child);
/// Defines GoRoute routes.
static final List<GoRoute> routes = [
GoRoute(
path: '/',
name: Home.pageName,
pageBuilder: (context, state) =>
defaultTransition(context, state, const Home()),
)..setPublic(),
];
/// Singleton instance of [GoRouter]
static GoRouter? _router;
/// Navigator key for the root navigator
static final GlobalKey<NavigatorState> rootNavigatorKey =
GlobalKey<NavigatorState>();
/// Router
static GoRouter routerOf(BuildContext context) => _router ??= GoRouter(
initialLocation: '/',
routes: AppRouter.routes,
navigatorKey: rootNavigatorKey,
debugLogDiagnostics: true,
refreshListenable: GoRouterRefreshStream(const Stream.empty()),
// TODO(wyatt): Add authentication logic
redirect: (context, state) {
/// Define the default guard
/// This is the guard that will be used if the route
/// does not have a guard set. (It is set to [PageProtection.none])
const defaultProtection = PageProtection.protected;
/// Get the current route
final currentRoute = context.currentRoute;
/// Get the guard of the current route
final _ = (currentRoute.protection == PageProtection.none)
? defaultProtection
: currentRoute.protection;
return null;
},
);
}

Some files were not shown because too many files have changed in this diff Show More