├── .gitignore ├── __brick__ ├── lib │ ├── feature │ │ └── home │ │ │ ├── model │ │ │ └── .gitkeep │ │ │ ├── view_model │ │ │ └── .gitkeep │ │ │ └── view │ │ │ └── home_view.dart │ ├── app │ │ ├── constants │ │ │ └── string_constants.dart │ │ ├── l10n │ │ │ ├── arb │ │ │ │ ├── app_en.arb │ │ │ │ └── app_tr.arb │ │ │ └── l10n.dart │ │ ├── environment │ │ │ ├── app_environment.dart │ │ │ ├── production_environment.dart │ │ │ └── development_environment.dart │ │ ├── theme │ │ │ ├── base │ │ │ │ └── base_theme.dart │ │ │ ├── dark │ │ │ │ └── dark_theme.dart │ │ │ └── light │ │ │ │ └── light_theme.dart │ │ ├── router │ │ │ ├── app_router.dart │ │ │ └── custom_route_observer.dart │ │ └── view │ │ │ └── app.dart │ ├── main_production.dart │ ├── main_development.dart │ ├── core │ │ ├── utils │ │ │ ├── package_info │ │ │ │ └── package_info_utils.dart │ │ │ ├── logger │ │ │ │ └── logger_utils.dart │ │ │ └── device_info │ │ │ │ └── device_info_utils.dart │ │ ├── extensions │ │ │ └── context_extensions.dart │ │ └── clients │ │ │ └── network │ │ │ └── network_client.dart │ ├── locator.dart │ └── bootstrap.dart ├── scripts │ ├── pub_get.sh │ ├── flutter_gen.sh │ └── build_runner.sh ├── environment │ ├── .development.env │ └── .production.env ├── assets │ ├── fonts │ │ └── .gitkeep │ └── icons │ │ └── flutter.png ├── l10n.yaml ├── analysis_options.yaml ├── .vscode │ └── launch.json ├── .gitignore └── pubspec.yaml ├── hooks ├── .gitignore ├── pubspec.yaml ├── pre_gen.dart └── post_gen.dart ├── analysis_options.yaml ├── brick.yaml ├── LICENSE ├── CHANGELOG.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .DS_Store -------------------------------------------------------------------------------- /__brick__/lib/feature/home/model/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /__brick__/scripts/pub_get.sh: -------------------------------------------------------------------------------- 1 | flutter pub get -------------------------------------------------------------------------------- /__brick__/lib/feature/home/view_model/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /__brick__/environment/.development.env: -------------------------------------------------------------------------------- 1 | BASE_URL = '' -------------------------------------------------------------------------------- /__brick__/environment/.production.env: -------------------------------------------------------------------------------- 1 | BASE_URL = '' -------------------------------------------------------------------------------- /__brick__/assets/fonts/.gitkeep: -------------------------------------------------------------------------------- 1 | Add your fonts under this folder -------------------------------------------------------------------------------- /hooks/.gitignore: -------------------------------------------------------------------------------- 1 | .dart_tool 2 | .packages 3 | pubspec.lock 4 | build -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | analyzer: 2 | exclude: 3 | - __brick__/** 4 | -------------------------------------------------------------------------------- /__brick__/scripts/flutter_gen.sh: -------------------------------------------------------------------------------- 1 | dart pub global activate flutter_gen 2 | fluttergen 3 | -------------------------------------------------------------------------------- /__brick__/scripts/build_runner.sh: -------------------------------------------------------------------------------- 1 | dart run build_runner build --delete-conflicting-outputs -------------------------------------------------------------------------------- /__brick__/assets/icons/flutter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cem256/starter_template/HEAD/__brick__/assets/icons/flutter.png -------------------------------------------------------------------------------- /hooks/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: starter_template 2 | 3 | environment: 4 | sdk: ">=3.0.0 <4.0.0" 5 | 6 | dependencies: 7 | mason: ^0.1.0-dev.59 8 | -------------------------------------------------------------------------------- /__brick__/lib/app/constants/string_constants.dart: -------------------------------------------------------------------------------- 1 | final class StringConstants { 2 | StringConstants._(); 3 | 4 | static const String appName = '{{project_name.titleCase()}}'; 5 | } 6 | -------------------------------------------------------------------------------- /__brick__/lib/app/l10n/arb/app_en.arb: -------------------------------------------------------------------------------- 1 | { 2 | "flutter": "Flutter", 3 | "@flutter": { 4 | "description": "Displays text Flutter", 5 | "type": "text", 6 | "placeholders": {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /__brick__/lib/app/l10n/arb/app_tr.arb: -------------------------------------------------------------------------------- 1 | { 2 | "flutter": "Flutter", 3 | "@flutter": { 4 | "description": "Displays text Flutter", 5 | "type": "text", 6 | "placeholders": {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /__brick__/l10n.yaml: -------------------------------------------------------------------------------- 1 | arb-dir: lib/app/l10n/arb 2 | template-arb-file: app_en.arb 3 | output-localization-file: app_localizations.dart 4 | untranslated-messages-file: lib/app/l10n/arb/untranslated_translations.json 5 | nullable-getter: false 6 | -------------------------------------------------------------------------------- /__brick__/lib/app/environment/app_environment.dart: -------------------------------------------------------------------------------- 1 | abstract interface class AppEnvironment { 2 | static const String developmentPath = 'environment/.development.env'; 3 | static const String productionPath = 'environment/.production.env'; 4 | 5 | abstract final String baseUrl; 6 | } 7 | -------------------------------------------------------------------------------- /__brick__/lib/app/l10n/l10n.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; 3 | 4 | export 'package:flutter_gen/gen_l10n/app_localizations.dart'; 5 | 6 | extension AppLocalizationsX on BuildContext { 7 | AppLocalizations get l10n => AppLocalizations.of(this); 8 | } 9 | -------------------------------------------------------------------------------- /__brick__/lib/main_production.dart: -------------------------------------------------------------------------------- 1 | import 'package:{{project_name.snakeCase()}}/app/environment/production_environment.dart'; 2 | import 'package:{{project_name.snakeCase()}}/app/view/app.dart'; 3 | import 'package:{{project_name.snakeCase()}}/bootstrap.dart'; 4 | 5 | Future main() async { 6 | await bootstrap(builder: App.new, environment: ProductionEnvironment()); 7 | } 8 | -------------------------------------------------------------------------------- /__brick__/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:very_good_analysis/analysis_options.6.0.0.yaml 2 | analyzer: 3 | exclude: 4 | - "**.g.dart" 5 | - "**.gr.dart" 6 | - "**.freezed.dart" 7 | linter: 8 | rules: 9 | sort_pub_dependencies: false 10 | public_member_api_docs: false 11 | lines_longer_than_80_chars: false 12 | flutter_style_todos: false 13 | -------------------------------------------------------------------------------- /__brick__/lib/main_development.dart: -------------------------------------------------------------------------------- 1 | import 'package:{{project_name.snakeCase()}}/app/environment/development_environment.dart'; 2 | import 'package:{{project_name.snakeCase()}}/app/view/app.dart'; 3 | import 'package:{{project_name.snakeCase()}}/bootstrap.dart'; 4 | 5 | Future main() async { 6 | await bootstrap(builder: App.new, environment: DevelopmentEnvironment()); 7 | } 8 | -------------------------------------------------------------------------------- /__brick__/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Main Development", 6 | "type": "dart", 7 | "request": "launch", 8 | "program": "lib/main_development.dart" 9 | }, 10 | { 11 | "name": "Main Production", 12 | "type": "dart", 13 | "request": "launch", 14 | "program": "lib/main_production.dart" 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /__brick__/lib/app/theme/base/base_theme.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | abstract class BaseTheme { 4 | Brightness get brightness; 5 | ColorScheme get colorScheme; 6 | 7 | ThemeData get theme { 8 | return ThemeData( 9 | useMaterial3: true, 10 | brightness: brightness, 11 | colorScheme: colorScheme, 12 | //TODO: Customize widgets here 13 | typography: Typography.material2021(), 14 | ); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /__brick__/lib/app/environment/production_environment.dart: -------------------------------------------------------------------------------- 1 | import 'package:envied/envied.dart'; 2 | import 'package:{{project_name.snakeCase()}}/app/environment/app_environment.dart'; 3 | 4 | part 'production_environment.g.dart'; 5 | 6 | @Envied(obfuscate: true, path: AppEnvironment.productionPath) 7 | final class ProductionEnvironment implements AppEnvironment { 8 | ProductionEnvironment(); 9 | 10 | @override 11 | @EnviedField(varName: 'BASE_URL') 12 | final String baseUrl = _ProductionEnvironment.baseUrl; 13 | } 14 | -------------------------------------------------------------------------------- /__brick__/lib/app/environment/development_environment.dart: -------------------------------------------------------------------------------- 1 | import 'package:envied/envied.dart'; 2 | import 'package:{{project_name.snakeCase()}}/app/environment/app_environment.dart'; 3 | 4 | part 'development_environment.g.dart'; 5 | 6 | @Envied(obfuscate: true, path: AppEnvironment.developmentPath) 7 | final class DevelopmentEnvironment implements AppEnvironment { 8 | DevelopmentEnvironment(); 9 | 10 | @override 11 | @EnviedField(varName: 'BASE_URL') 12 | final String baseUrl = _DevelopmentEnvironment.baseUrl; 13 | } 14 | -------------------------------------------------------------------------------- /__brick__/lib/core/utils/package_info/package_info_utils.dart: -------------------------------------------------------------------------------- 1 | import 'package:package_info_plus/package_info_plus.dart'; 2 | 3 | final class PackageInfoUtils { 4 | PackageInfoUtils._(); 5 | 6 | static late final PackageInfo _packageInfo; 7 | 8 | static Future init() async { 9 | _packageInfo = await PackageInfo.fromPlatform(); 10 | } 11 | 12 | static String getAppVersion() { 13 | return _packageInfo.version; 14 | } 15 | 16 | static String getAppName() { 17 | return _packageInfo.appName; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /__brick__/lib/app/router/app_router.dart: -------------------------------------------------------------------------------- 1 | import 'package:auto_route/auto_route.dart'; 2 | import 'package:{{project_name.snakeCase()}}/app/router/app_router.gr.dart'; 3 | 4 | @AutoRouterConfig(replaceInRouteName: 'View,Route') 5 | 6 | /// Holds all the routes that are defined in the app 7 | /// Used to generate the Router object 8 | final class AppRouter extends RootStackRouter { 9 | @override 10 | List get routes => [ 11 | // TODO: Add routes here 12 | AutoRoute( 13 | initial: true, 14 | page: HomeRoute.page, 15 | ), 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /brick.yaml: -------------------------------------------------------------------------------- 1 | name: starter_template 2 | description: A Flutter starter app that includes support for an HTTP client, themes, routing, localization, and dependency injection. 3 | repository: https://github.com/cem256/starter_template 4 | 5 | version: 1.2.2+18 6 | 7 | environment: 8 | mason: ^0.1.0 9 | 10 | vars: 11 | project_name: 12 | type: string 13 | description: Project name 14 | default: Starter Template 15 | prompt: Enter the name of your project 16 | description: 17 | type: string 18 | description: Project description 19 | default: A new Flutter project. 20 | prompt: Enter the description of your project 21 | organization: 22 | type: string 23 | description: Organization of the project 24 | default: com.example 25 | prompt: Enter your organization name 26 | -------------------------------------------------------------------------------- /__brick__/lib/core/utils/logger/logger_utils.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: prefer_constructors_over_static_methods 2 | 3 | import 'package:logger/logger.dart'; 4 | 5 | class LoggerUtils { 6 | LoggerUtils._(); 7 | 8 | static LoggerUtils? _instance; 9 | 10 | static LoggerUtils get instance { 11 | _instance ??= LoggerUtils._(); 12 | return _instance!; 13 | } 14 | 15 | final Logger _logger = Logger(printer: PrettyPrinter(stackTraceBeginIndex: 2)); 16 | 17 | void logInfo(String message) { 18 | _logger.i(message); 19 | } 20 | 21 | void logWarning(String message) { 22 | _logger.w(message); 23 | } 24 | 25 | void logError(String message) { 26 | _logger.e(message); 27 | } 28 | 29 | void logFatalError(String message, StackTrace? stackTrace) { 30 | _logger.f(message, stackTrace: stackTrace); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /hooks/pre_gen.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'package:mason/mason.dart'; 3 | 4 | Future run(HookContext context) async { 5 | final progress = context.logger.progress("Running 'flutter create'"); 6 | 7 | try { 8 | await _createFlutterApp(context); 9 | progress.complete("Flutter App created!"); 10 | } catch (e) { 11 | progress.fail("Something went wrong while running 'flutter create' : $e"); 12 | } 13 | } 14 | 15 | Future _createFlutterApp(HookContext context) async { 16 | String projectName = context.vars["project_name"]; 17 | projectName = projectName.snakeCase; 18 | final description = context.vars["description"] as String; 19 | final organization = context.vars["organization"] as String; 20 | 21 | return Process.run( 22 | "flutter", 23 | [ 24 | "create", 25 | projectName, 26 | "--description", 27 | description, 28 | "--org", 29 | organization, 30 | ], 31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /__brick__/lib/feature/home/view/home_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:auto_route/auto_route.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:{{project_name.snakeCase()}}/app/l10n/l10n.dart'; 4 | import 'package:{{project_name.snakeCase()}}/core/extensions/context_extensions.dart'; 5 | import 'package:{{project_name.snakeCase()}}/generated/assets.gen.dart'; 6 | 7 | @RoutePage() 8 | class HomeView extends StatelessWidget { 9 | const HomeView({super.key}); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return Scaffold( 14 | appBar: AppBar( 15 | title: Text( 16 | context.l10n.flutter, 17 | ), 18 | ), 19 | body: Padding( 20 | padding: context.paddingAllDefault, 21 | child: Column( 22 | mainAxisAlignment: MainAxisAlignment.center, 23 | children: [ 24 | Assets.icons.flutter.image(), 25 | ], 26 | ), 27 | ), 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /__brick__/lib/locator.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:get_it/get_it.dart'; 4 | import 'package:{{project_name.snakeCase()}}/app/environment/app_environment.dart'; 5 | import 'package:{{project_name.snakeCase()}}/core/clients/network/network_client.dart'; 6 | 7 | /// [Locator] is responsible for locating and registering all the 8 | /// services of the application. 9 | abstract final class Locator { 10 | /// [GetIt] instance 11 | @visibleForTesting 12 | static final instance = GetIt.instance; 13 | 14 | /// Returns instance of [NetworkClient] 15 | static NetworkClient get networkClient => instance(); 16 | 17 | /// Responsible for registering all the dependencies 18 | static Future locateServices({required AppEnvironment environment}) async { 19 | instance 20 | // Clients 21 | ..registerLazySingleton(() => NetworkClient(dio: instance(), baseUrl: environment.baseUrl)) 22 | // Client Dependencies 23 | ..registerFactory(Dio.new); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /__brick__/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | .swiftpm/ 12 | migrate_working_dir/ 13 | 14 | # IntelliJ related 15 | *.iml 16 | *.ipr 17 | *.iws 18 | .idea/ 19 | 20 | # The .vscode folder contains launch configuration and tasks you configure in 21 | # VS Code which you may wish to be included in version control, so this line 22 | # is commented out by default. 23 | #.vscode/ 24 | 25 | # Flutter/Dart/Pub related 26 | **/doc/api/ 27 | **/ios/Flutter/.last_build_id 28 | .dart_tool/ 29 | .flutter-plugins 30 | .flutter-plugins-dependencies 31 | .packages 32 | .pub-cache/ 33 | .pub/ 34 | /build/ 35 | 36 | # Symbolication related 37 | app.*.symbols 38 | 39 | # Obfuscation related 40 | app.*.map.json 41 | 42 | # Android Studio will place build artifacts here 43 | /android/app/debug 44 | /android/app/profile 45 | /android/app/release 46 | 47 | # generated files 48 | *.g.dart 49 | *.gr.dart 50 | *.freezed.dart 51 | *.config.dart 52 | 53 | # environment variables 54 | # /environment/ 55 | 56 | 57 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Cem Avcı 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /__brick__/lib/app/view/app.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:{{project_name.snakeCase()}}/app/constants/string_constants.dart'; 3 | import 'package:{{project_name.snakeCase()}}/app/l10n/l10n.dart'; 4 | import 'package:{{project_name.snakeCase()}}/app/router/app_router.dart'; 5 | import 'package:{{project_name.snakeCase()}}/app/router/custom_route_observer.dart'; 6 | import 'package:{{project_name.snakeCase()}}/app/theme/dark/dark_theme.dart'; 7 | import 'package:{{project_name.snakeCase()}}/app/theme/light/light_theme.dart'; 8 | 9 | class App extends StatelessWidget { 10 | App({super.key}); 11 | 12 | final _appRouter = AppRouter(); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp.router( 17 | // App Name 18 | title: StringConstants.appName, 19 | 20 | // Theme 21 | theme: LightTheme().theme, 22 | darkTheme: DarkTheme().theme, 23 | 24 | // Localization 25 | localizationsDelegates: AppLocalizations.localizationsDelegates, 26 | supportedLocales: AppLocalizations.supportedLocales, 27 | 28 | // Routing 29 | routerConfig: _appRouter.config( 30 | navigatorObservers: () => [CustomRouteObserver()], 31 | ), 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /__brick__/lib/bootstrap.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:{{project_name.snakeCase()}}/app/environment/app_environment.dart'; 5 | import 'package:{{project_name.snakeCase()}}/core/utils/device_info/device_info_utils.dart'; 6 | import 'package:{{project_name.snakeCase()}}/core/utils/logger/logger_utils.dart'; 7 | import 'package:{{project_name.snakeCase()}}/core/utils/package_info/package_info_utils.dart'; 8 | import 'package:{{project_name.snakeCase()}}/locator.dart'; 9 | 10 | Future bootstrap({required FutureOr Function() builder, required AppEnvironment environment}) async { 11 | FlutterError.onError = (details) { 12 | LoggerUtils.instance.logFatalError(details.exceptionAsString(), details.stack); 13 | }; 14 | await runZonedGuarded>( 15 | () async { 16 | WidgetsFlutterBinding.ensureInitialized(); 17 | // Initialize Locator and Utils 18 | await Future.wait([ 19 | Locator.locateServices(environment: environment), 20 | PackageInfoUtils.init(), 21 | DeviceInfoUtils.init(), 22 | ]); 23 | 24 | runApp(await builder()); 25 | }, 26 | (error, stackTrace) { 27 | LoggerUtils.instance.logFatalError(error.toString(), stackTrace); 28 | }, 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /__brick__/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: {{project_name.snakeCase()}} 2 | description: {{description.sentenceCase()}} 3 | 4 | publish_to: "none" # Remove this line if you wish to publish to pub.dev 5 | 6 | version: 1.0.0+1 7 | 8 | environment: 9 | sdk: ">=3.0.0 <4.0.0" 10 | 11 | dependencies: 12 | flutter: 13 | sdk: flutter 14 | 15 | # Localization 16 | flutter_localizations: 17 | sdk: flutter 18 | 19 | # Networking 20 | dio: ^5.7.0 21 | dio_smart_retry: ^7.0.1 22 | pretty_dio_logger: ^1.4.0 23 | 24 | # Routing 25 | auto_route: ^9.2.2 26 | 27 | # Utility 28 | uuid: ^4.5.1 29 | intl: ^0.19.0 30 | logger: ^2.4.0 31 | envied: ^1.1.0 32 | package_info_plus: ^8.0.2 33 | device_info_plus: ^11.2.1 34 | 35 | # Dependency Injection 36 | get_it: ^8.0.0 37 | 38 | dev_dependencies: 39 | flutter_test: 40 | sdk: flutter 41 | # Linter 42 | very_good_analysis: ^7.0.0 43 | 44 | # Asset Generation 45 | flutter_gen_runner: ^5.8.0 46 | 47 | # Code Generation 48 | build_runner: ^2.4.13 49 | envied_generator: ^1.1.0 50 | auto_route_generator: ^9.0.0 51 | 52 | flutter_gen: 53 | output: lib/app/generated/ 54 | line_length: 120 55 | 56 | # Optional 57 | integrations: 58 | flutter_svg: true 59 | flare_flutter: false 60 | rive: false 61 | lottie: false 62 | 63 | flutter: 64 | generate: true 65 | uses-material-design: true 66 | 67 | assets: 68 | - assets/fonts/ 69 | - assets/icons/ 70 | -------------------------------------------------------------------------------- /__brick__/lib/app/theme/dark/dark_theme.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:{{project_name.snakeCase()}}/app/theme/base/base_theme.dart'; 3 | 4 | final class DarkTheme extends BaseTheme { 5 | @override 6 | Brightness get brightness => Brightness.dark; 7 | 8 | @override 9 | ColorScheme get colorScheme => _colorScheme; 10 | 11 | ColorScheme get _colorScheme { 12 | return const ColorScheme( 13 | brightness: Brightness.dark, 14 | primary: Color(0xffbb86fc), 15 | onPrimary: Color(0xff120e14), 16 | primaryContainer: Color(0xff6200ee), 17 | onPrimaryContainer: Color(0xffefdfff), 18 | secondary: Color(0xff03dac6), 19 | onSecondary: Color(0xff041413), 20 | secondaryContainer: Color(0xff003e3e), 21 | onSecondaryContainer: Color(0xffdfe9e9), 22 | tertiary: Color(0xff03dac6), 23 | onTertiary: Color(0xff041413), 24 | tertiaryContainer: Color(0xff005047), 25 | onTertiaryContainer: Color(0xffdfecea), 26 | error: Color(0xffcf6679), 27 | onError: Color(0xff140c0d), 28 | errorContainer: Color(0xffb1384e), 29 | onErrorContainer: Color(0xfffbe8ec), 30 | surface: Color(0xff19161c), 31 | onSurface: Color(0xffececed), 32 | onSurfaceVariant: Color(0xffe0e0e1), 33 | outline: Color(0xff76767d), 34 | outlineVariant: Color(0xff2c2c2e), 35 | shadow: Color(0xff000000), 36 | scrim: Color(0xff000000), 37 | inverseSurface: Color(0xfffbf8fe), 38 | onInverseSurface: Color(0xff131313), 39 | inversePrimary: Color(0xff5f4876), 40 | surfaceTint: Color(0xffbb86fc), 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /__brick__/lib/app/theme/light/light_theme.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:{{project_name.snakeCase()}}/app/theme/base/base_theme.dart'; 3 | 4 | final class LightTheme extends BaseTheme { 5 | @override 6 | Brightness get brightness => Brightness.light; 7 | 8 | @override 9 | ColorScheme get colorScheme => _colorScheme; 10 | 11 | ColorScheme get _colorScheme { 12 | return const ColorScheme( 13 | brightness: Brightness.light, 14 | primary: Color(0xff6200ee), 15 | onPrimary: Color(0xffffffff), 16 | primaryContainer: Color(0xffbb86fc), 17 | onPrimaryContainer: Color(0xff100c14), 18 | secondary: Color(0xff018786), 19 | onSecondary: Color(0xffffffff), 20 | secondaryContainer: Color(0xffa4f1ef), 21 | onSecondaryContainer: Color(0xff0e1414), 22 | tertiary: Color(0xff03dac6), 23 | onTertiary: Color(0xff000000), 24 | tertiaryContainer: Color(0xffcefaf8), 25 | onTertiaryContainer: Color(0xff111414), 26 | error: Color(0xffb00020), 27 | onError: Color(0xffffffff), 28 | errorContainer: Color(0xfffcd8df), 29 | onErrorContainer: Color(0xff141213), 30 | surface: Color(0xfffaf8fe), 31 | onSurface: Color(0xff090909), 32 | onSurfaceVariant: Color(0xff121112), 33 | outline: Color(0xff7c7c7c), 34 | outlineVariant: Color(0xffc8c8c8), 35 | shadow: Color(0xff000000), 36 | scrim: Color(0xff000000), 37 | inverseSurface: Color(0xff131017), 38 | onInverseSurface: Color(0xfff5f5f5), 39 | inversePrimary: Color(0xffda99ff), 40 | surfaceTint: Color(0xff6200ee), 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /__brick__/lib/core/utils/device_info/device_info_utils.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:device_info_plus/device_info_plus.dart'; 4 | import 'package:flutter/foundation.dart' show kIsWeb; 5 | import 'package:uuid/uuid.dart'; 6 | 7 | final class DeviceInfoUtils { 8 | DeviceInfoUtils._(); 9 | 10 | static late final DeviceInfoPlugin _deviceInfo; 11 | 12 | static Future init() async { 13 | _deviceInfo = DeviceInfoPlugin(); 14 | } 15 | 16 | static Future getDeviceId() async { 17 | if (Platform.isIOS) { 18 | final iosDeviceInfo = await _deviceInfo.iosInfo; 19 | return iosDeviceInfo.identifierForVendor; 20 | } else if (Platform.isAndroid) { 21 | final androidDeviceInfo = await _deviceInfo.androidInfo; 22 | return androidDeviceInfo.id; 23 | } else if (kIsWeb) { 24 | return const Uuid().v4(); 25 | } else { 26 | return null; 27 | } 28 | } 29 | 30 | static Future getDeviceInfo() async { 31 | if (Platform.isIOS) { 32 | final iosDeviceInfo = await _deviceInfo.iosInfo; 33 | return iosDeviceInfo.utsname.machine; 34 | } else if (Platform.isAndroid) { 35 | final androidDeviceInfo = await _deviceInfo.androidInfo; 36 | return androidDeviceInfo.model; 37 | } else if (kIsWeb) { 38 | final webBrowserInfo = await _deviceInfo.webBrowserInfo; 39 | return webBrowserInfo.platform; 40 | } else { 41 | return null; 42 | } 43 | } 44 | 45 | static String getPlatformName() { 46 | if (Platform.isIOS) { 47 | return 'IOS'; 48 | } else if (Platform.isAndroid) { 49 | return 'ANDROID'; 50 | } else if (kIsWeb) { 51 | return 'WEB'; 52 | } else { 53 | return 'UNKNOWN'; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 1.2.2 2 | - Fixed the generated files location for flutter_gen 3 | 4 | # 1.2.1 5 | - Added compatibility with Flutter 3.27.3 to README.md 6 | 7 | # 1.2.0 8 | - Bumped mason to v0.1.0 9 | - Bumped flutter version to v3.27.3 10 | - Bumped dependencies to the major versions 11 | - Added [flutter_gen](https://pub.dev/packages/flutter_gen) for asset generation 12 | 13 | # 1.1.12 14 | - Bumped dependencies to the latest versions 15 | 16 | # 1.1.11 17 | - Added logging config for CustomRouteObserver #10 18 | 19 | # 1.1.10 20 | - bumped mason to v0.1.0-dev.59 21 | 22 | # 1.1.9 23 | - Migrated auto_route to v9.2.0 24 | - Bumped very_good_analysis to v6.0.0 25 | 26 | # 1.1.8 27 | - Migrated to flutter 3.22 28 | - Added [logger](https://pub.dev/packages/logger) as a logging tool 29 | - Added a custom navigatorObserver to track route changes 30 | 31 | # 1.1.7 32 | - Upgraded dependencies to the latest versions 33 | - Added untranslated-messages-file parameter to l10n.yaml 34 | 35 | # 1.1.6 36 | - Removed /environment folder from .gitignore to resolve build_runner issues. 37 | 38 | # 1.1.5 39 | - Refactored post gen hook 40 | 41 | # 1.1.4 42 | - Added output section to README.md 43 | 44 | # 1.1.3 45 | - Added multi-environment setup using [envied](https://pub.dev/packages/envied) 46 | - Removed [injectable](https://pub.dev/packages/injectable) because it reduced the flexibility of the environment setup. 47 | 48 | # 1.1.2 49 | - Added package info utils 50 | - Added device info utils 51 | 52 | # 1.1.1 53 | - Upgraded dependencies to the latest versions 54 | 55 | # 1.1.0 56 | - Upgraded dependencies to the latest versions 57 | - Used Dart 3.0 class modifiers 58 | 59 | # 1.0.9 60 | 61 | - Added base theme for easier theme customization 62 | - Upgraded dependencies to the latest versions 63 | - Migrated to Dart 3.0 64 | 65 | # 1.0.8 66 | 67 | - Refactored project structure for improved organization and readability 68 | - Switched to Flutter's default localization package (flutter_localizations) for simplified internationalization and localization 69 | - Added code generation with Injectable for improved dependency injection and reduced boilerplate code 70 | 71 | # 1.0.7 72 | 73 | - Service locator added. [get_it](https://pub.dev/packages/get_it) 74 | - Dependency versions bumped to latest versions. 75 | 76 | # 1.0.6 77 | 78 | - Minor change made to improve readability in hook files. 79 | 80 | # 1.0.5 81 | 82 | - Refactored hooks as suggested [#514](https://github.com/felangel/mason/issues/514) 83 | 84 | # 1.0.4 85 | 86 | - AutoRoute version bumped to 5.0.1 87 | 88 | # 1.0.3 89 | 90 | - Improved post and pre gen hooks for easier installation. 91 | - Update README.md 92 | -------------------------------------------------------------------------------- /__brick__/lib/app/router/custom_route_observer.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: strict_raw_type 2 | 3 | import 'package:auto_route/auto_route.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:{{project_name.snakeCase()}}/core/utils/logger/logger_utils.dart'; 6 | 7 | /// Custom route observer that logs all route changes 8 | final class CustomRouteObserver extends AutoRouteObserver { 9 | CustomRouteObserver({ 10 | this.logPush = true, 11 | this.logPop = true, 12 | this.logReplace = true, 13 | this.logRemove = true, 14 | this.logInitTab = true, 15 | this.logChangeTab = true, 16 | }); 17 | final bool logPush; 18 | final bool logPop; 19 | final bool logReplace; 20 | final bool logRemove; 21 | final bool logInitTab; 22 | final bool logChangeTab; 23 | 24 | @override 25 | void didPush(Route route, Route? previousRoute) { 26 | super.didPush(route, previousRoute); 27 | if (logPush) { 28 | LoggerUtils.instance.logInfo( 29 | '[AutoRoute] New route pushed: ${route.settings.name}, Previous route: ${previousRoute?.settings.name}', 30 | ); 31 | } 32 | } 33 | 34 | @override 35 | void didPop(Route route, Route? previousRoute) { 36 | super.didPop(route, previousRoute); 37 | if (logPop) { 38 | LoggerUtils.instance.logInfo( 39 | '[AutoRoute] Route popped: ${route.settings.name}, Previous route: ${previousRoute?.settings.name}', 40 | ); 41 | } 42 | } 43 | 44 | @override 45 | void didReplace({Route? newRoute, Route? oldRoute}) { 46 | super.didReplace(newRoute: newRoute, oldRoute: oldRoute); 47 | if (logReplace) { 48 | LoggerUtils.instance.logInfo( 49 | '[AutoRoute] Route replaced: ${newRoute?.settings.name}, Old route: ${oldRoute?.settings.name}', 50 | ); 51 | } 52 | } 53 | 54 | @override 55 | void didRemove(Route route, Route? previousRoute) { 56 | super.didRemove(route, previousRoute); 57 | if (logRemove) { 58 | LoggerUtils.instance.logInfo( 59 | '[AutoRoute] Route removed: ${route.settings.name}, Previous route: ${previousRoute?.settings.name}', 60 | ); 61 | } 62 | } 63 | 64 | @override 65 | void didInitTabRoute(TabPageRoute route, TabPageRoute? previousRoute) { 66 | super.didInitTabRoute(route, previousRoute); 67 | if (logInitTab) { 68 | LoggerUtils.instance.logInfo( 69 | '[AutoRoute] Tab route initialized: ${route.name}, Previous tab route: ${previousRoute?.name}', 70 | ); 71 | } 72 | } 73 | 74 | @override 75 | void didChangeTabRoute(TabPageRoute route, TabPageRoute previousRoute) { 76 | super.didChangeTabRoute(route, previousRoute); 77 | if (logChangeTab) { 78 | LoggerUtils.instance.logInfo( 79 | '[AutoRoute] Tab route changed: ${route.name}, Previous tab route: ${previousRoute.name}', 80 | ); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Starter Template 2 | 3 | [![Powered by Mason](https://img.shields.io/endpoint?url=https%3A%2F%2Ftinyurl.com%2Fmason-badge)](https://github.com/felangel/mason) 4 | 5 | A Flutter starter app that includes support for an HTTP client, themes, routing, localization, and dependency injection. 6 | 7 | ## Compatibility 8 | 9 | Tested on Flutter 3.27.3 10 | 11 | ## Brick Uses: 12 | 13 | - [dio](https://pub.dev/packages/dio) as an HTTP client 14 | - [auto_route](https://pub.dev/packages/auto_route) for routing 15 | - [get_it](https://pub.dev/packages/get_it) for dependency injection 16 | - [logger](https://pub.dev/packages/logger) as logging utility 17 | - [envied](https://pub.dev/packages/envied) for secure handling of environment variables 18 | - [flutter_gen](https://pub.dev/packages/flutter_gen) for asset generation 19 | - [very_good_analysis](https://pub.dev/packages/very_good_analysis) for lint rules 20 | 21 | ## Project Structure 22 | 23 | - "app" folder holds files specific to this particular application. 24 | - "core" folder contains application-agnostic code that can be reused in other projects. 25 | - "feature" folder represents the app's feature set. 26 | 27 | ## How to use 🚀 28 | 29 | Make sure you have the [mason_cli](https://github.com/felangel/mason/tree/master/packages/mason_cli) installed. 30 | 31 | ```sh 32 | dart pub global activate mason_cli 33 | ``` 34 | 35 | Add starter_template to your library 36 | 37 | ```sh 38 | mason add starter_template 39 | ``` 40 | 41 | Generate your brick 42 | 43 | ```sh 44 | mason make starter_template 45 | ``` 46 | 47 | ## Warning ⚠️ 48 | 49 | Ensure the environment/ folder is included in your .gitignore to protect sensitive configuration 50 | 51 | ## Variables ✨ 52 | 53 | | Variable | Description | Default | Type | 54 | | -------------- | --------------------------- | ---------------------- | -------- | 55 | | `project_name` | Project Name | Starter Template | `string` | 56 | | `description` | Project description | A new Flutter project. | `string` | 57 | | `organization` | Organization of the project | com.example | `string` | 58 | 59 | ## Output 📦 60 | 61 | ```sh 62 | 📦lib 63 | ┣ 📂app 64 | ┃ ┣ 📂constants 65 | ┃ ┃ ┗ 📜string_constants.dart 66 | ┃ ┣ 📂environment 67 | ┃ ┃ ┣ 📜app_environment.dart 68 | ┃ ┃ ┣ 📜development_environment.dart 69 | ┃ ┃ ┣ 📜development_environment.g.dart 70 | ┃ ┃ ┣ 📜production_environment.dart 71 | ┃ ┃ ┗ 📜production_environment.g.dart 72 | ┃ ┣ 📂l10n 73 | ┃ ┃ ┣ 📂arb 74 | ┃ ┃ ┃ ┣ 📜app_en.arb 75 | ┃ ┃ ┃ ┣ 📜app_tr.arb 76 | ┃ ┃ ┃ ┗ 📜untranslated_translations.json 77 | ┃ ┃ ┗ 📜l10n.dart 78 | ┃ ┣ 📂router 79 | ┃ ┃ ┣ 📜app_router.dart 80 | ┃ ┃ ┣ 📜app_router.gr.dart 81 | ┃ ┃ ┗ 📜custom_route_observer.dart 82 | ┃ ┣ 📂theme 83 | ┃ ┃ ┣ 📂base 84 | ┃ ┃ ┃ ┗ 📜base_theme.dart 85 | ┃ ┃ ┣ 📂dark 86 | ┃ ┃ ┃ ┗ 📜dark_theme.dart 87 | ┃ ┃ ┗ 📂light 88 | ┃ ┃ ┃ ┗ 📜light_theme.dart 89 | ┃ ┗ 📂view 90 | ┃ ┃ ┗ 📜app.dart 91 | ┣ 📂core 92 | ┃ ┣ 📂clients 93 | ┃ ┃ ┗ 📂network 94 | ┃ ┃ ┃ ┗ 📜network_client.dart 95 | ┃ ┣ 📂extensions 96 | ┃ ┃ ┗ 📜context_extensions.dart 97 | ┃ ┗ 📂utils 98 | ┃ ┃ ┣ 📂device_info 99 | ┃ ┃ ┃ ┗ 📜device_info_utils.dart 100 | ┃ ┃ ┣ 📂logger 101 | ┃ ┃ ┃ ┗ 📜logger_utils.dart 102 | ┃ ┃ ┗ 📂package_info 103 | ┃ ┃ ┃ ┗ 📜package_info_utils.dart 104 | ┣ 📂feature 105 | ┃ ┗ 📂home 106 | ┃ ┃ ┣ 📂model 107 | ┃ ┃ ┃ ┗ 📜.gitkeep 108 | ┃ ┃ ┣ 📂view 109 | ┃ ┃ ┃ ┗ 📜home_view.dart 110 | ┃ ┃ ┗ 📂view_model 111 | ┃ ┃ ┃ ┗ 📜.gitkeep 112 | ┣ 📂generated 113 | ┃ ┗ 📜assets.gen.dart 114 | ┣ 📜bootstrap.dart 115 | ┣ 📜locator.dart 116 | ┣ 📜main_development.dart 117 | ┗ 📜main_production.dart 118 | ``` 119 | 120 | ## Contributing 121 | 122 | Contributions are always welcomed and appreciated! 123 | -------------------------------------------------------------------------------- /hooks/post_gen.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'package:mason/mason.dart'; 3 | 4 | Future run(HookContext context) async { 5 | String projectName = context.vars["project_name"]; 6 | projectName = projectName.snakeCase; 7 | 8 | final List foldersToRemove = [ 9 | "$projectName/lib/", 10 | "$projectName/test/", 11 | "$projectName/pubspec.yaml", 12 | "$projectName/analysis_options.yaml", 13 | "$projectName/.gitignore", 14 | ]; 15 | 16 | final List> filesToCopy = [ 17 | {"source": ".vscode", "destination": "$projectName/"}, 18 | {"source": "environment", "destination": "$projectName/"}, 19 | {"source": "lib", "destination": "$projectName/"}, 20 | {"source": "assets", "destination": "$projectName/"}, 21 | {"source": "scripts", "destination": "$projectName/"}, 22 | {"source": "pubspec.yaml", "destination": "$projectName/"}, 23 | {"source": "analysis_options.yaml", "destination": "$projectName/"}, 24 | {"source": "l10n.yaml", "destination": "$projectName/"}, 25 | {"source": ".gitignore", "destination": "$projectName/"}, 26 | ]; 27 | 28 | await _copyFiles(context, foldersToRemove, filesToCopy); 29 | await _runFlutterPubGet(context, projectName); 30 | await _runBuildRunnerScript(context, projectName); 31 | await _runFlutterGenScript(context, projectName); 32 | } 33 | 34 | Future _copyFiles( 35 | HookContext context, List foldersToRemove, List> filesToCopy) async { 36 | final copyFileProgress = context.logger.progress("Copying required files"); 37 | 38 | for (String folder in foldersToRemove) { 39 | await Process.run("rm", ["-rf", folder]); 40 | } 41 | 42 | List> copyFutures = []; 43 | for (var fileMap in filesToCopy) { 44 | copyFutures.add(Process.run("mv", [fileMap["source"]!, fileMap["destination"]!])); 45 | } 46 | 47 | final result = await Future.wait(copyFutures); 48 | 49 | if (result.every((element) => element.exitCode == 0)) { 50 | copyFileProgress.complete("Files copied successfully!"); 51 | } else { 52 | copyFileProgress.fail(result.firstWhere((element) => element.exitCode != 0).stderr.toString()); 53 | } 54 | } 55 | 56 | Future _runFlutterPubGet(HookContext context, String projectName) async { 57 | final flutterPubGetProgress = context.logger.progress("Running pub get script"); 58 | final result = await Process.start("sh", ["scripts/pub_get.sh"], workingDirectory: projectName); 59 | 60 | final exitCode = await result.exitCode; 61 | 62 | if (exitCode == 0) { 63 | flutterPubGetProgress.complete("Pub get script successfully executed!"); 64 | } else { 65 | flutterPubGetProgress.complete("An error occurred on pub get script ${result.stderr.toString()}"); 66 | exit(exitCode); 67 | } 68 | } 69 | 70 | Future _runBuildRunnerScript(HookContext context, String projectName) async { 71 | final buildRunnerProgress = context.logger.progress("Running build runner script"); 72 | final result = await Process.start("sh", ["scripts/build_runner.sh"], workingDirectory: projectName); 73 | 74 | final exitCode = await result.exitCode; 75 | 76 | if (exitCode == 0) { 77 | buildRunnerProgress.complete("Build runner script successfully executed!"); 78 | } else { 79 | buildRunnerProgress.complete("An error occurred on build runner script ${result.stderr.toString()}"); 80 | exit(exitCode); 81 | } 82 | } 83 | 84 | Future _runFlutterGenScript(HookContext context, String projectName) async { 85 | final flutterGenProgress = context.logger.progress("Running flutter gen script"); 86 | final result = await Process.start("sh", ["scripts/flutter_gen.sh"], workingDirectory: projectName); 87 | 88 | final exitCode = await result.exitCode; 89 | 90 | if (exitCode == 0) { 91 | flutterGenProgress.complete("Flutter gen script successfully executed!"); 92 | } else { 93 | flutterGenProgress.complete("An error occurred on flutter gen script ${result.stderr.toString()}"); 94 | exit(exitCode); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /__brick__/lib/core/extensions/context_extensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | extension MediaQueryExtension on BuildContext { 4 | MediaQueryData get mediaQuery => MediaQuery.of(this); 5 | 6 | /// Returns the height of the device 7 | double get height => MediaQuery.sizeOf(this).height; 8 | 9 | /// Returns the width of the device 10 | double get width => MediaQuery.sizeOf(this).width; 11 | 12 | /// Returns 1% of the screen height 13 | double get lowValue => height * 0.01; 14 | 15 | /// Default value is 2% of the screen height 16 | double get defaultValue => height * 0.02; 17 | 18 | /// Returns 5% of the screen height 19 | double get highValue => height * 0.05; 20 | 21 | /// Returns 10% of the screen height 22 | double get veryhighValue1x => height * 0.1; 23 | 24 | /// Returns 20% of the screen height 25 | double get veryhighValue2x => height * 0.2; 26 | 27 | /// Returns 30% of the screen height 28 | double get veryhighValue3x => height * 0.3; 29 | 30 | /// Returns 40% of the screen height 31 | double get veryhighValue4x => height * 0.4; 32 | 33 | /// Returns 50% of the screen height 34 | double get veryhighValue5x => height * 0.5; 35 | 36 | double dynamicWidth(double val) => width * val; 37 | double dynamicHeight(double val) => height * val; 38 | } 39 | 40 | extension PaddingExtension on BuildContext { 41 | /// Adds 1% padding from all sides. 42 | EdgeInsets get paddingAllLow => EdgeInsets.all(lowValue); 43 | 44 | /// Adds 2% padding from all sides. 45 | /// Use this when you want to add padding from all sides. 46 | EdgeInsets get paddingAllDefault => EdgeInsets.all(defaultValue); 47 | 48 | /// Adds 5% padding from all sides. 49 | EdgeInsets get paddingAllHigh => EdgeInsets.all(highValue); 50 | 51 | /// Adds 1% padding horizontally. 52 | EdgeInsets get paddingHorizontalLow => EdgeInsets.symmetric(horizontal: lowValue); 53 | 54 | /// Adds 2% padding horizontally. 55 | /// Use this when you want to add padding horizontally. 56 | EdgeInsets get paddingHorizontalDefault => EdgeInsets.symmetric(horizontal: defaultValue); 57 | 58 | /// Adds 5% padding horizontally. 59 | EdgeInsets get paddingHorizontalHigh => EdgeInsets.symmetric(horizontal: highValue); 60 | 61 | /// Adds 1% padding vertically. 62 | EdgeInsets get paddingVerticalLow => EdgeInsets.symmetric(vertical: lowValue); 63 | 64 | /// Adds 2% padding vertically. 65 | /// Use this when you want to add padding vertically. 66 | EdgeInsets get paddingVerticalDefault => EdgeInsets.symmetric(vertical: defaultValue); 67 | 68 | /// Adds 5% padding vertically. 69 | EdgeInsets get paddingVerticalHigh => EdgeInsets.symmetric(vertical: highValue); 70 | 71 | /// Adds 1% padding from right. 72 | EdgeInsets get paddingRightLow => EdgeInsets.only(right: lowValue); 73 | 74 | /// Adds 2% padding from right. 75 | /// Use this when you want to add padding from right. 76 | EdgeInsets get paddingRightDefault => EdgeInsets.only(right: defaultValue); 77 | 78 | /// Adds 5% padding from right. 79 | EdgeInsets get paddingRightHigh => EdgeInsets.only(right: highValue); 80 | 81 | /// Adds 1% padding from left. 82 | EdgeInsets get paddingLeftLow => EdgeInsets.only(left: lowValue); 83 | 84 | /// Adds 2% padding from left. 85 | /// Use this when you want to add padding from left. 86 | EdgeInsets get paddingLeftDefault => EdgeInsets.only(left: defaultValue); 87 | 88 | /// Adds 5% padding from left. 89 | EdgeInsets get paddingLeftHigh => EdgeInsets.only(left: highValue); 90 | 91 | /// Adds 1% padding from top. 92 | EdgeInsets get paddingTopLow => EdgeInsets.only(top: lowValue); 93 | 94 | /// Adds 2% padding from top. 95 | /// Use this when you want to add padding from top. 96 | EdgeInsets get paddingTopDefault => EdgeInsets.only(top: defaultValue); 97 | 98 | /// Adds 5% padding from top. 99 | EdgeInsets get paddingTopHigh => EdgeInsets.only(top: highValue); 100 | 101 | /// Adds 1% padding from bottom. 102 | EdgeInsets get paddingBottomLow => EdgeInsets.only(bottom: lowValue); 103 | 104 | /// Adds 2% padding from bottom. 105 | /// Use this when you want to add padding from bottom. 106 | EdgeInsets get paddingBottomDefault => EdgeInsets.only(bottom: defaultValue); 107 | 108 | /// Adds 5% padding from bottom. 109 | EdgeInsets get paddingBottomHigh => EdgeInsets.only(bottom: highValue); 110 | } 111 | 112 | extension ThemeExtension on BuildContext { 113 | /// Get the theme data 114 | ThemeData get theme => Theme.of(this); 115 | 116 | /// Get the text theme 117 | TextTheme get textTheme => Theme.of(this).textTheme; 118 | 119 | /// Get the brightness 120 | Brightness get brightness => Theme.of(this).brightness; 121 | } 122 | -------------------------------------------------------------------------------- /__brick__/lib/core/clients/network/network_client.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | import 'package:dio_smart_retry/dio_smart_retry.dart'; 3 | import 'package:flutter/foundation.dart'; 4 | import 'package:pretty_dio_logger/pretty_dio_logger.dart'; 5 | 6 | // Defining a network client using Dio 7 | /// Instance of this class can be used to make network calls 8 | final class NetworkClient { 9 | NetworkClient({ 10 | required Dio dio, 11 | required String baseUrl, 12 | }) : _dio = dio, 13 | _baseUrl = baseUrl { 14 | _dio.options.baseUrl = _baseUrl; 15 | _dio.options.connectTimeout = const Duration(minutes: 1); 16 | _dio.options.sendTimeout = const Duration(minutes: 1); 17 | _dio.options.receiveTimeout = const Duration(minutes: 1); 18 | 19 | _dio.interceptors.add(RetryInterceptor(dio: _dio)); 20 | if (kDebugMode) { 21 | _dio.interceptors.add( 22 | PrettyDioLogger( 23 | requestHeader: true, 24 | requestBody: true, 25 | ), 26 | ); 27 | } 28 | } 29 | 30 | final Dio _dio; 31 | final String _baseUrl; 32 | // Post:---------------------------------------------------------------------- 33 | Future> get( 34 | String path, { 35 | Map? queryParameters, 36 | Options? options, 37 | CancelToken? cancelToken, 38 | void Function(int, int)? onReceiveProgress, 39 | }) async { 40 | final response = await _dio.get( 41 | path, 42 | queryParameters: queryParameters, 43 | options: options, 44 | cancelToken: cancelToken, 45 | onReceiveProgress: onReceiveProgress, 46 | ); 47 | return response; 48 | } 49 | 50 | // Post:---------------------------------------------------------------------- 51 | Future> post( 52 | String path, { 53 | dynamic data, 54 | Map? queryParameters, 55 | Options? options, 56 | CancelToken? cancelToken, 57 | void Function(int, int)? onSendProgress, 58 | void Function(int, int)? onReceiveProgress, 59 | }) async { 60 | final response = await _dio.post( 61 | path, 62 | data: data, 63 | queryParameters: queryParameters, 64 | options: options, 65 | cancelToken: cancelToken, 66 | onSendProgress: onSendProgress, 67 | onReceiveProgress: onReceiveProgress, 68 | ); 69 | return response; 70 | } 71 | 72 | // Put:----------------------------------------------------------------------- 73 | Future> put( 74 | String path, { 75 | dynamic data, 76 | Map? queryParameters, 77 | Options? options, 78 | CancelToken? cancelToken, 79 | void Function(int, int)? onSendProgress, 80 | void Function(int, int)? onReceiveProgress, 81 | }) async { 82 | final response = await _dio.put( 83 | path, 84 | data: data, 85 | queryParameters: queryParameters, 86 | options: options, 87 | cancelToken: cancelToken, 88 | onSendProgress: onSendProgress, 89 | onReceiveProgress: onReceiveProgress, 90 | ); 91 | return response; 92 | } 93 | 94 | // Delete:-------------------------------------------------------------------- 95 | Future> delete( 96 | String path, { 97 | dynamic data, 98 | Map? queryParameters, 99 | Options? options, 100 | CancelToken? cancelToken, 101 | }) async { 102 | final response = await _dio.delete( 103 | path, 104 | data: data, 105 | queryParameters: queryParameters, 106 | options: options, 107 | cancelToken: cancelToken, 108 | ); 109 | return response; 110 | } 111 | 112 | // Patch:--------------------------------------------------------------------- 113 | Future> patch( 114 | String path, { 115 | dynamic data, 116 | Map? queryParameters, 117 | Options? options, 118 | CancelToken? cancelToken, 119 | void Function(int, int)? onSendProgress, 120 | void Function(int, int)? onReceiveProgress, 121 | }) async { 122 | final response = await _dio.patch( 123 | path, 124 | queryParameters: queryParameters, 125 | options: options, 126 | cancelToken: cancelToken, 127 | onSendProgress: onSendProgress, 128 | onReceiveProgress: onReceiveProgress, 129 | ); 130 | return response; 131 | } 132 | 133 | // Download:------------------------------------------------------------------ 134 | Future> download( 135 | String urlPath, 136 | dynamic savePath, { 137 | void Function(int, int)? onReceiveProgress, 138 | Map? queryParameters, 139 | CancelToken? cancelToken, 140 | bool deleteOnError = true, 141 | String lengthHeader = Headers.contentLengthHeader, 142 | dynamic data, 143 | Options? options, 144 | }) async { 145 | final response = await _dio.download( 146 | urlPath, 147 | savePath, 148 | onReceiveProgress: onReceiveProgress, 149 | queryParameters: queryParameters, 150 | cancelToken: cancelToken, 151 | deleteOnError: deleteOnError, 152 | lengthHeader: lengthHeader, 153 | data: data, 154 | options: options, 155 | ); 156 | 157 | return response; 158 | } 159 | } 160 | --------------------------------------------------------------------------------