diff --git a/example/.gitignore b/example/.gitignore index 29a3a50..79c113f 100644 --- a/example/.gitignore +++ b/example/.gitignore @@ -5,9 +5,11 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ migrate_working_dir/ # IntelliJ related diff --git a/example/lib/application/bindings/application_bindings.dart b/example/lib/application/bindings/application_bindings.dart deleted file mode 100644 index 47d946d..0000000 --- a/example/lib/application/bindings/application_bindings.dart +++ /dev/null @@ -1,28 +0,0 @@ -import 'package:example/application/deep_link/my_deep_link.dart'; -import 'package:flutter_getit/flutter_getit.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -class MyApplicationBindings extends ApplicationBindings { - @override - List> bindings() => [ - Bind.singletonAsync( - (i) async => SharedPreferences.getInstance(), - ), - Bind.singletonAsync( - (i) async => Future.delayed( - const Duration(seconds: 1), - () => AsyncTest(), - ), - ), - Bind.singleton( - (i) => MyDeepLink(i()), - keepAlive: true, - dependsOn: [ - SharedPreferences, - AsyncTest, - ], - ), - ]; -} - -class AsyncTest {} diff --git a/example/lib/application/bindings/navigator_bindings.dart b/example/lib/application/bindings/navigator_bindings.dart deleted file mode 100644 index c1b831a..0000000 --- a/example/lib/application/bindings/navigator_bindings.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:example/src/home/home_controller.dart'; -import 'package:example/src/nav_bar/my_nav_bar_helper_controller.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -class MyNavigatorBindings extends ApplicationBindings { - @override - List> bindings() => [ - Bind.singleton( - (i) => HomeController(), - keepAlive: true, - tag: 'HomeController', - ), - Bind.lazySingleton( - (i) => MyNavBarHelperController(), - ), - ]; -} diff --git a/example/lib/application/debug/my_debug_log.dart b/example/lib/application/debug/my_debug_log.dart deleted file mode 100644 index 11e163e..0000000 --- a/example/lib/application/debug/my_debug_log.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:flutter_getit/flutter_getit.dart'; - -class MyDebugLog extends FGetItLoggerConfig { - MyDebugLog() - : super( - colored: false, - enable: false, - gettingInstance: false, - gettingAsyncInstance: false, - allReady: false, - disposeInstance: false, - registerInstance: false, - disposingInstance: false, - enterAndExitModule: false, - enterAndExitWidget: false, - ); -} diff --git a/example/lib/application/deep_link/my_deep_link.dart b/example/lib/application/deep_link/my_deep_link.dart deleted file mode 100644 index aeecf5f..0000000 --- a/example/lib/application/deep_link/my_deep_link.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'package:flutter_getit/flutter_getit.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -class MyDeepLink with FlutterGetItMixin { - final SharedPreferences sharedPreferences; - - MyDeepLink(this.sharedPreferences); - @override - void onDispose() {} - - @override - void onInit() {} -} diff --git a/example/lib/application/middleware/auth_middleware.dart b/example/lib/application/middleware/auth_middleware.dart deleted file mode 100644 index 1911a92..0000000 --- a/example/lib/application/middleware/auth_middleware.dart +++ /dev/null @@ -1,23 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -class AuthMiddleware extends FlutterGetItAsyncMiddleware { - @override - Future execute(RouteSettings? route) async { - await Future.delayed(const Duration(seconds: 1)); - return route?.name == '/Landing/Presentation7AAA' - ? MiddlewareResult.failure - : MiddlewareResult.next; - } - - @override - Widget get onExecute => const Scaffold( - body: Center( - child: Icon( - Icons.lock, - color: Colors.red, - size: 100, - ), - ), - ); -} diff --git a/example/lib/application/middleware/module_middleware.dart b/example/lib/application/middleware/module_middleware.dart deleted file mode 100644 index fb9ec12..0000000 --- a/example/lib/application/middleware/module_middleware.dart +++ /dev/null @@ -1,10 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -class ModuleMiddleware extends FlutterGetItSyncMiddleware { - @override - MiddlewareResult execute(RouteSettings? route) { - // log("VINDO DO MODULO ===== ${route?.name ?? 'SEM ROTA'}"); - return MiddlewareResult.next; - } -} diff --git a/example/lib/application/middleware/page_middleware.dart b/example/lib/application/middleware/page_middleware.dart deleted file mode 100644 index 318c96b..0000000 --- a/example/lib/application/middleware/page_middleware.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/material.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -class PageMiddleware extends FlutterGetItAsyncMiddleware { - @override - Future execute(RouteSettings? route) async { - // log("Vindo da Page! ===== ${route?.name ?? 'SEM ROTA'}"); - return MiddlewareResult.next; - } - - @override - FutureOr onFail(RouteSettings? route, - FlutterGetItMiddlewareContext fContext, MiddlewareResult result, - {dynamic error}) async { - super.onFail(route, fContext, result, error: error); - await fContext.bottomSheet( - builder: (_) => Scaffold(body: Center(child: Text(error.toString())))); - } -} diff --git a/example/lib/application/middleware/print_middleware.dart b/example/lib/application/middleware/print_middleware.dart deleted file mode 100644 index 5b0e10f..0000000 --- a/example/lib/application/middleware/print_middleware.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -class PrintMiddleware extends FlutterGetItSyncMiddleware { - @override - MiddlewareResult execute(RouteSettings? route) { - // log("DE APPLICATION! ===== ${route?.name ?? 'SEM ROTA'}"); - - if (executeWhen(route)) { - return MiddlewareResult.next; - } - return MiddlewareResult.next; - } - - @override - bool executeWhen(RouteSettings? route) { - if (route?.name == null) { - return true; - } else { - if (route?.name?.contains('Register') ?? false) { - return false; - } - return true; - } - } -} diff --git a/example/lib/application/session/model/user_model.dart b/example/lib/application/session/model/user_model.dart deleted file mode 100644 index 6f52e99..0000000 --- a/example/lib/application/session/model/user_model.dart +++ /dev/null @@ -1,5 +0,0 @@ -class UserModel { - final String name; - - UserModel({required this.name}); -} diff --git a/example/lib/application/session/user_session.dart b/example/lib/application/session/user_session.dart deleted file mode 100644 index f432089..0000000 --- a/example/lib/application/session/user_session.dart +++ /dev/null @@ -1,23 +0,0 @@ -import 'dart:async'; - -import 'package:flutter_getit/flutter_getit.dart'; - -import 'model/user_model.dart'; - -final class UserSession with FlutterGetItMixin { - static final _me = StreamController.broadcast(); - static Stream get me => _me.stream; - late final Stream periodicReset; - - static void updateMe(UserModel? user) { - _me.add(user); - } - - @override - void onDispose() { - _me.close(); - } - - @override - void onInit() {} -} diff --git a/example/lib/main.dart b/example/lib/main.dart index 9810496..04375c6 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,154 +1,150 @@ -import 'package:example/application/bindings/application_bindings.dart'; -import 'package:example/application/middleware/print_middleware.dart'; -import 'package:example/src/auth/repository/auth_repository.dart'; -import 'package:example/src/auth/view/active_account/active_account_controller.dart'; -import 'package:example/src/auth/view/active_account/active_account_page.dart'; -import 'package:example/src/auth/view/active_account/validate_email_controller.dart'; -import 'package:example/src/auth/view/login/login_controller.dart'; -import 'package:example/src/auth/view/login/login_page.dart'; -import 'package:example/src/auth/view/register/register_controller.dart'; -import 'package:example/src/auth/view/register/register_page.dart'; -import 'package:example/src/landing/landing_module.dart'; -import 'package:example/src/loader/load_dependencies.dart'; -import 'package:example/src/nav_bar/nav_bar_module.dart'; -import 'package:example/src/products/products_module.dart'; -import 'package:example/src/route_outlet_nav_bar/my_nav_bar.dart'; +import 'package:example/src/application/binds/my_applications_binds.dart'; +import 'package:example/src/home/home_controller.dart'; +import 'package:example/src/home/home_page.dart'; +import 'package:example/src/middlewares/my_async_middleware.dart'; +import 'package:example/src/products/detail/product_detail_controller.dart'; +import 'package:example/src/products/detail/product_detail_page.dart'; +import 'package:example/src/products/middlewares/product_middleware.dart'; +import 'package:example/src/products/products_controller.dart'; +import 'package:example/src/products/products_home.dart'; +import 'package:example/src/products/service/product_service.dart'; import 'package:example/src/splash/splash_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_getit/flutter_getit.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; void main() { - runApp(const MyApp()); + usePathUrlStrategy(); + runApp(const MainApp()); } -class MyApp extends StatelessWidget { - const MyApp({super.key}); +final routeParse = MyRouteInformationParser(); - @override - Widget build(BuildContext context) { - return FlutterGetIt( - bindings: MyApplicationBindings(), - middlewares: [ - PrintMiddleware(), +final router = FGetItRouterDelegate( + applicationBindings: myApplicationBinds, + middlewares: [ + myAsyncMiddleware, + ], + loaderBuilder: (stream) => StreamBuilder( + stream: stream, + builder: (context, snapshot) { + return Scaffold( + backgroundColor: snapshot.data is FlutterGetItInitializationMiddleware + ? Colors.white + : Colors.black54, + body: switch (snapshot.data) { + MyAsyncMiddleware() => const Center( + child: Text('MyAsyncMiddleware...'), + ), + _ => const Center( + child: FlutterLogo(), + ), + }, + ); + }, + ), + routes: [ + FlutterGetItRoute( + path: '/', + buildPage: ( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + FGetItRouterParams params, + ) => + const SplashPage(), + binds: [], + ), + FlutterGetItRoute( + path: '/Home', + buildPage: ( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + FGetItRouterParams params, + ) => + const HomePage( + title: '1', + ), + binds: [ + Bind.lazySingleton( + (context) => HomeController(), + ), ], - modules: [ - LandingModule(), - NavBarModule(), - ProductsModule(), + ), + FlutterGetItModuleRoute( + path: '/Products', + redirect: '/Products/', + binds: [ + Bind.lazySingleton( + (context) => ProductService(), + ), ], - modulesRouter: [ - FlutterGetItModuleRouter( - name: '/outlet', - pages: [ - FlutterGetItPageRouter( - name: '/', - builderAsync: (context, isReady, loader) => switch (isReady) { - true => const RouteOutletMyNavBar(), - false => loader ?? const WidgetLoadDependencies(), - }, - bindings: [], + middlewares: [ + ProductMiddleware(), + ], + pages: [ + FlutterGetItRoute( + path: '/', + buildPage: ( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + FGetItRouterParams params, + ) => + const ProductsHome(), + binds: [ + Bind.lazySingleton( + (context) => ProductsController(), ), ], ), - FlutterGetItModuleRouter( - name: '/Auth', - onInit: (i) => debugPrint('hi by /Auth'), - onDispose: (i) => debugPrint('bye by /Auth'), - bindings: [ - Bind.lazySingleton( - (i) => AuthRepository(), - ), - ], - pages: [ - FlutterGetItPageRouter( - name: '/Login', - builderAsync: (context, isReady, loader) => switch (isReady) { - true => LoginPage( - controller: context.get(), - ), - false => loader ?? const WidgetLoadDependencies(), - }, - bindings: [ - Bind.lazySingleton( - (i) => LoginController( - name: 'Login', - authRepository: i(), - ), - ), - ], - ), - FlutterGetItModuleRouter( - name: '/Register', - bindings: [ - Bind.lazySingleton( - (i) => RegisterController(), - ), - ], - onInit: (i) => debugPrint('hi by /Register'), - onDispose: (i) => debugPrint('bye by /Register'), - pages: [ - FlutterGetItPageRouter( - name: '/Page', - builderAsync: (context, isReady, loader) => switch (isReady) { - true => RegisterPage( - controller: context.get(), - ), - false => loader ?? const WidgetLoadDependencies(), - }, - bindings: [ - Bind.lazySingleton( - (i) => RegisterController(), - ), - ], - ), - FlutterGetItModuleRouter( - name: '/ActiveAccount', - bindings: [ - Bind.lazySingleton( - (i) => ( - controller: ActiveAccountController(name: 'MyName'), - validateEmailController: - ValidateEmailController(email: 'fgetit@injector'), - ), - ), - ], - pages: [ - FlutterGetItPageRouter( - name: '/Page', - builderAsync: (context, isReady, loader) => - switch (isReady) { - true => const ActiveAccountPage(), - false => loader ?? const WidgetLoadDependencies(), - }, - bindings: [], - ), - ], - ), - ], + FlutterGetItRoute( + path: '/:productId/Detail', + buildPage: ( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + FGetItRouterParams params, + ) => + const ProductDetailPage(), + binds: [ + Bind.lazySingleton( + (context) => ProductDetailController(), ), ], - ) - ], - // loggerConfig: MyDebugLog(), - pagesRouter: [ - FlutterGetItPageRouter( - name: '/splash', builder: (context) => const SplashPage()), + ), ], - builder: (context, routes, isReady) { - return MaterialApp( - title: 'Flutter Demo', - theme: ThemeData( - colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), - useMaterial3: true, - ), - initialRoute: '/splash', - routes: routes, - builder: (context, child) => switch (isReady) { - true => child ?? const SizedBox.shrink(), - false => const WidgetLoadDependencies(), - }, - ); - }, + ), + ], +); + +final myAsyncMiddleware = MyAsyncMiddleware(); +final myApplicationBinds = MyApplicationsBinds(); + +class MainApp extends StatelessWidget { + const MainApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp.router( + routerDelegate: router, + debugShowCheckedModeBanner: false, + routeInformationParser: routeParse, ); } } + +class MyRouteInformationParser extends RouteInformationParser { + @override + Future parseRouteInformation( + RouteInformation routeInformation) async { + print(routeInformation); + return routeInformation.uri.path; + } + + @override + RouteInformation restoreRouteInformation(String configuration) { + return RouteInformation(uri: Uri.parse(configuration)); + } +} diff --git a/example/lib/src/application/binds/my_applications_binds.dart b/example/lib/src/application/binds/my_applications_binds.dart new file mode 100644 index 0000000..0b8ba72 --- /dev/null +++ b/example/lib/src/application/binds/my_applications_binds.dart @@ -0,0 +1,21 @@ +import 'package:flutter_getit/flutter_getit.dart'; + +class MyApplicationsBinds extends ApplicationBindings { + @override + List> bindings() => [ + Bind.singletonAsync( + (i) async => await Future.delayed( + const Duration(seconds: 2), + () => FakeAsyncService(), + ), + ), + ]; +} + +class FakeAsyncService extends FlutterGetItController { + @override + void onDispose() {} + + @override + void onInit() {} +} diff --git a/example/lib/src/auth/repository/auth_repository.dart b/example/lib/src/auth/repository/auth_repository.dart deleted file mode 100644 index 7edf5be..0000000 --- a/example/lib/src/auth/repository/auth_repository.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:flutter_getit/flutter_getit.dart'; - -class AuthRepository with FlutterGetItMixin { - @override - void onDispose() {} - - @override - void onInit() {} -} diff --git a/example/lib/src/auth/view/active_account/active_account_controller.dart b/example/lib/src/auth/view/active_account/active_account_controller.dart deleted file mode 100644 index 92ee8ce..0000000 --- a/example/lib/src/auth/view/active_account/active_account_controller.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:flutter_getit/flutter_getit.dart'; - -class ActiveAccountController with FlutterGetItMixin { - final String name; - - ActiveAccountController({required this.name}); - @override - void onDispose() {} - - @override - void onInit() {} -} diff --git a/example/lib/src/auth/view/active_account/active_account_page.dart b/example/lib/src/auth/view/active_account/active_account_page.dart deleted file mode 100644 index 5bf9e8f..0000000 --- a/example/lib/src/auth/view/active_account/active_account_page.dart +++ /dev/null @@ -1,56 +0,0 @@ -import 'package:example/src/auth/view/active_account/active_account_controller.dart'; -import 'package:example/src/auth/view/active_account/validate_email_controller.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -typedef ActiveAccountPageDependencies = ({ - ActiveAccountController controller, - ValidateEmailController validateEmailController -}); - -class ActiveAccountPage - extends FlutterGetItView { - const ActiveAccountPage({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(fGetIt.controller.name), - ), - body: Center( - child: Column( - children: [ - ElevatedButton( - onPressed: () { - Navigator.of(context).popUntil( - (route) => route.settings.name == '/Home/Page', - ); - }, - child: const Text('PopUntil - Home - Page'), - ), - const SizedBox( - height: 16, - ), - ElevatedButton( - onPressed: () { - Navigator.of(context) - .pushReplacementNamed('/Auth/Register/Page'); - }, - child: const Text('PushReplacementNamed - Register - Page'), - ), - const SizedBox( - height: 16, - ), - ElevatedButton( - onPressed: () { - Navigator.of(context).pushNamed('/Auth/Register/Page'); - }, - child: const Text('PushNamed - Register - Page'), - ), - ], - ), - ), - ); - } -} diff --git a/example/lib/src/auth/view/active_account/validate_email_controller.dart b/example/lib/src/auth/view/active_account/validate_email_controller.dart deleted file mode 100644 index aab0630..0000000 --- a/example/lib/src/auth/view/active_account/validate_email_controller.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:flutter_getit/flutter_getit.dart'; - -class ValidateEmailController with FlutterGetItMixin { - final String email; - - ValidateEmailController({required this.email}); - @override - void onDispose() {} - - @override - void onInit() {} -} diff --git a/example/lib/src/auth/view/login/login_controller.dart b/example/lib/src/auth/view/login/login_controller.dart deleted file mode 100644 index 9bbb69b..0000000 --- a/example/lib/src/auth/view/login/login_controller.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'package:example/src/auth/repository/auth_repository.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -class LoginController with FlutterGetItMixin { - final String name; - final AuthRepository authRepository; - LoginController({required this.name, required this.authRepository}); - @override - void onDispose() {} - - @override - void onInit() {} -} diff --git a/example/lib/src/auth/view/login/login_page.dart b/example/lib/src/auth/view/login/login_page.dart deleted file mode 100644 index 4504379..0000000 --- a/example/lib/src/auth/view/login/login_page.dart +++ /dev/null @@ -1,59 +0,0 @@ -import 'package:example/application/session/model/user_model.dart'; -import 'package:example/application/session/user_session.dart'; -import 'package:example/src/auth/view/login/login_controller.dart'; -import 'package:flutter/material.dart'; - -class LoginPage extends StatelessWidget { - final LoginController controller; - const LoginPage({super.key, required this.controller}); - - @override - Widget build(BuildContext context) { - return Scaffold( - floatingActionButton: FloatingActionButton( - onPressed: () { - UserSession.updateMe( - UserModel( - name: 'Leo ${DateTime.now().second}', - ), - ); - }, - ), - appBar: AppBar( - title: Text(controller.name), - ), - body: Center( - child: Column( - children: [ - ElevatedButton( - onPressed: () { - Navigator.of(context).pushNamed('/Auth/Register/Page'); - }, - child: const Text('PushNamed - Register - Page'), - ), - const SizedBox( - height: 16, - ), - ElevatedButton( - onPressed: () { - Navigator.of(context) - .pushReplacementNamed('/Auth/Register/Page'); - }, - child: const Text('PushReplacementNamed - Register - Page'), - ), - const SizedBox( - height: 16, - ), - ElevatedButton( - onPressed: () { - Navigator.of(context) - .pushReplacementNamed('/Auth/Register/ActiveAccount/Page'); - }, - child: const Text('PushReplacementNamed - ActiveAccount'), - ), - ], - ), - ), - ); - } -} diff --git a/example/lib/src/auth/view/register/register_controller.dart b/example/lib/src/auth/view/register/register_controller.dart deleted file mode 100644 index b02a28e..0000000 --- a/example/lib/src/auth/view/register/register_controller.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:flutter_getit/flutter_getit.dart'; - -class RegisterController with FlutterGetItMixin { - @override - void onDispose() {} - - @override - void onInit() {} -} diff --git a/example/lib/src/auth/view/register/register_page.dart b/example/lib/src/auth/view/register/register_page.dart deleted file mode 100644 index b59838e..0000000 --- a/example/lib/src/auth/view/register/register_page.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'package:example/src/auth/view/register/register_controller.dart'; -import 'package:flutter/material.dart'; - -class RegisterPage extends StatelessWidget { - final RegisterController controller; - const RegisterPage({super.key, required this.controller}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Register Page'), - ), - body: Center( - child: Column( - children: [ - ElevatedButton( - onPressed: () { - Navigator.of(context) - .pushReplacementNamed('/Auth/Register/ActiveAccount/Page'); - }, - child: const Text( - 'PushReplacementNamed - ActiveAccount - Page', - ), - ), - const SizedBox( - height: 16, - ), - ElevatedButton( - onPressed: () { - Navigator.of(context).pushNamed('/Auth/Register/Page'); - }, - child: const Text('PushNamed - Register - Page'), - ), - ], - ), - ), - ); - } -} diff --git a/example/lib/src/detail/detail_module.dart b/example/lib/src/detail/detail_module.dart deleted file mode 100644 index 0ecaa57..0000000 --- a/example/lib/src/detail/detail_module.dart +++ /dev/null @@ -1,173 +0,0 @@ -import 'package:example/src/detail/detail_controller.dart'; -import 'package:example/src/detail/detail_page.dart'; -import 'package:example/src/detail/detail_repository.dart'; -import 'package:example/src/detail/detail_super_controller.dart'; -import 'package:example/src/detail/detail_super_page.dart'; -import 'package:example/src/detail/internal/detail_internal_child.dart'; -import 'package:example/src/detail/internal/detail_internal_page.dart'; -import 'package:example/src/detail/internal/detail_internal_repository.dart'; -import 'package:example/src/detail/widget/form_item_controller.dart'; -import 'package:example/src/home/home_controller.dart'; -import 'package:example/src/loader/load_dependencies.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -class DetailModule extends FlutterGetItModule { - @override - void onDispose(Injector i) {} - - @override - void onInit(Injector i) {} - - @override - String get moduleRouteName => '/Detail'; - - @override - List> get bindings => [ - Bind.lazySingleton( - (i) => DetailRepository(), - ), - Bind.singleton( - (i) => HomeController(), - tag: 'HomeController2', - ), - ]; - - @override - List get pages => [ - FlutterGetItModuleRouter( - name: '/Factories', - bindings: [ - Bind.factory( - (i) => FormItemController( - name: 'FormItemController', - ), - ), - ], - pages: [ - FlutterGetItModuleRouter( - name: '/One', - pages: [ - FlutterGetItPageRouter( - name: '/', - builderAsync: (context, isReady, loader) => switch (isReady) { - true => DetailPage( - controller: context.get(), - ), - false => loader ?? const WidgetLoadDependencies(), - }, - bindings: [ - Bind.lazySingleton( - (i) => DetailController(), - ), - ], - ), - FlutterGetItModuleRouter( - name: '/Internal', - pages: [ - FlutterGetItPageRouter( - name: '/', - bindings: [ - Bind.lazySingleton( - (i) => DetailInternalRepository(), - ), - ], - ), - FlutterGetItModuleRouter( - name: '/Page', - pages: [ - FlutterGetItPageRouter( - name: '/', - builderAsync: (context, isReady, loader) => - switch (isReady) { - true => DetailInternalPage( - repository: context.get(), - ), - false => loader ?? const WidgetLoadDependencies(), - }, - bindings: [], - ), - FlutterGetItPageRouter( - name: '/Child', - builderAsync: (context, isReady, loader) => - switch (isReady) { - true => DetailInternalChild( - repository: context.get(), - ), - false => loader ?? const WidgetLoadDependencies(), - }, - bindings: [], - ), - ], - ), - ], - ) - ], - ), - // FlutterGetItPageRouter( - // name: '/One', - // builderAsync: (context, isReady, loader) => switch (isReady) { - // true => DetailPage( - // controller: context.get(), - // ), - // false => loader ?? const WidgetLoadDependencies(), - // }, - // bindings: [ - // Bind.lazySingleton( - // (i) => DetailController(), - // ), - // ], - // pages: [ - // FlutterGetItModuleRouter( - // name: '/Internal', - // bindings: [ - // Bind.lazySingleton( - // (i) => DetailInternalRepository(), - // ), - // ], - // pages: [ - // FlutterGetItPageRouter( - // name: '/Page', - // builderAsync: (context, isReady, loader) => - // switch (isReady) { - // true => DetailInternalPage( - // repository: context.get(), - // ), - // false => loader ?? const WidgetLoadDependencies(), - // }, - // bindings: [], - // pages: [ - // FlutterGetItPageRouter( - // name: '/Child', - // builderAsync: (context, isReady, loader) => - // switch (isReady) { - // true => DetailInternalChild( - // repository: context.get(), - // ), - // false => loader ?? const WidgetLoadDependencies(), - // }, - // bindings: [], - // ), - // ], - // ), - // ], - // ) - // ], - // ), - FlutterGetItPageRouter( - name: '/Two', - builderAsync: (context, isReady, loader) => switch (isReady) { - true => DetailSuperPage( - controller: context.get(), - ), - false => loader ?? const WidgetLoadDependencies(), - }, - bindings: [ - Bind.lazySingleton( - (i) => DetailSuperController(), - ), - ], - ), - ], - ), - ]; -} diff --git a/example/lib/src/detail/detail_page.dart b/example/lib/src/detail/detail_page.dart deleted file mode 100644 index 8589699..0000000 --- a/example/lib/src/detail/detail_page.dart +++ /dev/null @@ -1,65 +0,0 @@ -import 'dart:developer'; - -import 'package:example/src/detail/detail_controller.dart'; -import 'package:example/src/home/home_controller.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -import 'widget/form_item.dart'; - -class DetailPage extends StatelessWidget { - final DetailController controller; - - const DetailPage({super.key, required this.controller}); - - @override - Widget build(BuildContext context) { - final home1 = context.get(tag: 'HomeController2'); - log('$home1'); - return Scaffold( - appBar: AppBar( - title: const Text('Home detail'), - ), - body: Center( - child: Column( - children: [ - const FormItem( - id: '', - ), - const Divider(), - const FormItem( - id: 'FormItem2', - ), - const Divider(), - const FormItem( - id: 'FormItem3', - ), - const Divider(), - ElevatedButton( - onPressed: () { - Navigator.of(context) - .pushReplacementNamed('/Detail/Factories/Two'); - }, - child: const Text('Detail Two - pushReplacementNamed'), - ), - const Divider(), - ElevatedButton( - onPressed: () { - Navigator.of(context).pushNamed('/Detail/Factories/Two'); - }, - child: const Text('Detail Two'), - ), - const Divider(), - ElevatedButton( - onPressed: () { - Navigator.of(context) - .pushNamed('/Detail/Factories/One/Internal/Page'); - }, - child: const Text('Detail Internal'), - ), - ], - ), - ), - ); - } -} diff --git a/example/lib/src/detail/detail_repository.dart b/example/lib/src/detail/detail_repository.dart deleted file mode 100644 index c39ebc9..0000000 --- a/example/lib/src/detail/detail_repository.dart +++ /dev/null @@ -1 +0,0 @@ -class DetailRepository {} diff --git a/example/lib/src/detail/detail_super_controller.dart b/example/lib/src/detail/detail_super_controller.dart deleted file mode 100644 index 1be254e..0000000 --- a/example/lib/src/detail/detail_super_controller.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:flutter_getit/flutter_getit.dart'; - -class DetailSuperController with FlutterGetItMixin { - @override - void onDispose() {} - - @override - void onInit() {} -} diff --git a/example/lib/src/detail/detail_super_page.dart b/example/lib/src/detail/detail_super_page.dart deleted file mode 100644 index 21e0046..0000000 --- a/example/lib/src/detail/detail_super_page.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'package:example/src/detail/detail_super_controller.dart'; -import 'package:example/src/detail/widget/form_item.dart'; -import 'package:flutter/material.dart'; - -class DetailSuperPage extends StatelessWidget { - final DetailSuperController controller; - const DetailSuperPage({super.key, required this.controller}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Home detail Super'), - ), - body: const Center( - child: Column( - children: [ - FormItem( - id: 'FormItem4', - ), - Divider(), - FormItem( - id: 'FormItem5', - ), - Divider(), - FormItem( - id: 'FormItem6', - ), - ], - )), - ); - } -} diff --git a/example/lib/src/detail/internal/detail_internal_child.dart b/example/lib/src/detail/internal/detail_internal_child.dart deleted file mode 100644 index e052767..0000000 --- a/example/lib/src/detail/internal/detail_internal_child.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:example/src/detail/internal/detail_internal_repository.dart'; -import 'package:flutter/material.dart'; - -class DetailInternalChild extends StatelessWidget { - final DetailInternalRepository repository; - const DetailInternalChild({super.key, required this.repository}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('DetailInternalChild'), - ), - body: Center( - child: ElevatedButton( - onPressed: () { - Navigator.of(context) - .pushReplacementNamed('/Detail/Factories/One/Internal/Page'); - }, - child: const Text('Detail Internal - pushReplacementNamed'), - )), - ); - } -} diff --git a/example/lib/src/detail/internal/detail_internal_page.dart b/example/lib/src/detail/internal/detail_internal_page.dart deleted file mode 100644 index 91b1f23..0000000 --- a/example/lib/src/detail/internal/detail_internal_page.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:example/src/detail/internal/detail_internal_repository.dart'; -import 'package:flutter/material.dart'; - -class DetailInternalPage extends StatelessWidget { - final DetailInternalRepository repository; - const DetailInternalPage({super.key, required this.repository}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('DetailInternalPage'), - ), - body: Center( - child: ElevatedButton( - onPressed: () { - Navigator.of(context) - .pushNamed('/Detail/Factories/One/Internal/Page/Child'); - }, - child: const Text('Detail Internal Child'), - )), - ); - } -} diff --git a/example/lib/src/detail/internal/detail_internal_repository.dart b/example/lib/src/detail/internal/detail_internal_repository.dart deleted file mode 100644 index 44af9d7..0000000 --- a/example/lib/src/detail/internal/detail_internal_repository.dart +++ /dev/null @@ -1 +0,0 @@ -class DetailInternalRepository {} diff --git a/example/lib/src/detail/widget/form_item.dart b/example/lib/src/detail/widget/form_item.dart deleted file mode 100644 index 17660b6..0000000 --- a/example/lib/src/detail/widget/form_item.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:example/src/detail/widget/form_item_controller.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -class FormItem extends StatelessWidget { - final String id; - const FormItem({super.key, required this.id}); - - @override - Widget build(BuildContext context) { - return FlutterGetItWidget( - name: id + hashCode.toString(), - binds: const [], - onDispose: () { - Injector.unRegisterFactoryByTag(id); - }, - builder: (context) { - final fGetIt = context.get(factoryTag: id); - return Column( - children: [ - Text(fGetIt.name), - const SizedBox(height: 10), - TextField( - decoration: InputDecoration( - labelText: fGetIt.name, - border: const OutlineInputBorder(), - ), - ), - ], - ); - }, - ); - } -} diff --git a/example/lib/src/detail/widget/form_item_controller.dart b/example/lib/src/detail/widget/form_item_controller.dart deleted file mode 100644 index e69e7b8..0000000 --- a/example/lib/src/detail/widget/form_item_controller.dart +++ /dev/null @@ -1,14 +0,0 @@ -import 'package:flutter_getit/flutter_getit.dart'; - -class FormItemController with FlutterGetItMixin { - final String name; - - FormItemController({ - required this.name, - }); - @override - void onDispose() {} - - @override - void onInit() {} -} diff --git a/example/lib/src/home/home_controller.dart b/example/lib/src/home/home_controller.dart index 5143c38..ceb2dfe 100644 --- a/example/lib/src/home/home_controller.dart +++ b/example/lib/src/home/home_controller.dart @@ -1,17 +1,3 @@ -import 'dart:developer'; - -import 'package:flutter_getit/flutter_getit.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -class HomeController with FlutterGetItMixin { - HomeController(); - - @override - void onDispose() {} - - @override - void onInit() { - final sp = Injector.get(); - log(sp.toString()); - } +class HomeController { + final String title = 'FGetIt is awesome'; } diff --git a/example/lib/src/home/home_module.dart b/example/lib/src/home/home_module.dart deleted file mode 100644 index ca0d6f3..0000000 --- a/example/lib/src/home/home_module.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'package:example/src/home/home_controller.dart'; -import 'package:example/src/home/home_page.dart'; -import 'package:example/src/loader/load_dependencies.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -class HomeModule extends FlutterGetItModule { - @override - String get moduleRouteName => '/Home'; - @override - List> get bindings => []; - - @override - List get pages => [ - FlutterGetItPageRouter( - name: '/Page', - builderAsync: (context, isReady, loader) => switch (isReady) { - true => HomePage(), - false => loader ?? const WidgetLoadDependencies(), - }, - bindings: [ - Bind.lazySingleton( - (i) => HomeController(), - ), - ], - ), - ]; - - @override - void onDispose(Injector i) {} - - @override - void onInit(Injector i) {} -} diff --git a/example/lib/src/home/home_page.dart b/example/lib/src/home/home_page.dart index 5e964c2..3f1e342 100644 --- a/example/lib/src/home/home_page.dart +++ b/example/lib/src/home/home_page.dart @@ -1,168 +1,74 @@ -import 'dart:developer'; - -import 'package:example/application/session/model/user_model.dart'; -import 'package:example/application/session/user_session.dart'; import 'package:example/src/home/home_controller.dart'; -import 'package:example/src/param_example/param_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_getit/flutter_getit.dart'; class HomePage extends StatelessWidget { - HomePage({super.key}); - - final _home1 = Injector.get(tag: 'HomeController'); + final String title; + const HomePage({super.key, required this.title}); @override Widget build(BuildContext context) { - log(_home1.toString()); - log(context.any().toString()); - + final controller = context.get(); return Scaffold( - floatingActionButton: FloatingActionButton( - onPressed: () { - showModalBottomSheet( - context: context, - builder: (context) => FlutterGetItWidget( - name: 'Test', - builder: (context) { - return const Center( - child: Text('Test'), - ); - }, - ), - ); - }, - ), appBar: AppBar( - title: const Text('HomePage'), + title: Text('Home Page $title - ${controller.title}'), ), - body: Center( - child: ListView( - children: [ - StreamBuilder( - stream: UserSession.me, - builder: (context, user) { - return Text(user.data?.name ?? 'No User'); + body: Column( + children: [ + Center( + child: ElevatedButton( + onPressed: () { + Navigator.of(context).pushNamed('/Home2'); }, - ), - const Divider(), - ElevatedButton( - onPressed: () async { - Navigator.of(context).pushNamed('/Auth/Login'); + child: const Text('Go to Home 2 (Don\'t exist)'), + ), + ), + const SizedBox(height: 10), + Center( + child: ElevatedButton( + onPressed: () { + Navigator.of(context).pushNamed('/Products'); }, child: const Text( - 'PushNamed - Login', + 'Go to "/Products" (It\'s a module not a route)', ), ), - const SizedBox( - height: 16, - ), - ElevatedButton( - onPressed: () async { - Navigator.of(context).pushNamed('/Auth/Register/Page'); + ), + const SizedBox(height: 10), + Center( + child: ElevatedButton( + onPressed: () { + Navigator.of(context).pushNamed('/Products/'); }, child: const Text( - 'PushNamed - Register - Page', + 'Go to "/Products/" (It\'s a route)', ), ), - const SizedBox( - height: 16, - ), - ElevatedButton( - onPressed: () async { - Navigator.of(context) - .pushNamed('/Auth/Register/ActiveAccount/Page'); + ), + const SizedBox(height: 10), + Center( + child: ElevatedButton( + onPressed: () { + Navigator.of(context).pushNamed('/Products/29/Detail'); }, child: const Text( - 'PushNamed - ActiveAccount - Page', + 'Go directly to "/Products/29/Detail" (It\'s a route)', ), ), - const SizedBox( - height: 16, - ), - ElevatedButton( - onPressed: () async { - Navigator.of(context).pushNamed('/Auth/Register/ActiveAccount'); - }, - child: const Text( - 'PushNamed - Wrong page', - ), - ), - const Divider(), - ElevatedButton( - onPressed: () async { - Navigator.of(context).pushNamed('/Random/Page'); - }, - child: const Text( - 'PushNamed - RandomPage', - ), - ), - const Divider(), - ElevatedButton( - onPressed: () async { - Navigator.of(context).pushNamed('/Detail/Factories/One'); - }, - child: const Text( - 'Detail One Page', - ), - ), - const SizedBox( - height: 16, - ), - ElevatedButton( - onPressed: () async { - Navigator.of(context) - .pushNamed('/Detail/Factories/One/Internal/Page'); - }, - child: const Text( - 'Detail One Internal', - ), - ), - const SizedBox( - height: 16, - ), - ElevatedButton( - onPressed: () async { + ), + const SizedBox(height: 10), + Center( + child: ElevatedButton( + onPressed: () { Navigator.of(context) - .pushNamed('/Detail/Factories/One/Internal/Page/Child'); - }, - child: const Text( - 'Detail One Internal Child', - ), - ), - const SizedBox( - height: 16, - ), - ElevatedButton( - onPressed: () async { - Navigator.of(context).pushNamed('/Detail/Factories/Two'); - }, - child: const Text( - 'Detail Two Page', - ), - ), - const Divider(), - const SizedBox( - height: 16, - ), - ElevatedButton( - onPressed: () async { - ParamPageDto dto = ( - name: 'FlutterGetIt', - date: DateTime(2021), - ); - - Navigator.of(context).pushNamed( - '/Params/Page', - arguments: dto, - ); + .pushNamed('/Products/30/Detail', arguments: 'Block'); }, child: const Text( - 'Page with Params', + 'Go directly to "/Products/30/Detail" (It\'s a route) but with a middleware that blocks the navigation', ), ), - ], - ), + ), + ], ), ); } diff --git a/example/lib/src/landing/initialize_bloc.dart b/example/lib/src/landing/initialize_bloc.dart deleted file mode 100644 index a164a72..0000000 --- a/example/lib/src/landing/initialize_bloc.dart +++ /dev/null @@ -1 +0,0 @@ -class InitializeBloc {} diff --git a/example/lib/src/landing/initialize_controller.dart b/example/lib/src/landing/initialize_controller.dart deleted file mode 100644 index 11f8b60..0000000 --- a/example/lib/src/landing/initialize_controller.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'dart:developer'; - -import 'package:example/application/bindings/application_bindings.dart'; -import 'package:flutter_getit/flutter_getit.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -import 'initialize_bloc.dart'; - -class InitializeController implements InitializeBloc, FlutterGetItMixin { - InitializeController(); - @override - void onDispose() {} - - @override - void onInit() async { - final spByAsync = Injector.get(); - final myTest = await Injector.getAsync(); - log(spByAsync.toString()); - log(myTest.toString()); - } -} diff --git a/example/lib/src/landing/initialize_page.dart b/example/lib/src/landing/initialize_page.dart deleted file mode 100644 index 022addc..0000000 --- a/example/lib/src/landing/initialize_page.dart +++ /dev/null @@ -1,37 +0,0 @@ -import 'dart:developer'; - -import 'package:example/application/deep_link/my_deep_link.dart'; -import 'package:example/src/landing/initialize_controller.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -class InitializePage extends StatelessWidget { - const InitializePage({super.key}); - - @override - Widget build(BuildContext context) { - final controller = Injector.get(); - final deepLink = Injector.get(); - log(controller.toString()); - log(deepLink.toString()); - return Scaffold( - appBar: AppBar( - title: const Text('Initialize page'), - ), - body: Center( - child: Column( - children: [ - const FlutterLogo(), - ElevatedButton( - onPressed: () { - Navigator.of(context).pushNamedAndRemoveUntil( - '/Landing/Presentation', (route) => false); - }, - child: const Text('Ir a Presentation'), - ), - ], - ), - ), - ); - } -} diff --git a/example/lib/src/landing/landing_module.dart b/example/lib/src/landing/landing_module.dart deleted file mode 100644 index 7b63b18..0000000 --- a/example/lib/src/landing/landing_module.dart +++ /dev/null @@ -1,94 +0,0 @@ -import 'dart:developer'; - -import 'package:example/application/middleware/auth_middleware.dart'; -import 'package:example/src/landing/initialize_controller.dart'; -import 'package:example/src/landing/initialize_page.dart'; -import 'package:example/src/landing/presentation_page.dart'; -import 'package:example/src/loader/load_dependencies.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -class LandingModule extends FlutterGetItModule { - @override - String get moduleRouteName => '/Landing'; - - @override - List> get bindings => []; - - @override - List get pages => [ - FlutterGetItPageRouter( - name: '/Initialize', - builderAsync: (context, isReady, loader) => switch (isReady) { - true => const InitializePage(), - false => loader ?? const WidgetLoadDependencies(), - }, - bindings: [ - Bind.lazySingleton( - (i) => InitializeController(), - ), - ], - ), - FlutterGetItPageRouter( - name: '/Presentation', - builderAsync: (context, isReady, loader) => switch (isReady) { - true => const PresentationPage(), - false => loader ?? const WidgetLoadDependencies(), - }, - middlewares: [ - AuthMiddleware(), - ], - bindings: [ - Bind.singletonAsync( - (i) => Future.delayed( - const Duration(seconds: 1), - () => PresentationRepository(), - ), - keepAlive: true, - ), - Bind.singleton( - (i) => PresentationController( - repository: i(), - ), - dependsOn: [PresentationRepository], - ), - Bind.lazySingletonAsync( - (i) => Future.delayed( - const Duration(seconds: 1), - () => PresentationDatabase(), - ), - ), - ], - ), - ]; - - @override - void onDispose(Injector i) {} - - @override - void onInit(Injector i) {} -} - -class PresentationController with FlutterGetItMixin { - final PresentationRepository repository; - PresentationController({required this.repository}); - - @override - void onDispose() {} - - @override - void onInit() {} -} - -class PresentationRepository {} - -class PresentationDatabase with FlutterGetItMixin { - @override - void onDispose() { - log('Dispose PresentationDatabase'); - } - - @override - void onInit() { - log('Init PresentationDatabase'); - } -} diff --git a/example/lib/src/landing/presentation_page.dart b/example/lib/src/landing/presentation_page.dart deleted file mode 100644 index 3450221..0000000 --- a/example/lib/src/landing/presentation_page.dart +++ /dev/null @@ -1,45 +0,0 @@ -import 'dart:developer'; - -import 'package:example/src/landing/landing_module.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -class PresentationPage extends StatelessWidget { - const PresentationPage({super.key}); - - @override - Widget build(BuildContext context) { - final controller = Injector.get(); - log(controller.toString()); - return Scaffold( - appBar: AppBar( - title: const Text('Presentation'), - ), - body: Center( - child: Column( - children: [ - ElevatedButton( - onPressed: () { - Navigator.of(context).pushNamedAndRemoveUntil( - '/RootNavBar/Root', - (route) => false, - ); - }, - child: const Text('Ir a RootNav'), - ), - const SizedBox(height: 20), - ElevatedButton( - onPressed: () { - Navigator.of(context).pushNamedAndRemoveUntil( - '/outlet/', - (route) => false, - ); - }, - child: const Text('Ir a RouteOutlet'), - ), - ], - ), - ), - ); - } -} diff --git a/example/lib/src/loader/load_dependencies.dart b/example/lib/src/loader/load_dependencies.dart deleted file mode 100644 index 5ebbdfd..0000000 --- a/example/lib/src/loader/load_dependencies.dart +++ /dev/null @@ -1,14 +0,0 @@ -import 'package:flutter/material.dart'; - -class WidgetLoadDependencies extends StatelessWidget { - const WidgetLoadDependencies({super.key}); - - @override - Widget build(BuildContext context) { - return const Scaffold( - body: Center( - child: Text('⏰ - Loading dependencies...'), - ), - ); - } -} diff --git a/example/lib/src/middlewares/my_async_middleware.dart b/example/lib/src/middlewares/my_async_middleware.dart new file mode 100644 index 0000000..e919804 --- /dev/null +++ b/example/lib/src/middlewares/my_async_middleware.dart @@ -0,0 +1,37 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter_getit/flutter_getit.dart'; + +class MyAsyncMiddleware implements FlutterGetItAsyncMiddleware { + @override + FutureOr execute(dynamic arguments) { + return Future.delayed( + const Duration(microseconds: 500), + () => MiddlewareStatus.success, + ); + } + + @override + void onFailure(BuildContext context, dynamic arguments) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + backgroundColor: Colors.red, + content: Text( + 'MyAsyncMiddleware failed', + style: TextStyle( + color: Colors.white, + ), + ), + ), + ); + } + + @override + MiddlewareAction when(String path) { + if (path != '/') { + return MiddlewareAction.execute; + } + return MiddlewareAction.skip; + } +} diff --git a/example/lib/src/middlewares/my_sync_middleware.dart b/example/lib/src/middlewares/my_sync_middleware.dart new file mode 100644 index 0000000..dd9cb98 --- /dev/null +++ b/example/lib/src/middlewares/my_sync_middleware.dart @@ -0,0 +1,25 @@ +/* import 'package:flutter_getit/flutter_getit.dart'; + +class MySyncMiddleware implements FlutterGetItSyncMiddlewareV4 { + @override + MiddlewareStatus execute(FlutterGetItRouteBase route) { + if (route.fullName == '/Account/Profile') { + return MiddlewareStatus.failure; + } + return MiddlewareStatus.success; + } + + @override + void onFailure(FlutterGetItRouteBase route) { + route.navigator?.pop(); + } + + @override + MiddlewareAction when(FlutterGetItRouteBase route) { + if (route.fullName.contains('/Account')) { + return MiddlewareAction.execute; + } + return MiddlewareAction.skip; + } +} + */ diff --git a/example/lib/src/nav_bar/my_nav_bar.dart b/example/lib/src/nav_bar/my_nav_bar.dart deleted file mode 100644 index 79d1ef9..0000000 --- a/example/lib/src/nav_bar/my_nav_bar.dart +++ /dev/null @@ -1,237 +0,0 @@ -import 'package:example/application/bindings/navigator_bindings.dart'; -import 'package:example/application/middleware/module_middleware.dart'; -import 'package:example/application/middleware/page_middleware.dart'; -import 'package:example/src/auth/repository/auth_repository.dart'; -import 'package:example/src/auth/view/active_account/active_account_controller.dart'; -import 'package:example/src/auth/view/active_account/active_account_page.dart'; -import 'package:example/src/auth/view/active_account/validate_email_controller.dart'; -import 'package:example/src/auth/view/login/login_controller.dart'; -import 'package:example/src/auth/view/login/login_page.dart'; -import 'package:example/src/auth/view/register/register_controller.dart'; -import 'package:example/src/auth/view/register/register_page.dart'; -import 'package:example/src/detail/detail_module.dart'; -import 'package:example/src/home/home_module.dart'; -import 'package:example/src/loader/load_dependencies.dart'; -import 'package:example/src/param_example/param_example_module.dart'; -import 'package:example/src/products/products_module.dart'; -import 'package:example/src/random/random_controller.dart'; -import 'package:example/src/random/random_page.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -final internalNav = GlobalKey(); - -class MyNavBar extends StatefulWidget { - const MyNavBar({super.key}); - - @override - State createState() => _MyNavBarState(); -} - -class _MyNavBarState extends State { - var _currentIndex = 0; - @override - Widget build(BuildContext context) { - return Scaffold( - body: FlutterGetIt.navigator( - name: 'NAVbarProducts', - bindings: MyNavigatorBindings(), - modulesRouter: [ - FlutterGetItModuleRouter( - name: '/Random', - bindings: [ - Bind.lazySingleton( - (i) => RandomController('Random by FlutterGetItPageRouter'), - ), - ], - pages: [ - FlutterGetItPageRouter( - name: '/Page', - builderAsync: (context, isReady, loader) => switch (isReady) { - true => const RandomPage(), - false => loader ?? const WidgetLoadDependencies(), - }, - bindings: [ - Bind.lazySingleton( - (i) => RandomController('Random by FlutterGetItPageRouter'), - ), - ], - ), - FlutterGetItPageRouter( - name: '/Page2', - builderAsync: (context, isReady, loader) => switch (isReady) { - true => const RandomPage(), - false => loader ?? const WidgetLoadDependencies(), - }, - bindings: [ - Bind.lazySingleton( - (i) => RandomController('Random by FlutterGetItPageRouter'), - ), - ], - ), - ], - ), - FlutterGetItModuleRouter( - name: '/Auth', - onInit: (i) => debugPrint('hi by /Auth'), - onDispose: (i) => debugPrint('bye by /Auth'), - bindings: [ - Bind.lazySingleton( - (i) => AuthRepository(), - ), - ], - pages: [ - FlutterGetItPageRouter( - name: '/Login', - builderAsync: (context, isReady, loader) => switch (isReady) { - true => LoginPage( - controller: context.get(), - ), - false => loader ?? const WidgetLoadDependencies(), - }, - bindings: [ - Bind.lazySingleton( - (i) => LoginController( - name: 'Login', - authRepository: i(), - ), - keepAlive: true, - ), - ], - ), - FlutterGetItModuleRouter( - middlewares: [ - ModuleMiddleware(), - ], - name: '/Register', - bindings: [ - Bind.lazySingleton( - (i) => RegisterController(), - ), - ], - onInit: (i) => debugPrint('hi by /Register'), - onDispose: (i) => debugPrint('bye by /Register'), - pages: [ - FlutterGetItPageRouter( - middlewares: [ - PageMiddleware(), - ], - name: '/Page', - builderAsync: (context, isReady, loader) => - switch (isReady) { - true => RegisterPage( - controller: context.get(), - ), - false => loader ?? const WidgetLoadDependencies(), - }, - bindings: [ - /* Bind.lazySingleton( - (i) => RegisterController(), - ), */ - ], - ), - FlutterGetItModuleRouter( - name: '/ActiveAccount', - bindings: [ - Bind.lazySingleton( - (i) => ( - controller: ActiveAccountController(name: 'MyName'), - validateEmailController: - ValidateEmailController(email: 'fgetit@injector'), - ), - ), - ], - pages: [ - FlutterGetItPageRouter( - name: '/Page', - builderAsync: (context, isReady, loader) => - switch (isReady) { - true => const ActiveAccountPage(), - false => loader ?? const WidgetLoadDependencies(), - }, - bindings: [], - ), - ], - ), - ], - ), - ], - ), - ], - modules: [ - HomeModule(), - DetailModule(), - ParamExampleModule(), - /* AuthModule(),*/ - ProductsModule(), - ], - builder: (context, routes, isReady) => Navigator( - key: internalNav, - initialRoute: '/Home/Page', - observers: const [], - onGenerateRoute: (settings) { - return PageRouteBuilder( - settings: settings, - pageBuilder: (context, animation, secondaryAnimation) => - routes[settings.name]?.call(context) ?? const Placeholder(), - ); - }, - ), - ), - bottomNavigationBar: BottomNavigationBar( - currentIndex: _currentIndex, - onTap: (value) { - if (_currentIndex != value) { - switch (value) { - case 0: - internalNav.currentState - ?.pushNamedAndRemoveUntil('/Home/Page', (_) => false); - case 1: - internalNav.currentState - ?.pushNamedAndRemoveUntil('/Products/Page/', (_) => false); - case 2: - internalNav.currentState - ?.pushNamedAndRemoveUntil('/Home/Page', (_) => false); - case 3: - internalNav.currentState - ?.pushNamedAndRemoveUntil('/Products/Page/', (_) => false); - } - setState(() { - _currentIndex = value; - }); - } - }, - items: const [ - BottomNavigationBarItem( - icon: Icon( - Icons.home, - color: Colors.blueAccent, - ), - label: 'Home', - ), - BottomNavigationBarItem( - icon: Icon( - Icons.production_quantity_limits, - color: Colors.blueAccent, - ), - label: 'Products', - ), - BottomNavigationBarItem( - icon: Icon( - Icons.home, - color: Colors.blueAccent, - ), - label: 'Home', - ), - BottomNavigationBarItem( - icon: Icon( - Icons.production_quantity_limits, - color: Colors.blueAccent, - ), - label: 'Products', - ), - ], - ), - ); - } -} diff --git a/example/lib/src/nav_bar/my_nav_bar_helper_controller.dart b/example/lib/src/nav_bar/my_nav_bar_helper_controller.dart deleted file mode 100644 index 738518d..0000000 --- a/example/lib/src/nav_bar/my_nav_bar_helper_controller.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:flutter_getit/flutter_getit.dart'; - -class MyNavBarHelperController with FlutterGetItMixin { - @override - void onDispose() {} - - @override - void onInit() {} -} diff --git a/example/lib/src/nav_bar/nav_bar_module.dart b/example/lib/src/nav_bar/nav_bar_module.dart deleted file mode 100644 index 0b0e186..0000000 --- a/example/lib/src/nav_bar/nav_bar_module.dart +++ /dev/null @@ -1,28 +0,0 @@ -import 'package:example/src/loader/load_dependencies.dart'; -import 'package:example/src/nav_bar/my_nav_bar.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -class NavBarModule extends FlutterGetItModule { - @override - String get moduleRouteName => '/RootNavBar'; - - @override - List> get bindings => []; - - @override - List get pages => [ - FlutterGetItPageRouter( - name: '/Root', - builderAsync: (context, isReady, loader) => switch (isReady) { - true => const MyNavBar(), - false => loader ?? const WidgetLoadDependencies(), - }, - ), - ]; - - @override - void onDispose(Injector i) {} - - @override - void onInit(Injector i) {} -} diff --git a/example/lib/src/param_example/param_example_module.dart b/example/lib/src/param_example/param_example_module.dart deleted file mode 100644 index b229651..0000000 --- a/example/lib/src/param_example/param_example_module.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'package:example/src/param_example/param_page.dart'; -import 'package:example/src/param_example/param_page_controller.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -class ParamExampleModule extends FlutterGetItModule { - @override - String get moduleRouteName => '/Params'; - - @override - void onDispose(Injector i) {} - - @override - void onInit(Injector i) {} - - @override - List get pages => [ - FlutterGetItPageRouter( - name: '/Page', - bindings: [ - Bind.singleton( - (i) => ParamPageController(), - ), - ], - builderAsync: (context, isReady, loader) { - return switch (isReady) { - true => const ParamPage(), - false => loader ?? const CircularProgressIndicator(), - }; - }, - ), - ]; -} diff --git a/example/lib/src/param_example/param_page.dart b/example/lib/src/param_example/param_page.dart deleted file mode 100644 index 8c1c4db..0000000 --- a/example/lib/src/param_example/param_page.dart +++ /dev/null @@ -1,51 +0,0 @@ -import 'package:example/src/param_example/param_page_controller.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -typedef ParamPageDto = ({String name, DateTime date}); - -class ParamPage extends StatelessWidget { - const ParamPage({super.key}); - - @override - Widget build(BuildContext context) { - final controller = Injector.get(); - - return Scaffold( - appBar: AppBar( - title: ValueListenableBuilder( - valueListenable: controller.dtoByInjector, - builder: (context, dtoByInjector, child) { - return Text( - switch (dtoByInjector) { - null => 'null', - _ => dtoByInjector.name, - }, - ); - }, - ), - ), - floatingActionButton: FloatingActionButton(onPressed: () { - controller.setDtoByInjector(); - }), - body: Center( - child: Column( - children: [ - const Text('Dto by injector'), - ValueListenableBuilder( - valueListenable: controller.dtoByInjector, - builder: (context, dtoByInjector, child) { - return Text( - switch (dtoByInjector) { - null => 'null', - _ => dtoByInjector.date.toIso8601String() - }, - ); - }, - ), - ], - ), - ), - ); - } -} diff --git a/example/lib/src/param_example/param_page_controller.dart b/example/lib/src/param_example/param_page_controller.dart deleted file mode 100644 index 2725b40..0000000 --- a/example/lib/src/param_example/param_page_controller.dart +++ /dev/null @@ -1,19 +0,0 @@ -import 'package:example/src/param_example/param_page.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -class ParamPageController with FlutterGetItMixin { - final dtoByInjector = ValueNotifier(null); - - ParamPageController(); - - @override - void onDispose() {} - - @override - void onInit() { - dtoByInjector.value = Injector.arguments; - } - - void setDtoByInjector() {} -} diff --git a/example/lib/src/products/detail/product_detail_controller.dart b/example/lib/src/products/detail/product_detail_controller.dart new file mode 100644 index 0000000..9355c4c --- /dev/null +++ b/example/lib/src/products/detail/product_detail_controller.dart @@ -0,0 +1,13 @@ +import 'package:flutter_getit/flutter_getit.dart'; + +class ProductDetailController with FlutterGetItMixin { + late final int productId; + + @override + void onDispose() {} + + @override + void onInit() { + // productId = FlutterGetIt.arguments; + } +} diff --git a/example/lib/src/products/detail/product_detail_page.dart b/example/lib/src/products/detail/product_detail_page.dart new file mode 100644 index 0000000..ef0267a --- /dev/null +++ b/example/lib/src/products/detail/product_detail_page.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; + +class ProductDetailPage extends StatelessWidget { + final String? productId; + const ProductDetailPage({ + super.key, + this.productId, + }); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Product Detail ID: $productId'), + ), + body: Center( + child: SizedBox( + width: 420, + child: ListView( + children: [ + ElevatedButton( + onPressed: () { + Navigator.of(context).pushNamed('/Products/Detail'); + }, + child: const Text('Push Named Detail (Again)'), + ), + const SizedBox(height: 10), + ElevatedButton( + onPressed: () { + Navigator.of(context) + .pushReplacementNamed('/Products/Detail'); + }, + child: const Text('Push Replacement this page'), + ), + const SizedBox(height: 10), + ElevatedButton( + onPressed: () { + Navigator.of(context).pushNamedAndRemoveUntil( + '/Products/Detail', (route) => false); + }, + child: const Text('Push NamedAndRemoveUntil this page'), + ), + const SizedBox(height: 10), + ElevatedButton( + onPressed: () { + Navigator.of(context).popAndPushNamed('/Products/Detail'); + }, + child: const Text('Push popAndPushNamed this page'), + ), + ], + ), + ), + ), + ); + } +} diff --git a/example/lib/src/products/middlewares/product_middleware.dart b/example/lib/src/products/middlewares/product_middleware.dart new file mode 100644 index 0000000..9b610f8 --- /dev/null +++ b/example/lib/src/products/middlewares/product_middleware.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_getit/flutter_getit.dart'; + +class ProductMiddleware implements FlutterGetItSyncMiddleware { + @override + MiddlewareStatus execute(arguments) { + if (arguments is String && arguments == 'Block') { + return MiddlewareStatus.failure; + } + return MiddlewareStatus.success; + } + + @override + void onFailure(BuildContext context, arguments) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + backgroundColor: Colors.red, + content: Text( + 'Middleware ProductMiddleware failed', + style: TextStyle(color: Colors.white), + ), + ), + ); + return; + } + + @override + MiddlewareAction when(String path) { + return MiddlewareAction.execute; + } +} diff --git a/example/lib/src/products/model/product_model.dart b/example/lib/src/products/model/product_model.dart deleted file mode 100644 index 79dc7dc..0000000 --- a/example/lib/src/products/model/product_model.dart +++ /dev/null @@ -1,13 +0,0 @@ -class ProductModel { - final String name; - - ProductModel({required this.name}); - - static List get getFake => [ - ProductModel(name: 'Camiseta'), - ProductModel(name: 'Short'), - ProductModel(name: 'Boné'), - ProductModel(name: 'Calça'), - ProductModel(name: 'Armario'), - ]; -} diff --git a/example/lib/src/products/product_controller.dart b/example/lib/src/products/product_controller.dart deleted file mode 100644 index 5935021..0000000 --- a/example/lib/src/products/product_controller.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:flutter_getit/flutter_getit.dart'; - -class ProductController with FlutterGetItMixin { - @override - void onDispose() {} - - @override - void onInit() async {} -} diff --git a/example/lib/src/detail/detail_controller.dart b/example/lib/src/products/products_controller.dart similarity index 54% rename from example/lib/src/detail/detail_controller.dart rename to example/lib/src/products/products_controller.dart index 6a73089..e349a8a 100644 --- a/example/lib/src/detail/detail_controller.dart +++ b/example/lib/src/products/products_controller.dart @@ -1,6 +1,7 @@ import 'package:flutter_getit/flutter_getit.dart'; -class DetailController with FlutterGetItMixin { +class ProductsController with FlutterGetItMixin { + final String title = 'Flutter GetIt is awesome'; @override void onDispose() {} diff --git a/example/lib/src/products/products_detail.dart b/example/lib/src/products/products_detail.dart deleted file mode 100644 index 9bcf153..0000000 --- a/example/lib/src/products/products_detail.dart +++ /dev/null @@ -1,19 +0,0 @@ -import 'package:example/src/products/model/product_model.dart'; -import 'package:flutter/material.dart'; - -class ProductsDetail extends StatelessWidget { - const ProductsDetail({super.key}); - - @override - Widget build(BuildContext context) { - final product = ModalRoute.of(context)?.settings.arguments as ProductModel; - return Scaffold( - appBar: AppBar( - title: Text('Product ${product.name}'), - ), - body: const Center( - child: FlutterLogo(), - ), - ); - } -} diff --git a/example/lib/src/products/products_home.dart b/example/lib/src/products/products_home.dart new file mode 100644 index 0000000..0805da8 --- /dev/null +++ b/example/lib/src/products/products_home.dart @@ -0,0 +1,56 @@ +import 'package:example/src/products/products_controller.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_getit/flutter_getit.dart'; + +class ProductsHome extends StatelessWidget { + const ProductsHome({super.key}); + + @override + Widget build(BuildContext context) { + final controller = context.get(); + return Scaffold( + appBar: AppBar( + title: Text(controller.title), + ), + body: Center( + child: SizedBox( + width: 420, + child: ListView( + children: [ + ElevatedButton( + onPressed: () { + Navigator.of(context).pushNamed('/Products/Detail'); + }, + child: const Text('Push Named Detail'), + ), + const SizedBox(height: 10), + ElevatedButton( + onPressed: () { + Navigator.of(context).pushReplacementNamed('/Products/'); + }, + child: const Text('Push Replacement this page'), + ), + const SizedBox(height: 10), + ElevatedButton( + onPressed: () { + Navigator.of(context).pushNamedAndRemoveUntil( + '/Products/', + (route) => false, + ); + }, + child: const Text('Push NamedAndRemoveUntil this page'), + ), + const SizedBox(height: 10), + ElevatedButton( + onPressed: () { + Navigator.of(context).popAndPushNamed('/Products/'); + }, + child: const Text('Push popAndPushNamed this page'), + ), + ], + ), + ), + ), + ); + } +} diff --git a/example/lib/src/products/products_module.dart b/example/lib/src/products/products_module.dart deleted file mode 100644 index 2e01017..0000000 --- a/example/lib/src/products/products_module.dart +++ /dev/null @@ -1,74 +0,0 @@ -import 'package:example/src/loader/load_dependencies.dart'; -import 'package:example/src/products/product_controller.dart'; -import 'package:example/src/products/products_detail.dart'; -import 'package:example/src/products/products_page.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -class ProductsModule extends FlutterGetItModule { - @override - String get moduleRouteName => '/Products'; - - @override - List> get bindings => []; - - @override - List get pages => [ - FlutterGetItModuleRouter( - name: "/Page", - pages: [ - FlutterGetItPageRouter( - name: '/', - builderAsync: (context, isReady, loader) => switch (isReady) { - true => ProductsPage( - ctrl: context.get(), - ), - false => loader ?? const WidgetLoadDependencies(), - }, - bindings: [ - Bind.lazySingleton( - (i) => ProductController(), - ) - ], - ), - FlutterGetItPageRouter( - name: '/Detail', - builderAsync: (context, isReady, loader) => switch (isReady) { - true => const ProductsDetail(), - false => loader ?? const WidgetLoadDependencies(), - }, - bindings: [], - ), - ], - ), - // FlutterGetItPageRouter( - // name: '/Page', - // builderAsync: (context, isReady, loader) => switch (isReady) { - // true => ProductsPage( - // ctrl: context.get(), - // ), - // false => loader ?? const WidgetLoadDependencies(), - // }, - // bindings: [ - // Bind.lazySingleton( - // (i) => ProductController(), - // ) - // ], - // pages: [ - // FlutterGetItPageRouter( - // name: '/Detail', - // builderAsync: (context, isReady, loader) => switch (isReady) { - // true => const ProductsDetail(), - // false => loader ?? const WidgetLoadDependencies(), - // }, - // bindings: [], - // ), - // ], - // ), - ]; - - @override - void onDispose(Injector i) {} - - @override - void onInit(Injector i) {} -} diff --git a/example/lib/src/products/products_page.dart b/example/lib/src/products/products_page.dart deleted file mode 100644 index 86f52c2..0000000 --- a/example/lib/src/products/products_page.dart +++ /dev/null @@ -1,27 +0,0 @@ -import 'package:example/src/products/model/product_model.dart'; -import 'package:example/src/products/product_controller.dart'; -import 'package:flutter/material.dart'; - -class ProductsPage extends StatelessWidget { - final ProductController ctrl; - const ProductsPage({super.key, required this.ctrl}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Products'), - ), - body: ListView.builder( - itemCount: ProductModel.getFake.length, - itemBuilder: (context, index) => ListTile( - title: Text('Product ${ProductModel.getFake[index].name}'), - onTap: () => Navigator.of(context).pushNamed( - '/Products/Page/Detail', - arguments: ProductModel.getFake[index], - ), - ), - ), - ); - } -} diff --git a/example/lib/src/products/service/product_service.dart b/example/lib/src/products/service/product_service.dart new file mode 100644 index 0000000..c322545 --- /dev/null +++ b/example/lib/src/products/service/product_service.dart @@ -0,0 +1 @@ +class ProductService {} diff --git a/example/lib/src/random/random_controller.dart b/example/lib/src/random/random_controller.dart deleted file mode 100644 index c727230..0000000 --- a/example/lib/src/random/random_controller.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:flutter_getit/flutter_getit.dart'; - -class RandomController with FlutterGetItMixin { - final String title; - - RandomController(this.title); - @override - void onDispose() {} - - @override - void onInit() {} -} diff --git a/example/lib/src/random/random_page.dart b/example/lib/src/random/random_page.dart deleted file mode 100644 index 85c2ac4..0000000 --- a/example/lib/src/random/random_page.dart +++ /dev/null @@ -1,23 +0,0 @@ -import 'package:example/src/random/random_controller.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -class RandomPage extends StatelessWidget { - const RandomPage({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(context.get().title), - ), - body: Center( - child: ElevatedButton( - onPressed: () { - Navigator.of(context).pushNamed('/Random/Page2'); - }, - child: const Text('Random Page2 ')), - ), - ); - } -} diff --git a/example/lib/src/route_outlet_nav_bar/my_nav_bar.dart b/example/lib/src/route_outlet_nav_bar/my_nav_bar.dart deleted file mode 100644 index 3df78b0..0000000 --- a/example/lib/src/route_outlet_nav_bar/my_nav_bar.dart +++ /dev/null @@ -1,84 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -final internalNav = GlobalKey(); -final internalNav2 = GlobalKey(); - -class RouteOutletMyNavBar extends StatefulWidget { - const RouteOutletMyNavBar({super.key}); - - @override - State createState() => _RouteOutletMyNavBarState(); -} - -class _RouteOutletMyNavBarState extends State { - var _currentIndex = 0; - @override - Widget build(BuildContext context) { - return Scaffold( - body: FlutterGetItRouteOutlet( - initialRoute: '/Auth/Login', - navKey: internalNav, - transitionsBuilder: (context, animation, secondaryAnimation, child) => - ScaleTransition( - scale: Tween(begin: 0.0, end: 1.0).animate(animation), - child: child, - ), - ), - bottomNavigationBar: BottomNavigationBar( - currentIndex: _currentIndex, - onTap: (value) { - if (_currentIndex != value) { - switch (value) { - case 0: - internalNav.currentState - ?.pushNamedAndRemoveUntil('/Auth/Login', (_) => false); - case 1: - internalNav.currentState?.pushNamedAndRemoveUntil( - '/Auth/Register/Page', (_) => false); - case 2: - internalNav.currentState - ?.pushNamedAndRemoveUntil('/RootNavBar/Root', (_) => false); - case 3: - internalNav.currentState?.pushNamedAndRemoveUntil( - '/Landing/Initialize', (_) => false); - } - setState(() { - _currentIndex = value; - }); - } - }, - items: const [ - BottomNavigationBarItem( - icon: Icon( - Icons.home, - color: Colors.blueAccent, - ), - label: 'Login', - ), - BottomNavigationBarItem( - icon: Icon( - Icons.production_quantity_limits, - color: Colors.blueAccent, - ), - label: 'Register', - ), - BottomNavigationBarItem( - icon: Icon( - Icons.home, - color: Colors.blueAccent, - ), - label: 'Custom NavBar', - ), - BottomNavigationBarItem( - icon: Icon( - Icons.home, - color: Colors.blueAccent, - ), - label: 'Presentation', - ), - ], - ), - ); - } -} diff --git a/example/lib/src/route_outlet_nav_bar/my_nav_bar_helper_controller.dart b/example/lib/src/route_outlet_nav_bar/my_nav_bar_helper_controller.dart deleted file mode 100644 index 738518d..0000000 --- a/example/lib/src/route_outlet_nav_bar/my_nav_bar_helper_controller.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:flutter_getit/flutter_getit.dart'; - -class MyNavBarHelperController with FlutterGetItMixin { - @override - void onDispose() {} - - @override - void onInit() {} -} diff --git a/example/lib/src/route_outlet_nav_bar/nav_bar_module.dart b/example/lib/src/route_outlet_nav_bar/nav_bar_module.dart deleted file mode 100644 index 0b0e186..0000000 --- a/example/lib/src/route_outlet_nav_bar/nav_bar_module.dart +++ /dev/null @@ -1,28 +0,0 @@ -import 'package:example/src/loader/load_dependencies.dart'; -import 'package:example/src/nav_bar/my_nav_bar.dart'; -import 'package:flutter_getit/flutter_getit.dart'; - -class NavBarModule extends FlutterGetItModule { - @override - String get moduleRouteName => '/RootNavBar'; - - @override - List> get bindings => []; - - @override - List get pages => [ - FlutterGetItPageRouter( - name: '/Root', - builderAsync: (context, isReady, loader) => switch (isReady) { - true => const MyNavBar(), - false => loader ?? const WidgetLoadDependencies(), - }, - ), - ]; - - @override - void onDispose(Injector i) {} - - @override - void onInit(Injector i) {} -} diff --git a/example/lib/src/splash/splash_page.dart b/example/lib/src/splash/splash_page.dart index 1a8c5a0..23b7b73 100644 --- a/example/lib/src/splash/splash_page.dart +++ b/example/lib/src/splash/splash_page.dart @@ -1,45 +1,21 @@ import 'package:flutter/material.dart'; -class SplashPage extends StatefulWidget { +class SplashPage extends StatelessWidget { const SplashPage({super.key}); - @override - State createState() => _SplashPageState(); -} - -class _SplashPageState extends State { - double width = 0.0; - double height = 0.0; - - @override - void initState() { - WidgetsBinding.instance.addPostFrameCallback((_) async { - setState(() { - width = 200; - height = 200; - }); - await Future.delayed(const Duration(seconds: 2)); - if (mounted) { - Navigator.of(context).pushReplacementNamed('/Landing/Initialize'); - } - }); - super.initState(); - } - @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: const Text('SplashPage'), + title: const Text('Splash Page'), ), body: Center( - child: AnimatedContainer( - duration: const Duration(seconds: 2), - width: width, - height: height, - child: const FlutterLogo( - size: 200, - )), + child: ElevatedButton( + onPressed: () { + Navigator.of(context).pushNamed('/Home'); + }, + child: const Text('Go to Home'), + ), ), ); } diff --git a/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 15368ec..ac78810 100644 --- a/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -59,6 +59,7 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" + enableGPUValidationMode = "1" allowLocationSimulation = "YES"> diff --git a/example/macos/Runner/AppDelegate.swift b/example/macos/Runner/AppDelegate.swift index 8e02df2..b3c1761 100644 --- a/example/macos/Runner/AppDelegate.swift +++ b/example/macos/Runner/AppDelegate.swift @@ -6,4 +6,8 @@ class AppDelegate: FlutterAppDelegate { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true } + + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } } diff --git a/example/pubspec.lock b/example/pubspec.lock index d7ec9c6..0314d4e 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: transitive description: name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 url: "https://pub.dev" source: hosted - version: "2.11.0" + version: "2.12.0" boolean_selector: dependency: transitive description: name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" characters: dependency: transitive description: @@ -29,18 +29,26 @@ packages: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" collection: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + url: "https://pub.dev" + source: hosted + version: "1.19.0" + crypto: + dependency: transitive + description: + name: crypto + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "3.0.6" cupertino_icons: dependency: "direct main" description: @@ -53,10 +61,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.2" ffi: dependency: transitive description: @@ -73,6 +81,14 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" flutter: dependency: "direct main" description: flutter @@ -84,7 +100,7 @@ packages: path: ".." relative: true source: path - version: "3.0.0" + version: "3.0.1" flutter_lints: dependency: "direct dev" description: @@ -99,7 +115,7 @@ packages: source: sdk version: "0.0.0" flutter_web_plugins: - dependency: transitive + dependency: "direct main" description: flutter source: sdk version: "0.0.0" @@ -107,26 +123,26 @@ packages: dependency: transitive description: name: get_it - sha256: d85128a5dae4ea777324730dc65edd9c9f43155c109d5cc0a69cab74139fbac1 + sha256: f126a3e286b7f5b578bf436d5592968706c4c1de28a228b870ce375d9f743103 url: "https://pub.dev" source: hosted - version: "7.7.0" + version: "8.0.3" leak_tracker: dependency: transitive description: name: leak_tracker - sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec url: "https://pub.dev" source: hosted - version: "10.0.5" + version: "10.0.8" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.9" leak_tracker_testing: dependency: transitive description: @@ -171,10 +187,10 @@ packages: dependency: transitive description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" path_provider_linux: dependency: transitive description: @@ -275,7 +291,7 @@ packages: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_span: dependency: transitive description: @@ -284,14 +300,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" stack_trace: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.12.0" stream_channel: dependency: transitive description: @@ -304,10 +328,10 @@ packages: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "0bd04f5bb74fcd6ff0606a888a30e917af9bd52820b178eaa464beb11dca84b6" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.4.0" term_glyph: dependency: transitive description: @@ -320,10 +344,26 @@ packages: dependency: transitive description: name: test_api - sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" + sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + url: "https://pub.dev" + source: hosted + version: "0.7.3" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + uuid: + dependency: transitive + description: + name: uuid + sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff url: "https://pub.dev" source: hosted - version: "0.7.2" + version: "4.5.1" vector_math: dependency: transitive description: @@ -336,10 +376,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" + sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" url: "https://pub.dev" source: hosted - version: "14.2.5" + version: "14.3.1" web: dependency: transitive description: @@ -357,5 +397,5 @@ packages: source: hosted version: "1.0.4" sdks: - dart: ">=3.4.0 <4.0.0" + dart: ">=3.5.0 <4.0.0" flutter: ">=3.22.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 0a75a41..b3a2831 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -30,6 +30,8 @@ environment: dependencies: flutter: sdk: flutter + flutter_web_plugins: + sdk: flutter # The following adds the Cupertino Icons font to your application. diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart deleted file mode 100644 index 092d222..0000000 --- a/example/test/widget_test.dart +++ /dev/null @@ -1,30 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility in the flutter_test package. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:example/main.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -} diff --git a/lib/flutter_getit.dart b/lib/flutter_getit.dart index b8b51c1..d420678 100644 --- a/lib/flutter_getit.dart +++ b/lib/flutter_getit.dart @@ -12,6 +12,20 @@ export 'src/middleware/flutter_get_it_sync_middleware.dart'; export 'src/mixin/flutter_get_it_mixin.dart'; export 'src/routers/flutter_getit_module.dart'; export 'src/routers/flutter_getit_module_page_router.dart'; +export 'src/v4/controller/flutter_get_it_controller.dart'; +//v4 +export 'src/v4/core/f_get_it.dart'; +export 'src/v4/debug/debug_fill_properties/material_debugger_wrapper.dart'; +export 'src/v4/delegate/flutter_get_it_delegate.dart'; +export 'src/v4/extensions/flutter_get_it_navigator.dart'; +export 'src/v4/middleware/flutter_get_it_middleware.dart'; +export 'src/v4/observer/flutter_get_it_route_observer.dart'; +export 'src/v4/router/flutter_get_it_router.dart'; +export 'src/v4/wallet/flutter_get_it_wallet.dart'; +export 'src/v4/widgets/flutter_get_it_error_page.dart'; +export 'src/v4/widgets/flutter_get_it_loader.dart'; +export 'src/v4/router/params/f_get_it_router_params.dart'; +// export 'src/widget/flutter_getit_route_outlet.dart'; export 'src/widget/flutter_getit_view.dart'; export 'src/widget/flutter_getit_widget.dart'; diff --git a/lib/src/config/flutter_getit_config.dart b/lib/src/config/flutter_getit_config.dart index cea236d..c643369 100644 --- a/lib/src/config/flutter_getit_config.dart +++ b/lib/src/config/flutter_getit_config.dart @@ -1,4 +1,4 @@ -import 'dart:async'; +/* import 'dart:async'; import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; @@ -439,3 +439,4 @@ class _FlutterGetItState extends State @override bool get wantKeepAlive => true; } + */ diff --git a/lib/src/core/flutter_getit_container_register.dart b/lib/src/core/flutter_getit_container_register.dart index 105df5f..c701adb 100644 --- a/lib/src/core/flutter_getit_container_register.dart +++ b/lib/src/core/flutter_getit_container_register.dart @@ -1,4 +1,4 @@ -import '../../flutter_getit.dart'; +/* import '../../flutter_getit.dart'; import '../middleware/flutter_get_it_middleware.dart'; import 'model/binding_register.dart'; @@ -99,8 +99,9 @@ final class FlutterGetItContainerRegister { b.tag == bind.tag, ), ); - if (!isUsed) { - _references[index].bindings[indexBind] = bind.unRegister(); + if (!isUsed && _references[index].listeners == 0) //TODO + { + _references[index].bindings[indexBind] = bind.unRegister(''); } else { _references[index].bindings[indexBind] = bind.copyWith(loaded: false); @@ -110,7 +111,9 @@ final class FlutterGetItContainerRegister { if (!_references[index].bindings.any( (element) => element.loaded, - )) _references.removeAt(index); + )) { + _references.removeAt(index); + } } } @@ -124,7 +127,7 @@ final class FlutterGetItContainerRegister { for (var bind in _references[index].bindings) { if (!bind.loaded) { final indexBind = _references[index].bindings.indexOf(bind); - final bindRegistered = bind.register(); + final bindRegistered = bind.register(''); if (bindRegistered != null) { _references[index].bindings[indexBind] = bindRegistered; @@ -150,3 +153,4 @@ final class FlutterGetItContainerRegister { return qntOfModuleId > 0; } } + */ diff --git a/lib/src/core/model/binding_register.dart b/lib/src/core/model/binding_register.dart index d2da54d..73d9576 100644 --- a/lib/src/core/model/binding_register.dart +++ b/lib/src/core/model/binding_register.dart @@ -1,4 +1,4 @@ -import '../../dependency_injector/binds/bind.dart'; +/* import '../../dependency_injector/binds/bind.dart'; import '../../middleware/flutter_get_it_middleware.dart'; final class RegisterModel { @@ -31,7 +31,9 @@ final class RegisterModel { /// Add a listener to the context. /// void addListener() { + print('Old listeners: $listeners'); listeners++; + print('New listeners: $listeners'); } /// Remove a listener from the context. @@ -55,3 +57,4 @@ final class RegisterModel { ); } } + */ diff --git a/lib/src/debug/debug_mode.dart b/lib/src/debug/debug_mode.dart index dd72f31..71e4b76 100644 --- a/lib/src/debug/debug_mode.dart +++ b/lib/src/debug/debug_mode.dart @@ -1,4 +1,4 @@ -import 'dart:convert'; +/* import 'dart:convert'; import 'dart:developer'; import 'package:flutter/foundation.dart'; @@ -73,3 +73,4 @@ final class DebugMode { } } } + */ diff --git a/lib/src/debug/extension/flutter_get_it_extension.dart b/lib/src/debug/extension/flutter_get_it_extension.dart index 759b6ad..677d6ef 100644 --- a/lib/src/debug/extension/flutter_get_it_extension.dart +++ b/lib/src/debug/extension/flutter_get_it_extension.dart @@ -7,26 +7,24 @@ import '../../../flutter_getit.dart'; @protected final class FlutterGetItExtension { - final FlutterGetItContainerRegister _register; - - FlutterGetItExtension({ - required FlutterGetItContainerRegister register, - }) : _register = register { + FlutterGetItExtension() { registerExtension( 'ext.br.com.academiadoflutter.flutter_getit.listAll', (_, parameters) async { final dataDefault = readyReferences(); return ServiceExtensionResponse.result( - jsonEncode({'data': dataDefault})); + jsonEncode( + {'data': dataDefault}, + ), + ); }, ); } Map>> readyReferences() { - final references = _register.references(); - var myMap = >>{}; + /* final references = _register.references(); for (var ref in references) { myMap[ref.id] = >[]; @@ -61,7 +59,7 @@ final class FlutterGetItExtension { ); } } - + */ return myMap; } } diff --git a/lib/src/debug/log/flutter_get_it_logger.dart b/lib/src/debug/log/flutter_get_it_logger.dart index 9792193..831459a 100644 --- a/lib/src/debug/log/flutter_get_it_logger.dart +++ b/lib/src/debug/log/flutter_get_it_logger.dart @@ -41,6 +41,7 @@ final class FGetItLogger { static const _logName = 'FGetIt'; static late FGetItLoggerConfig _config; static int logCount = 0; + static late List _applicationMiddlewares; static const FGetItLogColor _colors = ( cyan: '\x1b[36m', red: '\x1b[31m', @@ -50,8 +51,9 @@ final class FGetItLogger { blue: '\x1b[34m', ); - FGetItLogger(FGetItLoggerConfig s) { + FGetItLogger(FGetItLoggerConfig s, List applicationMiddlewares) { _config = s; + _applicationMiddlewares = applicationMiddlewares; } static String get _cyanColor => _config.colored ? _colors.cyan : ''; @@ -100,7 +102,9 @@ final class FGetItLogger { } static String _tagLog(String? tag) { - return tag != null ? '$_yellowColor with tag:$_cyanColor $tag' : ''; + return (tag != null && tag.isNotEmpty) + ? '$_yellowColor with tag:$_cyanColor $tag' + : ' NO TAG'; } static logGettingInstance({String? tag, String? factoryTag}) { @@ -207,15 +211,16 @@ final class FGetItLogger { static void logInstanceAlreadyRegistered(Bind bind) { if (_config.enable && _config.registerInstance) { _log( - '🚧$_yellowColor Attention you\'re trying to register the $T (${bind.type.name}) - ${_tagLog(bind.tag)} again.', + '| 🎣 $_yellowColor$T (${bind.type.name}) -${_tagLog(bind.tag)}\n| 🚨$_redColor Already registered on $_redColor[ ${bind.fullNameOfModuleRegister} ]', ); + logMidDivider(); } } static logRegisteringInstance(Bind bind) { if (_config.enable && _config.registerInstance) { _log( - '📠$_blueColor Registering: $T$_yellowColor as$_blueColor ${bind.type.name}${bind.keepAlive ? '$_yellowColor with$_blueColor keepAlive' : ''}${_tagLog(bind.tag)}', + '| 📠$_blueColor Registering: $T$_yellowColor as$_blueColor ${bind.type.name}${bind.keepAlive ? '$_yellowColor with$_blueColor keepAlive' : ''}${_tagLog(bind.tag)}', ); } } @@ -223,7 +228,7 @@ final class FGetItLogger { static logUnregisterFactory(String factoryTag, String hashCode) { if (_config.enable && _config.disposingInstance) { _log( - '🚮$_yellowColor Dispose: $T -$_blueColor as (Factory child)$_yellowColor - $hashCode - FactoryTag: $factoryTag', + '| 🚮$_yellowColor Dispose: $T -$_blueColor as (Factory child)$_yellowColor - $hashCode - FactoryTag: $factoryTag', ); } } @@ -268,6 +273,12 @@ final class FGetItLogger { } } + static void logMidDivider() { + if (_config.enable) { + _log('$_yellowColor|-----------------------------------\n'); + } + } + static logDisposeSubModule(String moduleName) { if (_config.enable && _config.enterAndExitModule) { _log( @@ -275,4 +286,116 @@ final class FGetItLogger { ); } } + + static void logCantUnregisteringInstance(Bind bind) { + if (_config.enable) { + _log( + '| 🚮$_yellowColor Dispose unavailable for $T (${bind.type.name}) - ${_tagLog(bind.tag)}\n| 🚨$_redColor Listeners$_redColor [ ${bind.listeners.join(' || ')} ]', + ); + } + } + + static void logNavigationTo(FlutterGetItRouteBase route) { + if (_config.enable) { + _log( + '${_initDivider(color: _yellowColor)}| 🛣️$_yellowColor Navigating to: ${route.fullPath}\n| Bindings: [ ${route.binds.map((e) => e.runtimeType.toString()).join(' || ')} ]\n| Middlewares: [ ${route.middlewares.map((e) => e.runtimeType.toString()).join(' || ')} ]\n| Application Middlewares: [ ${_applicationMiddlewares.map((e) => e).join(' || ')} ]${_endDivider(color: _yellowColor)}'); + } + } + + static String _initDivider({String? color}) { + return '${color ?? _yellowColor}-----------------------------------\n'; + } + + static String _endDivider({String? color}) { + return '\n${color ?? _yellowColor}-----------------------------------'; + } + + static void logInitDivider() { + if (_config.enable) { + _log('/${_initDivider(color: _yellowColor)}'); + } + } + + static void logEndDivider() { + if (_config.enable) { + _log(_endDivider(color: _yellowColor).replaceAll('\n', '\\')); + } + } + + static void logInitMiddleware(String origin) { + if (_config.enable) { + _log( + '/${_initDivider(color: _yellowColor)}| ⏳$_yellowColor Init middlewares by: $origin'); + } + } + + static void logRunningMiddleware(String middleware) { + if (_config.enable) { + _log('| ⏰$_yellowColor Running: $middleware'); + } + } + + static void logMiddlewareSuccess(String middleware) { + if (_config.enable) { + _log('| ✅$_greenColor Completed: $middleware'); + } + } + + static void logMiddlewareFail(String middleware) { + if (_config.enable) { + _log('| 🚨$_redColor Fail: $middleware'); + } + } + + static void logMiddlewareSkipped(String middleware) { + if (_config.enable) { + _log('\n| ⏩$_yellowColor Skipped: $middleware'); + } + } + + static void logSolvingAsyncDependenciesFor(String fullName) { + if (_config.enable) { + _log('| ⏰$_yellowColor Solving async dependencies for: $fullName'); + } + } + + static void logSolvingAsyncDependenciesCompleted(String fullName) { + if (_config.enable) { + _log('| ✅$_greenColor Complete async dependencies for: $fullName'); + } + } + + static void logInformThatTheNewRouteIsAsync(String path, String origin) { + if (_config.enable) { + _log( + '| ⏰$_yellowColor The navigation to "$path" will be async, because we detected: $origin'); + } + } + + static void logInformThatTheNewRouteIsSync(String path) { + if (_config.enable) { + _log( + '| ⏰$_yellowColor The navigation to "$path" will be sync, we don\'t detected any AsyncMiddleware or AsyncBinds'); + } + } + + static void logInitInitialRoute() { + if (_config.enable) { + _log( + '| ⏰$_yellowColor Init initial route detected, solving async dependencies'); + } + } + + static void logCallingDisposeRoute(String fullPath) { + if (_config.enable) { + _log('| 🚮$_yellowColor Calling dispose for: $fullPath'); + } + } + + static void logRedirectingTo(String currentPath, String redirectPath) { + if (_config.enable) { + _log( + '| 🔀$_redColor Attention you are trying navigate to: $_yellowColor$currentPath$_redColor define as a$_yellowColor "FlutterGetItModuleRoute"$_greenColor but we\'re redirecting to: $_yellowColor$redirectPath'); + } + } } diff --git a/lib/src/dependency_injector/binds/application_bindings.dart b/lib/src/dependency_injector/binds/application_bindings.dart index acd7c99..6dbdfe1 100644 --- a/lib/src/dependency_injector/binds/application_bindings.dart +++ b/lib/src/dependency_injector/binds/application_bindings.dart @@ -1,5 +1,3 @@ -import 'package:flutter/material.dart'; - import '../../../flutter_getit.dart'; @protected diff --git a/lib/src/dependency_injector/binds/bind.dart b/lib/src/dependency_injector/binds/bind.dart index a39f064..1fda407 100644 --- a/lib/src/dependency_injector/binds/bind.dart +++ b/lib/src/dependency_injector/binds/bind.dart @@ -2,7 +2,6 @@ import 'package:get_it/get_it.dart'; import '../../../flutter_getit.dart'; import '../../types/flutter_getit_typedefs.dart'; -import '../flutter_get_it_binding_opened.dart'; enum RegisterType { singleton, @@ -18,19 +17,12 @@ final class Bind { final BindAsyncRegister? bindAsyncRegister; final RegisterType type; final bool keepAlive; - final bool isTheFactoryDad; final String? tag; final Iterable dependsOn; - final bool loaded; - - Bind._( - this.bindRegister, - this.type, - this.keepAlive, - this.tag, - this.isTheFactoryDad, - this.dependsOn, - this.loaded, + List listeners = []; + String fullNameOfModuleRegister = ''; + bool isInitialized = false; + Bind._(this.bindRegister, this.type, this.keepAlive, this.tag, this.dependsOn, this.bindAsyncRegister); Bind._async( @@ -38,9 +30,7 @@ final class Bind { this.type, this.keepAlive, this.tag, - this.isTheFactoryDad, this.dependsOn, - this.loaded, this.bindRegister, ); @@ -57,9 +47,7 @@ final class Bind { RegisterType.singleton, keepAlive, tag, - false, dependsOn, - false, null, ); @@ -73,9 +61,7 @@ final class Bind { RegisterType.lazySingleton, keepAlive, tag, - false, [], - false, null, ); @@ -88,9 +74,7 @@ final class Bind { RegisterType.factory, false, tag, - true, [], - false, null, ); @@ -105,9 +89,7 @@ final class Bind { RegisterType.singletonAsync, keepAlive, tag, - false, dependsOn, - false, null, ); @@ -121,9 +103,7 @@ final class Bind { RegisterType.lazySingletonAsync, keepAlive, tag, - false, [], - false, null, ); @@ -136,64 +116,70 @@ final class Bind { RegisterType.factoryAsync, false, tag, - true, [], - false, null, ); - Bind unRegister() { + void unRegister(String fullNameOfModuleListener) { + final bind = GetIt.I.get>(instanceName: tag); + bind.listeners.remove(fullNameOfModuleListener); if (keepAlive) { FGetItLogger.logTryUnregisterBingWithKeepAlive(); - return this; + return; } - final isFactory = - type == RegisterType.factory || type == RegisterType.factoryAsync; - - if (isFactory && !isTheFactoryDad) { - return this; - } else if (isFactory && isTheFactoryDad) { - FlutterGetItBindingOpened.unRegisterFactories(); + if (bind.listeners.isEmpty) { + FGetItLogger.logDisposeInstance(this); + GetIt.I.unregister( + instanceName: tag, + disposingFunction: (entity) async { + if (itIs(entity)) { + (entity as FlutterGetItController).onDispose(); + } + isInitialized = false; + }, + ); + GetIt.I.unregister>(instanceName: tag); + } else { + FGetItLogger.logCantUnregisteringInstance(this); } + FGetItLogger.logMidDivider(); - FGetItLogger.logDisposeInstance(this); - GetIt.I.unregister( - instanceName: tag, - disposingFunction: (entity) async { - if (hasMixin(entity)) { - (entity as FlutterGetItMixin).onDispose(); - } - - FlutterGetItBindingOpened.unRegisterHashCodeOpened(entity.hashCode); - }, - ); + return; + } - return this.copyWith(loaded: false); + T getInstance() { + isInitialized = true; + return GetIt.I.get(instanceName: tag); } - Bind? register() { + void register(String fullNameOfModule) { final getIt = GetIt.I; final isRegistered = getIt.isRegistered(instanceName: tag); if (isRegistered) { + final bind = getIt.get>(instanceName: tag); + bind.listeners.add(fullNameOfModule); FGetItLogger.logInstanceAlreadyRegistered(this); - return copyWith(loaded: true); + return; } + this.listeners.add(fullNameOfModule); + this.fullNameOfModuleRegister = fullNameOfModule; FGetItLogger.logRegisteringInstance(this); + getIt.registerSingleton>(this, instanceName: tag); switch (type) { case RegisterType.singleton: if (dependsOn.isEmpty) { getIt.registerSingleton( - bindRegister!(Injector()), + bindRegister!(FGetIt()), instanceName: tag, dispose: (entity) => null, signalsReady: false, ); } else { getIt.registerSingletonWithDependencies( - () => bindRegister!(Injector()), + () => bindRegister!(FGetIt()), instanceName: tag, dispose: (entity) => null, dependsOn: dependsOn, @@ -202,13 +188,13 @@ final class Bind { } case RegisterType.lazySingleton: getIt.registerLazySingleton( - () => bindRegister!(Injector()), + () => bindRegister!(FGetIt()), instanceName: tag, dispose: (entity) => null, ); case RegisterType.singletonAsync: getIt.registerSingletonAsync( - () async => await bindAsyncRegister!(Injector()), + () async => await bindAsyncRegister!(FGetIt()), instanceName: tag, dispose: (entity) => null, dependsOn: dependsOn, @@ -216,53 +202,28 @@ final class Bind { ); case RegisterType.lazySingletonAsync: getIt.registerLazySingletonAsync( - () async => await bindAsyncRegister!(Injector()), + () async => await bindAsyncRegister!(FGetIt()), instanceName: tag, dispose: (entity) => null, ); case RegisterType.factory: - FlutterGetItBindingOpened.registerFactoryDad(); getIt.registerFactory( - () => bindRegister!(Injector()), + () => bindRegister!(FGetIt()), instanceName: tag, ); case RegisterType.factoryAsync: - FlutterGetItBindingOpened.registerFactoryDad(); getIt.registerFactoryAsync( - () async => await bindAsyncRegister!(Injector()), + () async => await bindAsyncRegister!(FGetIt()), instanceName: tag, ); } - return copyWith(loaded: true); + return; } @override String toString() { return 'Bind{bindRegister=$bindRegister, type=$type}'; } - - //copyWith method - Bind copyWith({ - BindRegister? bindRegister, - BindAsyncRegister? bindAsyncRegister, - RegisterType? type, - bool? keepAlive, - bool? isTheFactoryDad, - String? tag, - Iterable? dependsOn, - bool? loaded, - }) { - return Bind._( - bindRegister ?? this.bindRegister, - type ?? this.type, - keepAlive ?? this.keepAlive, - tag ?? this.tag, - isTheFactoryDad ?? this.isTheFactoryDad, - dependsOn ?? this.dependsOn, - loaded ?? this.loaded, - bindAsyncRegister ?? this.bindAsyncRegister, - ); - } } diff --git a/lib/src/dependency_injector/flutter_get_it_binding_opened.dart b/lib/src/dependency_injector/flutter_get_it_binding_opened.dart index 22091a9..20cef92 100644 --- a/lib/src/dependency_injector/flutter_get_it_binding_opened.dart +++ b/lib/src/dependency_injector/flutter_get_it_binding_opened.dart @@ -1,4 +1,4 @@ -import '../../flutter_getit.dart'; +/* import '../../flutter_getit.dart'; typedef FactoryRegister = ({Object obj, String? factoryTag}); @@ -96,3 +96,4 @@ final class FlutterGetItBindingOpened { return _factory.containsKey(T); } } + */ diff --git a/lib/src/dependency_injector/flutter_get_it_check_dependency.dart b/lib/src/dependency_injector/flutter_get_it_check_dependency.dart index 4f7fce1..bf1bb4a 100644 --- a/lib/src/dependency_injector/flutter_get_it_check_dependency.dart +++ b/lib/src/dependency_injector/flutter_get_it_check_dependency.dart @@ -1,4 +1,4 @@ -import 'package:flutter/rendering.dart'; +/* import 'package:flutter/rendering.dart'; import '../../flutter_getit.dart'; @@ -38,3 +38,4 @@ final class FlutterGetItCheckDependency { return bindings.map((bind) => bind.bindingClassName).toSet(); } } + */ diff --git a/lib/src/dependency_injector/injector.dart b/lib/src/dependency_injector/injector.dart index 1d86d9e..2ecaf05 100644 --- a/lib/src/dependency_injector/injector.dart +++ b/lib/src/dependency_injector/injector.dart @@ -1,4 +1,4 @@ -import 'package:flutter/material.dart'; +/* import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; import '../../flutter_getit.dart'; @@ -128,3 +128,4 @@ extension InjectorContext on BuildContext { bool any() => Injector.any(); } + */ diff --git a/lib/src/enum/middleware_result.dart b/lib/src/enum/middleware_result.dart index a29015d..b3a920b 100644 --- a/lib/src/enum/middleware_result.dart +++ b/lib/src/enum/middleware_result.dart @@ -1 +1,2 @@ -enum MiddlewareResult { next, failure, complete } +/* enum MiddlewareResult { next, failure, complete } + */ diff --git a/lib/src/middleware/flutter_get_it_async_middleware.dart b/lib/src/middleware/flutter_get_it_async_middleware.dart index 7ef95aa..a3dee66 100644 --- a/lib/src/middleware/flutter_get_it_async_middleware.dart +++ b/lib/src/middleware/flutter_get_it_async_middleware.dart @@ -1,4 +1,4 @@ -import 'dart:async'; +/* import 'dart:async'; import 'package:flutter/material.dart'; @@ -9,3 +9,4 @@ abstract class FlutterGetItAsyncMiddleware extends FlutterGetItMiddleware { Future execute(RouteSettings? route); Widget onExecute = const Center(child: CircularProgressIndicator.adaptive()); } + */ diff --git a/lib/src/middleware/flutter_get_it_middleware.dart b/lib/src/middleware/flutter_get_it_middleware.dart index b2621a1..3f50e9c 100644 --- a/lib/src/middleware/flutter_get_it_middleware.dart +++ b/lib/src/middleware/flutter_get_it_middleware.dart @@ -1,4 +1,4 @@ -import 'dart:async'; +/* import 'dart:async'; import 'package:flutter/material.dart'; @@ -14,3 +14,4 @@ abstract class FlutterGetItMiddleware { } } } + */ diff --git a/lib/src/middleware/flutter_get_it_middleware_context.dart b/lib/src/middleware/flutter_get_it_middleware_context.dart index ea38f0b..f8ecad9 100644 --- a/lib/src/middleware/flutter_get_it_middleware_context.dart +++ b/lib/src/middleware/flutter_get_it_middleware_context.dart @@ -1,4 +1,4 @@ -import 'package:flutter/material.dart'; +/* import 'package:flutter/material.dart'; class FlutterGetItMiddlewareContext { final BuildContext _context; @@ -90,3 +90,4 @@ class FlutterGetItMiddlewareContext { ); } } + */ diff --git a/lib/src/middleware/flutter_get_it_sync_middleware.dart b/lib/src/middleware/flutter_get_it_sync_middleware.dart index 011cec6..8765872 100644 --- a/lib/src/middleware/flutter_get_it_sync_middleware.dart +++ b/lib/src/middleware/flutter_get_it_sync_middleware.dart @@ -1,4 +1,4 @@ -import 'package:flutter/material.dart'; +/* import 'package:flutter/material.dart'; import '../../flutter_getit.dart'; import 'flutter_get_it_middleware.dart'; @@ -8,3 +8,4 @@ abstract class FlutterGetItSyncMiddleware extends FlutterGetItMiddleware { return MiddlewareResult.next; } } + */ diff --git a/lib/src/routers/flutter_get_it_route_params_extractor.dart b/lib/src/routers/flutter_get_it_route_params_extractor.dart index db8a4fa..bf86312 100644 --- a/lib/src/routers/flutter_get_it_route_params_extractor.dart +++ b/lib/src/routers/flutter_get_it_route_params_extractor.dart @@ -22,8 +22,9 @@ class FlutterGetItRouteParamsExtractor { final patternSegment = patternSegments[i]; final routeSegment = routeSegments.length > i ? routeSegments[i] : null; - if (routeSegment == null) + if (routeSegment == null) { break; // Se não houver mais segmentos, sair do loop + } if (_isDynamicSegment(patternSegment)) { final paramName = _createParamName(patternSegments, i, patternSegment); diff --git a/lib/src/routers/flutter_getit_module.dart b/lib/src/routers/flutter_getit_module.dart index 1478cb4..49347f3 100644 --- a/lib/src/routers/flutter_getit_module.dart +++ b/lib/src/routers/flutter_getit_module.dart @@ -1,4 +1,4 @@ -import 'dart:async'; +/* import 'dart:async'; import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; @@ -309,3 +309,4 @@ class _FlutterGetItPageModuleState extends State { return MiddlewareResult.complete; } } + */ diff --git a/lib/src/routers/flutter_getit_module_page_router.dart b/lib/src/routers/flutter_getit_module_page_router.dart index 63e906e..1589c4a 100644 --- a/lib/src/routers/flutter_getit_module_page_router.dart +++ b/lib/src/routers/flutter_getit_module_page_router.dart @@ -1,4 +1,4 @@ -import 'package:flutter/material.dart'; +/* import 'package:flutter/material.dart'; import '../../flutter_getit.dart'; import '../middleware/flutter_get_it_middleware.dart'; @@ -174,3 +174,4 @@ class FlutterGetItModuleRouter extends FlutterGetItPageRouter { ); } } + */ diff --git a/lib/src/types/flutter_getit_typedefs.dart b/lib/src/types/flutter_getit_typedefs.dart index 2d6852a..2bc4ae4 100644 --- a/lib/src/types/flutter_getit_typedefs.dart +++ b/lib/src/types/flutter_getit_typedefs.dart @@ -1,14 +1,14 @@ import 'package:flutter/cupertino.dart'; import '../dependency_injector/binds/bind.dart'; -import '../dependency_injector/injector.dart'; +import '../v4/core/f_get_it.dart'; typedef ApplicationBindingsBuilder = List Function(); typedef BindBuilder = Bind Function(); -typedef BindRegister = T Function(Injector i); -typedef BindAsyncRegister = Future Function(Injector i); +typedef BindRegister = T Function(FGetIt i); +typedef BindAsyncRegister = Future Function(FGetIt i); typedef ApplicationBuilder = Widget Function( BuildContext context, Map routes, diff --git a/lib/src/v4/controller/flutter_get_it_controller.dart b/lib/src/v4/controller/flutter_get_it_controller.dart new file mode 100644 index 0000000..d4e68cb --- /dev/null +++ b/lib/src/v4/controller/flutter_get_it_controller.dart @@ -0,0 +1,12 @@ +abstract class FlutterGetItController { + FlutterGetItController() { + onInit(); + } + void onDispose(); + + void onInit(); +} + +bool itIs(Object object) { + return object is T; +} diff --git a/lib/src/v4/core/f_get_it.dart b/lib/src/v4/core/f_get_it.dart new file mode 100644 index 0000000..5a497f1 --- /dev/null +++ b/lib/src/v4/core/f_get_it.dart @@ -0,0 +1,335 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:get_it/get_it.dart'; + +import '../../../flutter_getit.dart'; +import '../../helper/flutter_get_it_helper.dart'; + +class FGetIt { + static bool isRegistered({String? tag}) { + return GetIt.I.isRegistered>(instanceName: tag); + } + + //static dynamic get arguments => FlutterGetItBindingOpened.argument; + + static bool any() { + return GetIt.I.getAll>().isNotEmpty; + } + + static T get({ + String? tag, + String? factoryTag, + }) { + try { + final getIt = GetIt.I; + FlutterGetItHelper.throwIfNot( + getIt.isRegistered>( + instanceName: tag, + ), + FlutterError( + 'The type $T is not registered in the FlutterGetIt, please check if it is registered in the module or in the main.', + ), + ); + + return getIt.get>(instanceName: tag).getInstance(); + } on AssertionError catch (e) { + FGetItLogger.logErrorInGetInstance( + e.toString(), + tag: tag, + factoryTag: factoryTag, + ); + rethrow; + } + } + + static Future getAsync( + {String? tag, String? factoryTag}) async { + try { + FGetItLogger.logGettingAsyncInstance(tag: tag, factoryTag: factoryTag); + + return await GetIt.I.isReady(instanceName: tag).then((_) { + FGetItLogger.logAsyncInstanceReady( + tag: tag, + factoryTag: factoryTag, + ); + + return get>(tag: tag, factoryTag: factoryTag).getInstance(); + }); + } on AssertionError catch (e) { + FGetItLogger.logErrorInGetAsyncInstance( + e.toString(), + tag: tag, + factoryTag: factoryTag, + ); + throw Exception('${T.toString()} not found in FlutterGetIt'); + } + } + + static Future allReady() async { + FGetItLogger.logWaitingAllReady(); + + await GetIt.I.allReady().then((value) { + FGetItLogger.logWaitingAllReadyCompleted(); + }); + } + + T call({String? tag, String? factoryTag}) => + get(tag: tag, factoryTag: factoryTag); + + static void debugFillProperties(DiagnosticPropertiesBuilder properties) { + final fGetItWallet = GetIt.I.get(); + final route = fGetItWallet.routeStack.last; + properties.add(DiagnosticsProperty( + 'Route', + route, + )); + } +} + +extension FGetItContext on BuildContext { + T get({String? tag, String? factoryTag}) => + FGetIt.get(tag: tag, factoryTag: factoryTag); + + Future getAsync({String? tag, String? factoryTag}) => + FGetIt.getAsync(tag: tag, factoryTag: factoryTag); + + bool isRegistered({String? tag}) => + FGetIt.isRegistered(tag: tag); + + bool any() => FGetIt.any(); +/* + /// All bellow is for the navigator + NavigatorState get _navigator => + GetIt.I.get().navigatorKey.currentState!; + static dynamic _arguments; + dynamic get arguments => _arguments; + //set arguments(dynamic value) => _arguments = value; + + void _openLoader() { + showDialog( + barrierDismissible: false, + context: _navigator.context, + builder: (context) => const Center( + child: Card( + child: Padding( + padding: EdgeInsets.all(16.0), + child: CircularProgressIndicator(), + )), + ), + ); + } + + void _closeLoader() { + Navigator.of(_navigator.context).pop(); + } + + Future pushNamed( + String routeName, { + Object? arguments, + }) async { + _arguments = arguments; + final fGetItWallet = GetIt.I.get(); + final appMiddlewares = fGetItWallet.applicationMiddlewares; + final parentsMiddlewares = fGetItWallet.getParentMiddlewares(routeName); + final routeMiddlewares = fGetItWallet.getRouteMiddlewares(routeName); + + //Any async middleware? + final anyAsyncMiddleware = appMiddlewares + .any((middleware) => middleware is FlutterGetItAsyncMiddleware) || + parentsMiddlewares + .any((middleware) => middleware is FlutterGetItAsyncMiddleware) || + routeMiddlewares + .any((middleware) => middleware is FlutterGetItAsyncMiddleware); + + if (anyAsyncMiddleware) { + _openLoader(); + } + + for (var middleware in appMiddlewares) { + FGetItLogger.logInitMiddleware('Application Middlewares'); + if (middleware.when(routeName) == MiddlewareAction.execute) { + FGetItLogger.logRunningMiddleware(middleware.runtimeType.toString()); + final result = await middleware.execute(arguments); + if (result != MiddlewareStatus.success) { + FGetItLogger.logMiddlewareFail(middleware.runtimeType.toString()); + FGetItLogger.logEndDivider(); + _closeLoader(); + return null; + } + FGetItLogger.logMiddlewareSuccess(middleware.runtimeType.toString()); + } else { + FGetItLogger.logMiddlewareSkipped(middleware.runtimeType.toString()); + } + } + FGetItLogger.logEndDivider(); + + FGetItLogger.logInitMiddleware('Parent Middlewares'); + for (var middleware in parentsMiddlewares) { + FGetItLogger.logRunningMiddleware(middleware.runtimeType.toString()); + if (middleware.when(routeName) == MiddlewareAction.execute) { + final result = await middleware.execute(arguments); + if (result != MiddlewareStatus.success) { + FGetItLogger.logMiddlewareFail(middleware.runtimeType.toString()); + FGetItLogger.logEndDivider(); + _closeLoader(); + return null; + } + FGetItLogger.logMiddlewareSuccess(middleware.runtimeType.toString()); + } else { + FGetItLogger.logMiddlewareSkipped(middleware.runtimeType.toString()); + } + } + FGetItLogger.logEndDivider(); + + FGetItLogger.logInitMiddleware('Route Middlewares'); + for (var middleware in routeMiddlewares) { + FGetItLogger.logRunningMiddleware(middleware.runtimeType.toString()); + if (middleware.when(routeName) == MiddlewareAction.execute) { + final result = await middleware.execute(arguments); + if (result != MiddlewareStatus.success) { + FGetItLogger.logMiddlewareFail(middleware.runtimeType.toString()); + FGetItLogger.logEndDivider(); + _closeLoader(); + return null; + } + FGetItLogger.logMiddlewareSuccess(middleware.runtimeType.toString()); + } else { + FGetItLogger.logMiddlewareSkipped(middleware.runtimeType.toString()); + } + } + FGetItLogger.logEndDivider(); + + await _initRoute(routeName); + + if (anyAsyncMiddleware) { + _closeLoader(); + } + + return _navigator.pushNamed( + routeName, + arguments: arguments, + ); + } + + FutureOr _initRoute(String path) async { + FGetItLogger.logInitDivider(); + final fGetItWallet = GetIt.I.get(); + + //Init parent binds + final parentBinds = fGetItWallet.getParentBinds(path); + final routeBinds = fGetItWallet.getRouteBindings(path); + for (var bind in parentBinds) { + bind.register(path); + } + + //Init route binds + for (var bind in routeBinds) { + bind.register(path); + } + FGetItLogger.logSolvingAsyncDependenciesFor(path); + await GetIt.I.allReady().then((value) { + FGetItLogger.logSolvingAsyncDependenciesCompleted(path); + }); + FGetItLogger.logEndDivider(); + return; + } + + Future pushReplacementNamed( + String routeName, { + TO? result, + Object? arguments, + }) { + return _navigator.pushReplacementNamed( + routeName, + result: result, + arguments: arguments, + ); + } + + Future popAndPushNamed( + String routeName, { + TO? result, + Object? arguments, + }) { + return _navigator.popAndPushNamed( + routeName, + result: result, + arguments: arguments, + ); + } + + Future pushNamedAndRemoveUntil( + String newRouteName, + RoutePredicate predicate, { + Object? arguments, + }) { + return _navigator.pushNamedAndRemoveUntil( + newRouteName, + predicate, + arguments: arguments, + ); + } + + String? restorablePushNamed( + String routeName, { + Object? arguments, + }) { + return _navigator.restorablePushNamed( + routeName, + arguments: arguments, + ); + } + + String? restorablePushReplacementNamed( + String routeName, { + T? result, + Object? arguments, + }) { + return _navigator.restorablePushReplacementNamed( + routeName, + result: result, + arguments: arguments, + ); + } + + String? restorablePopAndPushNamed( + String routeName, { + T? result, + Object? arguments, + }) { + return _navigator.restorablePopAndPushNamed( + routeName, + result: result, + arguments: arguments, + ); + } + + String? restorablePushNamedAndRemoveUntil( + String newRouteName, + RoutePredicate predicate, { + Object? arguments, + }) { + return _navigator.restorablePushNamedAndRemoveUntil( + newRouteName, + predicate, + arguments: arguments, + ); + } + + void pop([T? result]) { + _navigator.pop(result); + } + + void popUntil(RoutePredicate predicate) { + _navigator.popUntil(predicate); + } + + bool canPop() { + return _navigator.canPop(); + } + + Future maybePop([T? result]) { + return _navigator.maybePop(result); + } */ +} diff --git a/lib/src/v4/debug/debug_fill_properties/cupertino_debugger_wrapper.dart b/lib/src/v4/debug/debug_fill_properties/cupertino_debugger_wrapper.dart new file mode 100644 index 0000000..13749a7 --- /dev/null +++ b/lib/src/v4/debug/debug_fill_properties/cupertino_debugger_wrapper.dart @@ -0,0 +1,25 @@ +import 'package:flutter/foundation.dart'; + +import '../../../../flutter_getit.dart'; + +class CupertinoDebuggerWrapper extends StatelessWidget { + final FlutterGetItRouteBase route; + final Widget child; + + const CupertinoDebuggerWrapper({ + required this.route, + required this.child, + super.key, + }); + + @override + Widget build(BuildContext context) { + return child; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(DiagnosticsProperty('Route', route)); + } +} diff --git a/lib/src/v4/debug/debug_fill_properties/material_debugger_wrapper.dart b/lib/src/v4/debug/debug_fill_properties/material_debugger_wrapper.dart new file mode 100644 index 0000000..39e5fcf --- /dev/null +++ b/lib/src/v4/debug/debug_fill_properties/material_debugger_wrapper.dart @@ -0,0 +1,26 @@ +import 'package:flutter/foundation.dart'; +import 'package:get_it/get_it.dart'; + +import '../../../../flutter_getit.dart'; + +class FlutterGetItDebuggerWrapper extends StatelessWidget { + final Widget child; + + const FlutterGetItDebuggerWrapper({ + required this.child, + super.key, + }); + + @override + Widget build(BuildContext context) { + return child; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + final fGetItWallet = GetIt.I.get(); + final route = fGetItWallet.routeStack.last; + super.debugFillProperties(properties); + properties.add(DiagnosticsProperty('Route', route)); + } +} diff --git a/lib/src/v4/delegate/flutter_get_it_delegate.dart b/lib/src/v4/delegate/flutter_get_it_delegate.dart new file mode 100644 index 0000000..7e18328 --- /dev/null +++ b/lib/src/v4/delegate/flutter_get_it_delegate.dart @@ -0,0 +1,192 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get_it/get_it.dart'; + +import '../../../flutter_getit.dart'; +import '../router/seed/flutter_get_it_custom_route.dart'; +import '../router/seed/flutter_get_it_material_route.dart'; +import '../widgets/flutter_get_it_middleware_loader.dart'; + +class FGetItRouterDelegate extends RouterDelegate + with ChangeNotifier, PopNavigatorRouterDelegateMixin { + FGetItRouterDelegate({ + GlobalKey? navigatorKey, + List routes = const [], + ApplicationBindings? applicationBindings, + List middlewares = const [], + String initialRoute = '/', + this.loaderBuilder, + }) : _navigatorKey = navigatorKey ?? GlobalKey() { + final logger = FGetItLogger( + FGetItLoggerConfig(), + middlewares.map((e) => e.runtimeType).toList(), + ); + final wallet = FlutterGetItWallet( + routes: routes, + applicationMiddlewares: middlewares, + applicationBindings: applicationBindings, + navigatorKey: _navigatorKey, + initialRoute: initialRoute, + ); + GetIt.I.registerSingleton(logger); + GetIt.I.registerSingleton(wallet); + _routeObserver = FlutterGetItRouteObserver(); + } + + late final FlutterGetItRouteObserver _routeObserver; + late final GlobalKey _navigatorKey; + final Widget Function(Stream stream)? loaderBuilder; + + @override + Future setNewRoutePath(String configuration) async { + notifyListeners(); + } + + @override + Widget build(BuildContext context) { + return Navigator( + key: _navigatorKey, + observers: [_routeObserver], + onGenerateRoute: (settings) { + final route = + GetIt.I.get().getRoute(settings.name ?? ''); + if (route == null) { + return null; + } + + final routeSolved = _solveNavigation( + route as FlutterGetItRoute, + settings.arguments, + ); + SystemNavigator.routeInformationUpdated( + uri: Uri.parse(routeSolved.fullPath), + state: settings.arguments, + ); + + return switch (routeSolved.isCustom) { + true => FlutterGetItCustomRoute( + route: routeSolved, + settings: settings, + ), + false => FlutterGetItMaterialRoute( + route: routeSolved, + settings: settings, + ), + }; + }, + onUnknownRoute: (settings) { + const tip = 'Check your route name, e be sure that it\'s exists.'; + final description = + 'Are you trying to navigate to "${settings.name ?? 'NO NAME PROVIDED'}"? And we can\'t find it.'; + return FlutterGetItMaterialRoute( + route: FlutterGetItRoute( + path: settings.name ?? '', + buildPage: (context, animation, secondaryAnimation, params) => + FlutterGetItErrorPage( + exception: null, + stackTrace: null, + tip: tip, + description: description, + ), + ), + settings: settings, + ); + }, + ); + } + + FlutterGetItRoute _solveNavigation( + FlutterGetItRoute route, dynamic arguments) { + final fGetItWallet = GetIt.I.get(); + + final isMoreThenOneRouteLikeMe = + fGetItWallet.isMoreThenOneRouteLikeMe(route.fullPath); + final lastRouteWasLoader = fGetItWallet.lastRouteWasLoader; + + if (lastRouteWasLoader) { + fGetItWallet.addRouteStack(route); + return route; + } + + if (isMoreThenOneRouteLikeMe) { + fGetItWallet.initBinds(route: route); + return route; + } + + final appMiddlewares = fGetItWallet.applicationMiddlewares; + final parentsMiddlewares = + fGetItWallet.getParentMiddlewares(route.fullPath); + final routeMiddlewares = fGetItWallet.getRouteMiddlewares(route.fullPath); + + final anyMiddlewareIsAsync = appMiddlewares + .any((middleware) => middleware is FlutterGetItAsyncMiddleware) || + parentsMiddlewares + .any((middleware) => middleware is FlutterGetItAsyncMiddleware) || + routeMiddlewares + .any((middleware) => middleware is FlutterGetItAsyncMiddleware); + + final anyBindAsyncDontInitialized = + fGetItWallet.anyBindAsyncDontInitialized(route); + FGetItLogger.logInitDivider(); + switch ((anyMiddlewareIsAsync, anyBindAsyncDontInitialized)) { + case (true, true): + FGetItLogger.logInformThatTheNewRouteIsAsync( + route.fullPath, + 'AsyncMiddlewares && AsyncBinds', + ); + return _getLoaderPageRoute(route, arguments); + case (false, true): + FGetItLogger.logInformThatTheNewRouteIsAsync( + route.fullPath, + 'AsyncBinds', + ); + return _getLoaderPageRoute(route, arguments); + case (true, false): + FGetItLogger.logInformThatTheNewRouteIsAsync( + route.fullPath, + 'AsyncMiddlewares', + ); + return _getLoaderPageRoute(route, arguments); + case (false, false): + FGetItLogger.logInformThatTheNewRouteIsSync(route.fullPath); + fGetItWallet.addRouteStack(route); + return route; + } + } + + FlutterGetItRoute _getLoaderPageRoute( + FlutterGetItRoute routeToSolve, + dynamic arguments, + ) { + final fGetItWallet = GetIt.I.get(); + final loaderPage = FlutterGetItRoute( + path: routeToSolve.path, + barrierColor: Colors.black, + buildPage: (context, animation, secondaryAnimation, params) => + FlutterGetItMiddlewareLoader( + routeToSolve: routeToSolve, + loaderBuilder: loaderBuilder, + ), + buildTransition: ( + context, + animation, + secondaryAnimation, + child, + ) { + return FadeTransition( + opacity: animation, + child: child, + ); + }, + ); + loaderPage.fullPath = routeToSolve.fullPath; + loaderPage.isLoader = true; + fGetItWallet.addRouteStack(loaderPage); + return loaderPage; + } + + @override + GlobalKey? get navigatorKey => _navigatorKey; +} diff --git a/lib/src/v4/extensions/flutter_get_it_navigator.dart b/lib/src/v4/extensions/flutter_get_it_navigator.dart new file mode 100644 index 0000000..6bb3844 --- /dev/null +++ b/lib/src/v4/extensions/flutter_get_it_navigator.dart @@ -0,0 +1,12 @@ +import '../../../flutter_getit.dart'; +import '../router/params/f_get_it_router_params.dart'; + +extension FGetItExtensionRoute on Route { + FGetItRouterParams get routeParams { + return FGetItRouterParams( + arguments: null, + pathParams: {'id': 29}, + queryParams: {'query': 'value'}, + ); + } +} diff --git a/lib/src/v4/middleware/flutter_get_it_middleware.dart b/lib/src/v4/middleware/flutter_get_it_middleware.dart new file mode 100644 index 0000000..28518e4 --- /dev/null +++ b/lib/src/v4/middleware/flutter_get_it_middleware.dart @@ -0,0 +1,60 @@ +import 'dart:async'; + +import 'package:flutter/widgets.dart'; + +export 'package:flutter/widgets.dart'; + +enum MiddlewareAction { skip, execute } + +enum MiddlewareStatus { failure, success } + +class FlutterGetItMiddlewareArguments { + final dynamic arguments; + + FlutterGetItMiddlewareArguments(this.arguments); +} + +abstract class FlutterGetItMiddleware { + MiddlewareAction when(String path); + FutureOr execute(dynamic arguments); + void onFailure(BuildContext context, dynamic arguments); +} + +abstract class FlutterGetItSyncMiddleware extends FlutterGetItMiddleware { + @override + MiddlewareAction when(String path) { + return MiddlewareAction.execute; + } + + @override + MiddlewareStatus execute(dynamic arguments) { + return MiddlewareStatus.success; + } + + @override + void onFailure(BuildContext context, dynamic arguments) { + return; + } +} + +abstract class FlutterGetItAsyncMiddleware extends FlutterGetItMiddleware { + @override + MiddlewareAction when(String path) { + return MiddlewareAction.execute; + } + + @override + FutureOr execute(dynamic arguments) { + return Future.delayed( + const Duration(seconds: 4), + () => MiddlewareStatus.success, + ); + } + + @override + void onFailure(BuildContext context, dynamic arguments) { + return; + } +} + +class FlutterGetItInitializationMiddleware {} diff --git a/lib/src/v4/observer/flutter_get_it_route_observer.dart b/lib/src/v4/observer/flutter_get_it_route_observer.dart new file mode 100644 index 0000000..02a0727 --- /dev/null +++ b/lib/src/v4/observer/flutter_get_it_route_observer.dart @@ -0,0 +1,14 @@ +import 'package:flutter/material.dart'; + +class FlutterGetItRouteObserver extends NavigatorObserver { + @override + void didPush(Route route, Route? previousRoute) async {} + + @override + void didPop(Route route, Route? previousRoute) {} + + @override + void didReplace({Route? newRoute, Route? oldRoute}) { + if (newRoute != null) {} + } +} diff --git a/lib/src/v4/router/flutter_get_it_router.dart b/lib/src/v4/router/flutter_get_it_router.dart new file mode 100644 index 0000000..d5ad1f6 --- /dev/null +++ b/lib/src/v4/router/flutter_get_it_router.dart @@ -0,0 +1,184 @@ +import 'package:uuid/uuid.dart'; + +import '../../../flutter_getit.dart'; + +const _uuidConfig = Uuid(); + +abstract class FlutterGetItRouteBase { + FlutterGetItRouteBase(); + abstract String uuid; + abstract List binds; + abstract String path; + abstract String fullPath; + abstract List parentUUIDs; + abstract List middlewares; + abstract List> pages; + abstract bool isLoader; + + Map? extractParameters(String route, String path) { + final regexPattern = RegExp('^' + + route.replaceAllMapped(RegExp(r':(\w+)'), (match) => r'([^/]+)') + + r'$'); + final match = regexPattern.firstMatch(path); + if (match == null) return null; + + final paramNames = + RegExp(r':(\w+)').allMatches(route).map((m) => m.group(1)!).toList(); + + final paramValues = match + .groups( + List.generate(match.groupCount, (i) => i + 1), + ) + .map((e) => e.toString()) + .toList(); + + return Map.fromIterables(paramNames, paramValues); + } +} + +class FlutterGetItModuleRoute extends FlutterGetItRouteBase { + final bool safeRedirect; + final String? redirect; + + FlutterGetItModuleRoute({ + required this.path, + this.binds = const [], + this.pages = const [], + this.middlewares = const [], + this.redirect, + this.safeRedirect = true, + }) : parentUUIDs = [], + uuid = _uuidConfig.v4(), + fullPath = '', + isLoader = false; + + @override + List> pages; + + @override + List> binds; + + @override + String path; + + @override + List parentUUIDs; + + @override + String uuid; + + @override + String fullPath; + + @override + List middlewares; + + @override + bool isLoader; +} + +class FlutterGetItRoute extends FlutterGetItRouteBase { + final bool? requestFocus; + final bool maintainState; + final bool fullscreenDialog; + final bool allowSnapshotting; + final bool barrierDismissible; + final bool isCustom; + final Duration transitionDuration; + final Duration reverseTransitionDuration; + final bool opaque; + final Color? barrierColor; + final String? barrierLabel; + + final Widget Function( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + FGetItRouterParams params, + )? buildPage; + + final Widget Function( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + Widget child, + )? buildTransition; + + FlutterGetItRoute.custom({ + required this.path, + this.binds = const [], + this.pages = const [], + this.middlewares = const [], + this.buildPage, + this.buildTransition, + this.requestFocus, + this.maintainState = true, + this.fullscreenDialog = false, + this.allowSnapshotting = false, + this.barrierDismissible = false, + this.opaque = true, + this.barrierColor, + this.barrierLabel, + this.transitionDuration = const Duration(milliseconds: 300), + this.reverseTransitionDuration = const Duration(milliseconds: 300), + }) : parentUUIDs = [], + uuid = _uuidConfig.v4(), + fullPath = '', + isCustom = true, + isLoader = false, + assert( + buildPage != null || buildTransition != null, + 'Either buildPage or buildTransitions must be defined', + ); + + FlutterGetItRoute({ + required this.path, + this.binds = const [], + this.pages = const [], + this.middlewares = const [], + this.buildPage, + this.buildTransition, + this.requestFocus, + this.maintainState = true, + this.fullscreenDialog = false, + this.allowSnapshotting = false, + this.barrierDismissible = false, + this.opaque = true, + this.barrierColor, + this.barrierLabel, + this.transitionDuration = const Duration(milliseconds: 300), + this.reverseTransitionDuration = const Duration(milliseconds: 300), + }) : parentUUIDs = [], + uuid = _uuidConfig.v4(), + fullPath = '', + isCustom = false, + isLoader = false, + assert( + buildPage != null || buildTransition != null, + 'Either buildPage or buildTransitions must be defined', + ); + + @override + List> binds; + + @override + List parentUUIDs; + + @override + List> pages; + + @override + String uuid; + + @override + String fullPath; + + @override + List middlewares; + + @override + String path; + + @override + bool isLoader; +} diff --git a/lib/src/v4/router/params/f_get_it_router_params.dart b/lib/src/v4/router/params/f_get_it_router_params.dart new file mode 100644 index 0000000..12b4b5a --- /dev/null +++ b/lib/src/v4/router/params/f_get_it_router_params.dart @@ -0,0 +1,11 @@ +class FGetItRouterParams { + final dynamic arguments; + final Map pathParams; + final Map queryParams; + + FGetItRouterParams({ + required this.arguments, + required this.pathParams, + required this.queryParams, + }); +} diff --git a/lib/src/v4/router/seed/flutter_get_it_cupertino_route.dart b/lib/src/v4/router/seed/flutter_get_it_cupertino_route.dart new file mode 100644 index 0000000..2bc8ff2 --- /dev/null +++ b/lib/src/v4/router/seed/flutter_get_it_cupertino_route.dart @@ -0,0 +1,69 @@ +import 'package:flutter/cupertino.dart'; +import 'package:get_it/get_it.dart'; + +import '../../../../flutter_getit.dart'; +import '../../../routers/flutter_get_it_route_params_extractor.dart'; +import '../../debug/debug_fill_properties/cupertino_debugger_wrapper.dart'; + +class FlutterGetItCupertinoRoute extends CupertinoPageRoute { + final FlutterGetItRoute route; + FlutterGetItCupertinoRoute({ + super.settings, + required this.route, + }) : super( + title: route.fullPath, + builder: (context) => const SizedBox.shrink(), + requestFocus: route.requestFocus, + maintainState: route.maintainState, + fullscreenDialog: route.fullscreenDialog, + allowSnapshotting: route.allowSnapshotting, + barrierDismissible: route.barrierDismissible, + ); + + @override + Widget buildPage( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + ) { + final params = FlutterGetItRouteParamsExtractor( + route.fullPath, + route.fullPath, + ).extract(); + return CupertinoDebuggerWrapper( + route: route, + child: route.buildPage?.call( + context, + animation, + secondaryAnimation, + ModalRoute.of(context)!.routeParams, + ) ?? + const SizedBox.shrink(), + ); + } + + @override + Widget buildTransitions( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + Widget child, + ) { + return route.buildTransition?.call( + context, + animation, + secondaryAnimation, + child, + ) ?? + child; + } + + @override + void dispose() { + if (!route.isLoader) { + final fGetItWallet = GetIt.I.get(); + fGetItWallet.solveDisposeRoute(route); + } + super.dispose(); + } +} diff --git a/lib/src/v4/router/seed/flutter_get_it_custom_route.dart b/lib/src/v4/router/seed/flutter_get_it_custom_route.dart new file mode 100644 index 0000000..f58f5d6 --- /dev/null +++ b/lib/src/v4/router/seed/flutter_get_it_custom_route.dart @@ -0,0 +1,79 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; + +import '../../../../flutter_getit.dart'; +import '../../../routers/flutter_get_it_route_params_extractor.dart'; +import '../../debug/debug_fill_properties/cupertino_debugger_wrapper.dart'; + +class FlutterGetItCustomRoute extends PageRouteBuilder { + final FlutterGetItRoute route; + FlutterGetItCustomRoute({ + required this.route, + super.settings, + }) : super( + pageBuilder: (context, animation, secondaryAnimation) { + final params = FlutterGetItRouteParamsExtractor( + route.fullPath, + route.fullPath, + ).extract(); + + return route.buildPage?.call( + context, + animation, + secondaryAnimation, + ModalRoute.of(context)!.routeParams, + ) ?? + const SizedBox.shrink(); + }, + transitionsBuilder: (context, animation, secondaryAnimation, child) => + route.buildTransition?.call( + context, + animation, + secondaryAnimation, + child, + ) ?? + child, + requestFocus: route.requestFocus, + maintainState: route.maintainState, + fullscreenDialog: route.fullscreenDialog, + allowSnapshotting: route.allowSnapshotting, + barrierDismissible: route.barrierDismissible, + opaque: route.opaque, + barrierColor: route.barrierColor, + barrierLabel: route.barrierLabel, + transitionDuration: route.transitionDuration, + reverseTransitionDuration: route.reverseTransitionDuration, + ); + bool _isMaterialApp(BuildContext context) => + context.findAncestorWidgetOfExactType() != null; + + @override + Widget buildPage( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + ) { + if (kDebugMode) { + if (_isMaterialApp(context)) { + return FlutterGetItDebuggerWrapper( + child: super.buildPage(context, animation, secondaryAnimation), + ); + } + return CupertinoDebuggerWrapper( + route: route, + child: super.buildPage(context, animation, secondaryAnimation), + ); + } + return super.buildPage(context, animation, secondaryAnimation); + } + + @override + void dispose() { + if (!route.isLoader) { + final fGetItWallet = GetIt.I.get(); + fGetItWallet.solveDisposeRoute(route); + } + super.dispose(); + } +} diff --git a/lib/src/v4/router/seed/flutter_get_it_material_route.dart b/lib/src/v4/router/seed/flutter_get_it_material_route.dart new file mode 100644 index 0000000..2538fe7 --- /dev/null +++ b/lib/src/v4/router/seed/flutter_get_it_material_route.dart @@ -0,0 +1,76 @@ +import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; + +import '../../../../flutter_getit.dart'; +import '../../../routers/flutter_get_it_route_params_extractor.dart'; + +class FlutterGetItMaterialRoute extends MaterialPageRoute { + final FlutterGetItRoute route; + + FlutterGetItMaterialRoute({ + required this.route, + super.settings, + }) : super( + builder: (context) => const SizedBox.shrink(), + requestFocus: route.requestFocus, + maintainState: route.maintainState, + fullscreenDialog: route.fullscreenDialog, + allowSnapshotting: route.allowSnapshotting, + barrierDismissible: route.barrierDismissible, + ); + + @override + Widget buildPage( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + ) { + /* if (kDebugMode) { + return MaterialDebuggerWrapper( + route: route, + child: route.buildPage?.call( + context, + animation, + secondaryAnimation, + ) ?? + const SizedBox.shrink(), + ); + } */ + final params = FlutterGetItRouteParamsExtractor( + route.fullPath, + route.fullPath, + ).extract(); + return route.buildPage?.call( + context, + animation, + secondaryAnimation, + ModalRoute.of(context)!.routeParams, + ) ?? + const SizedBox.shrink(); + } + + @override + void dispose() { + if (!route.isLoader) { + final fGetItWallet = GetIt.I.get(); + fGetItWallet.solveDisposeRoute(route); + } + super.dispose(); + } + + @override + Widget buildTransitions( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + Widget child, + ) { + return route.buildTransition?.call( + context, + animation, + secondaryAnimation, + child, + ) ?? + child; + } +} diff --git a/lib/src/v4/wallet/flutter_get_it_wallet.dart b/lib/src/v4/wallet/flutter_get_it_wallet.dart new file mode 100644 index 0000000..9c6a211 --- /dev/null +++ b/lib/src/v4/wallet/flutter_get_it_wallet.dart @@ -0,0 +1,255 @@ +import 'dart:async'; + +import 'package:get_it/get_it.dart'; + +import '../../../flutter_getit.dart'; +import '../../routers/flutter_get_it_route_params_extractor.dart'; + +typedef RouteAndParentBinds = ({ + FlutterGetItRouteBase? route, + List parentBinds, +}); + +class FlutterGetItWallet { + late final Map _wallet; + late final List _applicationMiddlewares; + late final GlobalKey _navigatorKey; + final List _routeStack = []; + late final String _initialRoute; + late final List _applicationBinds; + + FlutterGetItWallet({ + ApplicationBindings? applicationBindings, + required List routes, + required List applicationMiddlewares, + required GlobalKey navigatorKey, + required String initialRoute, + }) { + _createRouteMap(routes); + _applicationMiddlewares = applicationMiddlewares; + _navigatorKey = navigatorKey; + _initialRoute = initialRoute; + _applicationBinds = applicationBindings?.bindings() ?? []; + } + + List get routeStack => _routeStack; + + String get initialRoute => _initialRoute; + + void addRouteStack(FlutterGetItRouteBase route) { + _routeStack.add(route); + } + + bool isMoreThenOneRouteLikeMe(String fullPath) { + return _routeStack + .where((element) => element.fullPath == fullPath && !element.isLoader) + .isNotEmpty; + } + + List get applicationMiddlewares => + _applicationMiddlewares; + + Map get wallet => _wallet; + + GlobalKey get navigatorKey => _navigatorKey; + + bool get lastRouteWasLoader => + _routeStack.isNotEmpty && _routeStack.last.isLoader; + + FlutterGetItRouteBase? getRoute(String path) { + final params = FlutterGetItRouteParamsExtractor( + path, + path, + ); + + final route = _wallet[path] ?? matchRoute(path); + + if (route is FlutterGetItModuleRoute) { + if (route.fullPath == route.redirect) { + //Avoid infinite loop + return route; + } + return getRoute(route.redirect ?? ''); + } + + return route; + } + + FlutterGetItRouteBase? matchRoute(String inputRoute) { + for (var definedRoute in _wallet.keys) { + final inputSegments = inputRoute.split('/'); + final definedSegments = definedRoute.split('/'); + + if (inputSegments.length != definedSegments.length) { + continue; + } + + final parameters = {}; + var isMatch = true; + + for (var i = 0; i < inputSegments.length; i++) { + final inputSegment = inputSegments[i]; + final definedSegment = definedSegments[i]; + + if (definedSegment.startsWith(':')) { + // É um parâmetro dinâmico + final paramName = definedSegment.substring(1); + parameters[paramName] = inputSegment; + } else if (inputSegment != definedSegment) { + // Segmentos não correspondem + isMatch = false; + break; + } + } + + if (isMatch) { + return _wallet[definedRoute]!..fullPath = inputRoute; + } + } + + return null; + } + + List getParentBinds(String path) { + final route = _wallet[path]; + final parentBinds = []; + + _wallet.forEach((key, routeInternal) { + if ((route?.parentUUIDs.contains(routeInternal.uuid) ?? false) && + routeInternal.uuid != route?.uuid) { + parentBinds.addAll(routeInternal.binds); + } + }); + + return parentBinds; + } + + List getParentMiddlewares(String path) { + final route = _wallet[path]; + final parentMiddlewares = []; + _wallet.forEach((key, routeInternal) { + if ((route?.parentUUIDs.contains(routeInternal.uuid) ?? false) && + routeInternal.uuid != route?.uuid) { + parentMiddlewares.addAll(routeInternal.middlewares); + } + }); + return parentMiddlewares; + } + + void _createRouteMap(List routes) { + final routeMap = {}; + final currentModuleUuids = []; // Stack to store parent module UUIDs + + for (var routeBase in routes) { + if (routeBase is FlutterGetItModuleRoute) { + currentModuleUuids.add(routeBase.uuid); // Add current module's uuid + } + + routeBase.parentUUIDs = List.unmodifiable(currentModuleUuids); + routeBase.fullPath = routeBase.path; + + if (routeBase is FlutterGetItRoute) { + routeMap[routeBase.path] = routeBase; + } else if (routeBase is FlutterGetItModuleRoute) { + routeMap[routeBase.path] = routeBase; + for (var page in routeBase.pages) { + page.parentUUIDs = List.unmodifiable(currentModuleUuids); + page.fullPath = '${routeBase.path}${page.path}'; + routeMap['${routeBase.path}${page.path}'] = page; + } + } + + if (routeBase is FlutterGetItModuleRoute) { + currentModuleUuids + .removeLast(); // Remove current module's uuid after processing its pages + } + } + + _wallet = routeMap; + } + + List getRouteMiddlewares(String routeName) { + final route = _wallet[routeName]; + return route?.middlewares ?? []; + } + + List getRouteBindings(String path) { + final route = _wallet[path]; + return route?.binds ?? []; + } + + bool anyBindAsyncDontInitialized(FlutterGetItRouteBase? route) { + final routeBinds = route?.binds ?? []; + final parentBinds = getParentBinds(route?.fullPath ?? ''); + + final allBinds = [...routeBinds, ...parentBinds]; + + return allBinds.any((bind) => + (bind.type == RegisterType.factoryAsync || + bind.type == RegisterType.singletonAsync || + bind.type == RegisterType.lazySingletonAsync) && + !bind.isInitialized); + } + + FutureOr initBinds({ + required FlutterGetItRouteBase route, + }) async { + final isTheInitialRoute = route.fullPath == _initialRoute; + + if (isTheInitialRoute) { + for (var bind in _applicationBinds) { + bind.register('APPLICATION_BINDINGS'); + } + FGetItLogger.logSolvingAsyncDependenciesFor('APPLICATION_BINDINGS'); + await GetIt.I.allReady().then((value) { + FGetItLogger.logSolvingAsyncDependenciesCompleted( + 'APPLICATION_BINDINGS', + ); + }); + return; + } + + FGetItLogger.logInitDivider(); + + //Init parent binds + final parentBinds = getParentBinds(route.fullPath); + + for (var bind in parentBinds) { + bind.register(route.fullPath); + } + + //Init route binds + for (var bind in route.binds) { + bind.register(route.fullPath); + } + FGetItLogger.logSolvingAsyncDependenciesFor(route.fullPath); + await GetIt.I.allReady().then((value) { + FGetItLogger.logSolvingAsyncDependenciesCompleted(route.fullPath); + }); + FGetItLogger.logEndDivider(); + + return; + } + + void removeLastRouteStack() { + _routeStack.removeLast(); + } + + void solveDisposeRoute(FlutterGetItRouteBase route) { + //Unregister parent binds + FGetItLogger.logInitDivider(); + FGetItLogger.logCallingDisposeRoute(route.fullPath); + FGetItLogger.logMidDivider(); + + for (var bind in getParentBinds(route.fullPath)) { + bind.unRegister(route.fullPath); + } + + //Unregister route binds + for (var bind in route.binds) { + bind.unRegister(route.fullPath); + } + + FGetItLogger.logEndDivider(); + } +} diff --git a/lib/src/v4/widgets/flutter_get_it_error_page.dart b/lib/src/v4/widgets/flutter_get_it_error_page.dart new file mode 100644 index 0000000..cde9fed --- /dev/null +++ b/lib/src/v4/widgets/flutter_get_it_error_page.dart @@ -0,0 +1,99 @@ +import 'package:flutter/material.dart'; + +class FlutterGetItErrorPage extends StatelessWidget { + final Exception? exception; + final StackTrace? stackTrace; + final String? tip; + final String? description; + + const FlutterGetItErrorPage({ + super.key, + this.exception, + this.stackTrace, + this.tip, + this.description, + }); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: const Text('FGetIt Error Information'), + ), + body: Center( + child: SizedBox( + width: 420, + child: ListView( + children: [ + const Center( + child: Text( + 'We detected an error! Be sure to check the following information.', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + ), + const Icon( + Icons.error, + color: Colors.red, + size: 100, + ), + Center( + child: Card( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + const Text( + 'Description', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 4), + Text( + description ?? '', + textAlign: TextAlign.center, + ), + ], + ), + ), + ), + ), + Center( + child: Card( + color: Colors.yellow.shade100, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + const Text( + 'Tip', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 4), + Text( + tip ?? '', + textAlign: TextAlign.center, + ), + ], + ), + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/src/v4/widgets/flutter_get_it_loader.dart b/lib/src/v4/widgets/flutter_get_it_loader.dart new file mode 100644 index 0000000..a6d995c --- /dev/null +++ b/lib/src/v4/widgets/flutter_get_it_loader.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; + +class FlutterGetItLoader extends StatelessWidget { + const FlutterGetItLoader({super.key}); + + @override + Widget build(BuildContext context) { + return const Center( + child: Card( + child: Padding( + padding: EdgeInsets.all(8.0), + child: CircularProgressIndicator.adaptive(), + ), + ), + ); + } +} diff --git a/lib/src/v4/widgets/flutter_get_it_middleware_loader.dart b/lib/src/v4/widgets/flutter_get_it_middleware_loader.dart new file mode 100644 index 0000000..ce287a8 --- /dev/null +++ b/lib/src/v4/widgets/flutter_get_it_middleware_loader.dart @@ -0,0 +1,169 @@ +import 'dart:async'; + +import 'package:get_it/get_it.dart'; + +import '../../../flutter_getit.dart'; +import 'flutter_get_it_loader.dart'; + +class FlutterGetItMiddlewareLoader extends StatefulWidget { + final FlutterGetItRouteBase routeToSolve; + final Widget Function(Stream)? loaderBuilder; + const FlutterGetItMiddlewareLoader({ + super.key, + required this.routeToSolve, + this.loaderBuilder, + }); + + @override + State createState() => + _FlutterGetItMiddlewareLoaderState(); +} + +class _FlutterGetItMiddlewareLoaderState + extends State { + final _streamLoader = StreamController(); + FlutterGetItRouteBase get routeToSolve => widget.routeToSolve; + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + _loadMiddleware(); + }); + } + + void _loadMiddleware() async { + final arguments = ModalRoute.of(context)?.settings.arguments; + final fGetItWallet = GetIt.I.get(); + final appMiddlewares = fGetItWallet.applicationMiddlewares; + + if (routeToSolve.fullPath == fGetItWallet.initialRoute) { + FGetItLogger.logInitDivider(); + FGetItLogger.logInitInitialRoute(); + _streamLoader.add(FlutterGetItInitializationMiddleware); + await fGetItWallet.initBinds(route: routeToSolve); + FGetItLogger.logEndDivider(); + fGetItWallet.navigatorKey.currentState?.popAndPushNamed( + routeToSolve.fullPath, + arguments: arguments, + ); + + return; + } + + final parentsMiddlewares = + fGetItWallet.getParentMiddlewares(routeToSolve.fullPath); + final routeMiddlewares = routeToSolve.middlewares; + + if (appMiddlewares.isNotEmpty) { + FGetItLogger.logInitMiddleware('Application Middlewares'); + + for (var middleware in appMiddlewares) { + if (middleware.when(routeToSolve.fullPath) == + MiddlewareAction.execute) { + FGetItLogger.logRunningMiddleware(middleware.runtimeType.toString()); + _streamLoader.add(middleware.runtimeType); + final result = await middleware.execute(arguments); + if (result != MiddlewareStatus.success) { + FGetItLogger.logMiddlewareFail(middleware.runtimeType.toString()); + FGetItLogger.logEndDivider(); + fGetItWallet.removeLastRouteStack(); + fGetItWallet.navigatorKey.currentState?.pop(); + //Maybe ?? Duration.zero + if (fGetItWallet.navigatorKey.currentState!.mounted) { + middleware.onFailure( + fGetItWallet.navigatorKey.currentState!.context, + arguments, + ); + } + return; + } + FGetItLogger.logMiddlewareSuccess(middleware.runtimeType.toString()); + } else { + FGetItLogger.logMiddlewareSkipped(middleware.runtimeType.toString()); + } + } + FGetItLogger.logEndDivider(); + } + + if (parentsMiddlewares.isNotEmpty) { + FGetItLogger.logInitMiddleware('Parent Middlewares'); + for (var middleware in parentsMiddlewares) { + FGetItLogger.logRunningMiddleware(middleware.runtimeType.toString()); + if (middleware.when(routeToSolve.fullPath) == + MiddlewareAction.execute) { + _streamLoader.add(middleware.runtimeType); + final result = await middleware.execute(arguments); + if (result != MiddlewareStatus.success) { + FGetItLogger.logMiddlewareFail(middleware.runtimeType.toString()); + FGetItLogger.logEndDivider(); + fGetItWallet.removeLastRouteStack(); + fGetItWallet.navigatorKey.currentState?.pop(); + //Maybe ?? Duration.zero + if (fGetItWallet.navigatorKey.currentState!.mounted) { + middleware.onFailure( + fGetItWallet.navigatorKey.currentState!.context, + arguments, + ); + } + return; + } + FGetItLogger.logMiddlewareSuccess(middleware.runtimeType.toString()); + } else { + FGetItLogger.logMiddlewareSkipped(middleware.runtimeType.toString()); + } + } + FGetItLogger.logEndDivider(); + } + + if (routeMiddlewares.isNotEmpty) { + FGetItLogger.logInitMiddleware('Route Middlewares'); + for (var middleware in routeMiddlewares) { + FGetItLogger.logRunningMiddleware(middleware.runtimeType.toString()); + if (middleware.when(routeToSolve.fullPath) == + MiddlewareAction.execute) { + _streamLoader.add(middleware.runtimeType); + final result = await middleware.execute(arguments); + if (result != MiddlewareStatus.success) { + FGetItLogger.logMiddlewareFail(middleware.runtimeType.toString()); + FGetItLogger.logEndDivider(); + fGetItWallet.removeLastRouteStack(); + fGetItWallet.navigatorKey.currentState?.pop(); + //Maybe ?? Duration.zero + if (fGetItWallet.navigatorKey.currentState!.mounted) { + middleware.onFailure( + fGetItWallet.navigatorKey.currentState!.context, + arguments, + ); + } + return; + } + FGetItLogger.logMiddlewareSuccess(middleware.runtimeType.toString()); + } else { + FGetItLogger.logMiddlewareSkipped(middleware.runtimeType.toString()); + } + } + FGetItLogger.logEndDivider(); + } + + await fGetItWallet.initBinds( + route: routeToSolve, + ); + fGetItWallet.navigatorKey.currentState?.popAndPushNamed( + routeToSolve.fullPath, + arguments: arguments, + ); + return; + } + + @override + void dispose() { + _streamLoader.close(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return widget.loaderBuilder?.call(_streamLoader.stream) ?? + const FlutterGetItLoader(); + } +} diff --git a/lib/src/widget/flutter_getit_route_outlet.dart b/lib/src/widget/flutter_getit_route_outlet.dart index bc50e4a..8163cef 100644 --- a/lib/src/widget/flutter_getit_route_outlet.dart +++ b/lib/src/widget/flutter_getit_route_outlet.dart @@ -1,4 +1,4 @@ -import 'package:flutter/material.dart'; +/* import 'package:flutter/material.dart'; import '../../flutter_getit.dart'; @@ -30,7 +30,7 @@ class FlutterGetItRouteOutlet extends StatelessWidget { key: navKey, initialRoute: initialRoute, onGenerateRoute: (settings) { - final pages = context.get>( + final pages = InjectorContext(context).get>( tag: 'RoutesMap_${contextType.key}', ); final widget = pages[settings.name]; @@ -68,3 +68,4 @@ class PageNotFound extends StatelessWidget { ); } } + */ diff --git a/lib/src/widget/flutter_getit_view.dart b/lib/src/widget/flutter_getit_view.dart index ae07dc6..1fc47ca 100644 --- a/lib/src/widget/flutter_getit_view.dart +++ b/lib/src/widget/flutter_getit_view.dart @@ -1,4 +1,4 @@ -import 'package:flutter/material.dart'; +/* import 'package:flutter/material.dart'; import '../../flutter_getit.dart'; @@ -11,3 +11,4 @@ class FlutterGetItView extends StatelessWidget { return const Placeholder(); } } + */ diff --git a/lib/src/widget/flutter_getit_widget.dart b/lib/src/widget/flutter_getit_widget.dart index 8960019..a9b4b3c 100644 --- a/lib/src/widget/flutter_getit_widget.dart +++ b/lib/src/widget/flutter_getit_widget.dart @@ -1,4 +1,4 @@ -import 'package:flutter/material.dart'; +/* import 'package:flutter/material.dart'; import '../../flutter_getit.dart'; @@ -86,3 +86,4 @@ class _FlutterGetItWidgetState extends State { super.dispose(); } } + */ diff --git a/pubspec.yaml b/pubspec.yaml index e86b62f..64b71e9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -21,7 +21,6 @@ tags: topics: - dependency-injection - - di - injection - router - routing @@ -33,7 +32,8 @@ environment: dependencies: flutter: sdk: flutter - get_it: ^7.7.0 + get_it: ^8.0.3 + uuid: ^4.5.1 dev_dependencies: flutter_lints: ^4.0.0