feat: add feature template

This commit is contained in:
Hugo Pointcheval 2023-03-03 14:42:11 +01:00
parent 1d1e7637cc
commit ebd8618043
Signed by: hugo
GPG Key ID: 3AAC487E131E00BC
40 changed files with 470 additions and 232 deletions

View File

@ -1,47 +0,0 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Web related
lib/generated_plugin_registrant.dart
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release

View File

@ -1,30 +0,0 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled.
version:
revision: f1875d570e39de09040c8f79aa13cc56baab8db1
channel: stable
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
- platform: android
create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'

View File

@ -1,16 +0,0 @@
# wyatt_feature_brick
A new Flutter project.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.

View File

@ -1,13 +0,0 @@
name: wyatt_feature_brick
description: New feature brick including state mananement
path_to_brickify: lib/feature_name
version: 0.1.1
vars:
feature_name:
type: string
name: feature_name
description: Name of the feature
default: Dash
prompt: What is the name of your new feature

View File

@ -1,2 +0,0 @@
export 'screens/feature_name_provider.dart';
export 'screens/feature_name_screen.dart';

View File

@ -1,115 +0,0 @@
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Invoke "debug painting" (press "p" in the console, choose the
// "Toggle Debug Paint" action from the Flutter Inspector in Android
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
// to see the wireframe for each widget.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}

View File

@ -0,0 +1,16 @@
name: wyatt_feature_template
description: A Wyatt Architecture Feature template
version: 0.1.0
vars:
feature_name:
compilable: feature_name
type: string
description: The feature name
default: Feature Name
prompt: "What is the feature name?"
brickgen:
path_to_brickify: wyatt_feature_template/lib/feature_name
hooks: true

View File

@ -0,0 +1,39 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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,
// 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.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'dart:io';
import 'package:mason/mason.dart';
void removeGitKeepFiles(String targetPath) {
if (!FileSystemEntity.isDirectorySync(targetPath)) {
throw ArgumentError('Target must be a directory', 'targetPath');
}
Directory(targetPath)
.listSync(recursive: true)
.whereType<File>()
.forEach((file) {
if (file.path.contains('.gitkeep')) {
file.deleteSync(recursive: true);
}
});
}
Future<void> run(HookContext context) async {
final workingDirectory = Directory.current.path;
removeGitKeepFiles(workingDirectory);
}

View File

@ -0,0 +1,7 @@
name: hooks
environment:
sdk: ">=2.18.0 <3.0.0"
dependencies:
mason: any

View File

@ -0,0 +1,7 @@
# https://dart.dev/guides/libraries/private-files
# Created by `dart pub`
.dart_tool/
# Avoid committing pubspec.lock for library packages; see
# https://dart.dev/guides/libraries/private-files#pubspeclock.
pubspec.lock

View File

@ -0,0 +1,3 @@
## 1.0.0
- Initial version.

View File

@ -0,0 +1,39 @@
<!--
This README describes the package. If you publish this package to pub.dev,
this README's contents appear on the landing page for your package.
For information about how to write a good package README, see the guide for
[writing package pages](https://dart.dev/guides/libraries/writing-package-pages).
For general information about developing packages, see the Dart guide for
[creating packages](https://dart.dev/guides/libraries/create-library-packages)
and the Flutter guide for
[developing packages and plugins](https://flutter.dev/developing-packages).
-->
TODO: Put a short description of the package here that helps potential users
know whether this package might be useful for them.
## Features
TODO: List what your package can do. Maybe include images, gifs, or videos.
## Getting started
TODO: List prerequisites and provide or point to information on how to
start using the package.
## Usage
TODO: Include short and useful examples for package users. Add longer examples
to `/example` folder.
```dart
const like = 'sample';
```
## Additional information
TODO: Tell users more about the package: where to find more information, how to
contribute to the package, how to file issues, what response they can expect
from the package authors, and more.

View File

@ -12,6 +12,8 @@ class FeatureNameCubit extends Cubit<FeatureNameState> {
/// {@macro feature_name_cubit}
FeatureNameCubit() : super(const FeatureNameInitial());
/// Add your usecases
/// A description for yourCustomFunction
FutureOr<void> yourCustomFunction() async {
// TODO(wyatt): Add custom UI logic

View File

@ -0,0 +1,6 @@
export 'blocs/feature_name_bloc/feature_name_bloc.dart';
export 'screens/feature_name_consumer_widget.dart';
export 'screens/feature_name_provider.dart';
export 'screens/feature_name_screen.dart';
export 'screens/widgets/feature_name_parent.dart';
export 'screens/widgets/feature_name_widget.dart';

View File

@ -3,7 +3,7 @@
import 'package:flutter/material.dart';
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
import '../../blocs/feature_name_cubit/feature_name_cubit.dart';
import '../blocs/feature_name_cubit/feature_name_cubit.dart';
/// {@template feature_name_consumer_widget}
/// FeatureNameConsumerWidget is a stateful widget. Aware of state changes.

View File

@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
import '../blocs/feature_name_cubit/feature_name_cubit.dart';
import 'widgets/feature_name_consumer_widget.dart';
import 'feature_name_consumer_widget.dart';
/// {@template feature_name_provider}
/// FeatureNameProvider provides bloc to his children.

View File

@ -3,9 +3,9 @@
import 'package:flutter/material.dart';
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
import './widgets/feature_name_parent.dart';
import '../blocs/feature_name_cubit/feature_name_cubit.dart';
import '../stateless/feature_name_widget.dart';
import 'feature_name_parent.dart';
import 'widgets/feature_name_widget.dart';
/// {@template feature_name_screen}
/// FeatureNameScreen is the merge of Provider and Consumer.

View File

@ -1,6 +1,10 @@
import 'package:flutter/material.dart';
/// {@template feature_name_parent}
/// FeatureNameParent description
/// {@endtemplate}
class FeatureNameParent extends StatelessWidget {
/// {@macro feature_name_parent}
const FeatureNameParent({
required this.child,
super.key,

View File

@ -0,0 +1,63 @@
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) => MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}

View File

@ -1,11 +1,9 @@
name: wyatt_feature_brick
name: wyatt_feature_template
description: A new Flutter project.
version: 1.0.0+1
publish_to: "none"
version: 1.0.0
environment:
sdk: ">=2.18.0 <3.0.0"
sdk: '>=2.19.2 <3.0.0'
dependencies:
flutter: { sdk: flutter }

View File

@ -0,0 +1,26 @@
import 'dart:async';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
part '{{#snakeCase}}{{feature_name}}{{/snakeCase}}_event.dart';
part '{{#snakeCase}}{{feature_name}}{{/snakeCase}}_state.dart';
/// {@template {{#snakeCase}}{{feature_name}}{{/snakeCase}}_bloc}
/// {{#pascalCase}}{{feature_name}}{{/pascalCase}}Bloc description
/// {@endtemplate}
class {{#pascalCase}}{{feature_name}}{{/pascalCase}}Bloc extends Bloc<{{#pascalCase}}{{feature_name}}{{/pascalCase}}Event, {{#pascalCase}}{{feature_name}}{{/pascalCase}}State> {
/// {@macro {{#snakeCase}}{{feature_name}}{{/snakeCase}}_bloc}
{{#pascalCase}}{{feature_name}}{{/pascalCase}}Bloc() : super(const {{#pascalCase}}{{feature_name}}{{/pascalCase}}Initial()) {
on<Custom{{#pascalCase}}{{feature_name}}{{/pascalCase}}Event>(_onCustom{{#pascalCase}}{{feature_name}}{{/pascalCase}}Event);
}
FutureOr<void> _onCustom{{#pascalCase}}{{feature_name}}{{/pascalCase}}Event(
Custom{{#pascalCase}}{{feature_name}}{{/pascalCase}}Event event,
Emitter<{{#pascalCase}}{{feature_name}}{{/pascalCase}}State> emit,
) async {
// TODO(wyatt): Add custom UI logic
const _ = 1 + 1;
return;
}
}

View File

@ -0,0 +1,20 @@
part of '{{#snakeCase}}{{feature_name}}{{/snakeCase}}_bloc.dart';
/// {@template {{#snakeCase}}{{feature_name}}{{/snakeCase}}_event}
/// {{#pascalCase}}{{feature_name}}{{/pascalCase}}Event description
/// {@endtemplate}
abstract class {{#pascalCase}}{{feature_name}}{{/pascalCase}}Event extends Equatable {
/// {@macro {{#snakeCase}}{{feature_name}}{{/snakeCase}}_event}
const {{#pascalCase}}{{feature_name}}{{/pascalCase}}Event();
}
/// {@template custom_{{#snakeCase}}{{feature_name}}{{/snakeCase}}_event}
/// Event added when some custom logic happens
/// {@endtemplate}
class Custom{{#pascalCase}}{{feature_name}}{{/pascalCase}}Event extends {{#pascalCase}}{{feature_name}}{{/pascalCase}}Event {
/// {@macro custom_{{#snakeCase}}{{feature_name}}{{/snakeCase}}_event}
const Custom{{#pascalCase}}{{feature_name}}{{/pascalCase}}Event();
@override
List<Object?> get props => [];
}

View File

@ -0,0 +1,20 @@
part of '{{#snakeCase}}{{feature_name}}{{/snakeCase}}_bloc.dart';
/// {@template {{#snakeCase}}{{feature_name}}{{/snakeCase}}_state}
/// {{#pascalCase}}{{feature_name}}{{/pascalCase}}State description
/// {@endtemplate}
abstract class {{#pascalCase}}{{feature_name}}{{/pascalCase}}State extends Equatable {
/// {@macro {{#snakeCase}}{{feature_name}}{{/snakeCase}}_state}
const {{#pascalCase}}{{feature_name}}{{/pascalCase}}State();
}
/// {@template {{#snakeCase}}{{feature_name}}{{/snakeCase}}_initial}
/// The initial state of {{#pascalCase}}{{feature_name}}{{/pascalCase}}State
/// {@endtemplate}
class {{#pascalCase}}{{feature_name}}{{/pascalCase}}Initial extends {{#pascalCase}}{{feature_name}}{{/pascalCase}}State {
/// {@macro {{#snakeCase}}{{feature_name}}{{/snakeCase}}_initial}
const {{#pascalCase}}{{feature_name}}{{/pascalCase}}Initial();
@override
List<Object?> get props => [];
}

View File

@ -0,0 +1,23 @@
import 'dart:async';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
part '{{#snakeCase}}{{feature_name}}{{/snakeCase}}_state.dart';
/// {@template {{#snakeCase}}{{feature_name}}{{/snakeCase}}_cubit}
/// {{#pascalCase}}{{feature_name}}{{/pascalCase}}Cubit description
/// {@endtemplate}
class {{#pascalCase}}{{feature_name}}{{/pascalCase}}Cubit extends Cubit<{{#pascalCase}}{{feature_name}}{{/pascalCase}}State> {
/// {@macro {{#snakeCase}}{{feature_name}}{{/snakeCase}}_cubit}
{{#pascalCase}}{{feature_name}}{{/pascalCase}}Cubit() : super(const {{#pascalCase}}{{feature_name}}{{/pascalCase}}Initial());
/// Add your usecases
/// A description for yourCustomFunction
FutureOr<void> yourCustomFunction() async {
// TODO(wyatt): Add custom UI logic
const _ = 1 + 1;
return;
}
}

View File

@ -0,0 +1,20 @@
part of '{{#snakeCase}}{{feature_name}}{{/snakeCase}}_cubit.dart';
/// {@template {{#snakeCase}}{{feature_name}}{{/snakeCase}}_state}
/// {{#pascalCase}}{{feature_name}}{{/pascalCase}}State description
/// {@endtemplate}
abstract class {{#pascalCase}}{{feature_name}}{{/pascalCase}}State extends Equatable {
/// {@macro {{#snakeCase}}{{feature_name}}{{/snakeCase}}_state}
const {{#pascalCase}}{{feature_name}}{{/pascalCase}}State();
}
/// {@template {{#snakeCase}}{{feature_name}}{{/snakeCase}}_initial}
/// The initial state of {{#pascalCase}}{{feature_name}}{{/pascalCase}}State
/// {@endtemplate}
class {{#pascalCase}}{{feature_name}}{{/pascalCase}}Initial extends {{#pascalCase}}{{feature_name}}{{/pascalCase}}State {
/// {@macro {{#snakeCase}}{{feature_name}}{{/snakeCase}}_initial}
const {{#pascalCase}}{{feature_name}}{{/pascalCase}}Initial();
@override
List<Object?> get props => [];
}

View File

@ -0,0 +1,19 @@
import 'package:flutter/material.dart';
/// {@template {{#snakeCase}}{{feature_name}}{{/snakeCase}}_parent}
/// {{#pascalCase}}{{feature_name}}{{/pascalCase}}Parent description
/// {@endtemplate}
class {{#pascalCase}}{{feature_name}}{{/pascalCase}}Parent extends StatelessWidget {
/// {@macro {{#snakeCase}}{{feature_name}}{{/snakeCase}}_parent}
const {{#pascalCase}}{{feature_name}}{{/pascalCase}}Parent({
required this.child,
super.key,
});
final Widget child;
@override
Widget build(BuildContext context) => Scaffold(
body: SafeArea(child: child),
);
}

View File

@ -0,0 +1,12 @@
import 'package:flutter/material.dart';
/// {@template {{#snakeCase}}{{feature_name}}{{/snakeCase}}_widget}
/// {{#pascalCase}}{{feature_name}}{{/pascalCase}}Widget is a stateless widget. (Not aware of cubit or bloc states)
/// {@endtemplate}
class {{#pascalCase}}{{feature_name}}{{/pascalCase}}Widget extends StatelessWidget {
/// {@macro {{#snakeCase}}{{feature_name}}{{/snakeCase}}_widget}
const {{#pascalCase}}{{feature_name}}{{/pascalCase}}Widget({super.key});
@override
Widget build(BuildContext context) => Container();
}

View File

@ -0,0 +1,18 @@
// ignore_for_file: always_use_package_imports
import 'package:flutter/material.dart';
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
import '../blocs/{{#snakeCase}}{{feature_name}}{{/snakeCase}}_cubit/{{#snakeCase}}{{feature_name}}{{/snakeCase}}_cubit.dart';
/// {@template {{#snakeCase}}{{feature_name}}{{/snakeCase}}_consumer_widget}
/// {{#pascalCase}}{{feature_name}}{{/pascalCase}}ConsumerWidget is a stateful widget. Aware of state changes.
/// {@endtemplate}
class {{#pascalCase}}{{feature_name}}{{/pascalCase}}ConsumerWidget
extends CubitConsumerScreen<{{#pascalCase}}{{feature_name}}{{/pascalCase}}Cubit, {{#pascalCase}}{{feature_name}}{{/pascalCase}}State> {
/// {@macro {{#snakeCase}}{{feature_name}}{{/snakeCase}}_consumer_widget}
const {{#pascalCase}}{{feature_name}}{{/pascalCase}}ConsumerWidget({super.key});
@override
Widget onBuild(BuildContext context, {{#pascalCase}}{{feature_name}}{{/pascalCase}}State state) => Container();
}

View File

@ -0,0 +1,22 @@
// ignore_for_file: always_use_package_imports
import 'package:flutter/material.dart';
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
import '../blocs/{{#snakeCase}}{{feature_name}}{{/snakeCase}}_cubit/{{#snakeCase}}{{feature_name}}{{/snakeCase}}_cubit.dart';
import '{{#snakeCase}}{{feature_name}}{{/snakeCase}}_consumer_widget.dart';
/// {@template {{#snakeCase}}{{feature_name}}{{/snakeCase}}_provider}
/// {{#pascalCase}}{{feature_name}}{{/pascalCase}}Provider provides bloc to his children.
/// {@endtemplate}
class {{#pascalCase}}{{feature_name}}{{/pascalCase}}Provider
extends CubitProviderScreen<{{#pascalCase}}{{feature_name}}{{/pascalCase}}Cubit, {{#pascalCase}}{{feature_name}}{{/pascalCase}}State> {
/// {@macro {{#snakeCase}}{{feature_name}}{{/snakeCase}}_provider}
const {{#pascalCase}}{{feature_name}}{{/pascalCase}}Provider({super.key});
@override
{{#pascalCase}}{{feature_name}}{{/pascalCase}}Cubit create(BuildContext context) => {{#pascalCase}}{{feature_name}}{{/pascalCase}}Cubit();
@override
Widget builder(BuildContext context) => const {{#pascalCase}}{{feature_name}}{{/pascalCase}}ConsumerWidget();
}

View File

@ -0,0 +1,33 @@
// ignore_for_file: always_use_package_imports
import 'package:flutter/material.dart';
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
import './widgets/{{#snakeCase}}{{feature_name}}{{/snakeCase}}_parent.dart';
import '../blocs/{{#snakeCase}}{{feature_name}}{{/snakeCase}}_cubit/{{#snakeCase}}{{feature_name}}{{/snakeCase}}_cubit.dart';
import 'widgets/{{#snakeCase}}{{feature_name}}{{/snakeCase}}_widget.dart';
/// {@template {{#snakeCase}}{{feature_name}}{{/snakeCase}}_screen}
/// {{#pascalCase}}{{feature_name}}{{/pascalCase}}Screen is the merge of Provider and Consumer.
/// {@endtemplate}
class {{#pascalCase}}{{feature_name}}{{/pascalCase}}Screen
extends CubitScreen<{{#pascalCase}}{{feature_name}}{{/pascalCase}}Cubit, {{#pascalCase}}{{feature_name}}{{/pascalCase}}State> {
/// {@macro {{#snakeCase}}{{feature_name}}{{/snakeCase}}_screen}
const {{#pascalCase}}{{feature_name}}{{/pascalCase}}Screen({super.key});
@override
{{#pascalCase}}{{feature_name}}{{/pascalCase}}Cubit create(BuildContext context) => {{#pascalCase}}{{feature_name}}{{/pascalCase}}Cubit();
@override
{{#pascalCase}}{{feature_name}}{{/pascalCase}}Cubit init(BuildContext context, {{#pascalCase}}{{feature_name}}{{/pascalCase}}Cubit bloc) =>
bloc..yourCustomFunction();
@override
Widget parent(BuildContext context, Widget child) =>
{{#pascalCase}}{{feature_name}}{{/pascalCase}}Parent(child: child);
// Rebuild on every bloc changes
@override
Widget onBuild(BuildContext context, {{#pascalCase}}{{feature_name}}{{/pascalCase}}State state) =>
const {{#pascalCase}}{{feature_name}}{{/pascalCase}}Widget();
}

View File

@ -0,0 +1,6 @@
export 'blocs/{{#snakeCase}}{{feature_name}}{{/snakeCase}}_bloc/{{#snakeCase}}{{feature_name}}{{/snakeCase}}_bloc.dart';
export 'screens/{{#snakeCase}}{{feature_name}}{{/snakeCase}}_consumer_widget.dart';
export 'screens/{{#snakeCase}}{{feature_name}}{{/snakeCase}}_provider.dart';
export 'screens/{{#snakeCase}}{{feature_name}}{{/snakeCase}}_screen.dart';
export 'screens/widgets/{{#snakeCase}}{{feature_name}}{{/snakeCase}}_parent.dart';
export 'screens/widgets/{{#snakeCase}}{{feature_name}}{{/snakeCase}}_widget.dart';

View File

@ -0,0 +1,12 @@
name: wyatt_feature_template
description: A Wyatt Architecture Feature template
version: 0.1.0
vars:
feature_name:
type: string
description: The feature name
default: Feature Name
prompt: What is the feature name?

View File

@ -0,0 +1,39 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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,
// 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.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'dart:io';
import 'package:mason/mason.dart';
void removeGitKeepFiles(String targetPath) {
if (!FileSystemEntity.isDirectorySync(targetPath)) {
throw ArgumentError('Target must be a directory', 'targetPath');
}
Directory(targetPath)
.listSync(recursive: true)
.whereType<File>()
.forEach((file) {
if (file.path.contains('.gitkeep')) {
file.deleteSync(recursive: true);
}
});
}
Future<void> run(HookContext context) async {
final workingDirectory = Directory.current.path;
removeGitKeepFiles(workingDirectory);
}

View File

@ -0,0 +1,7 @@
name: hooks
environment:
sdk: ">=2.18.0 <3.0.0"
dependencies:
mason: any