diff --git a/README.md b/README.md index 7430063..e0e74bf 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,12 @@ Tools • Dart 2.7.0 iconfont_builder --from ./assets/fonts --to ./lib/common/utils/iconfont.dart ``` +## 生成路由 + +``` +flutter packages pub run build_runner build +``` + ## 代码仓 https://github.com/ducafecat/flutter_learn_news diff --git a/lib/common/router/auth_grard.dart b/lib/common/router/auth_grard.dart new file mode 100644 index 0000000..9b63892 --- /dev/null +++ b/lib/common/router/auth_grard.dart @@ -0,0 +1,16 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter_ducafecat_news/common/router/router.gr.dart'; +import 'package:flutter_ducafecat_news/common/utils/utils.dart'; + +class AuthGuard extends RouteGuard { + @override + Future canNavigate(ExtendedNavigatorState navigator, String routeName, + Object arguments) async { + var isAuth = await isAuthenticated(); + if (isAuth == false) { + ExtendedNavigator.rootNavigator.pushNamed(Routes.signInPageRoute); + } + + return isAuth; + } +} diff --git a/lib/common/router/router.dart b/lib/common/router/router.dart new file mode 100644 index 0000000..51922fd --- /dev/null +++ b/lib/common/router/router.dart @@ -0,0 +1,34 @@ +import 'package:auto_route/auto_route_annotations.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_ducafecat_news/common/router/auth_grard.dart'; +import 'package:flutter_ducafecat_news/pages/application/application.dart'; +import 'package:flutter_ducafecat_news/pages/details/details.dart'; +import 'package:flutter_ducafecat_news/pages/index/index.dart'; +import 'package:flutter_ducafecat_news/pages/sign_in/sign_in.dart'; +import 'package:flutter_ducafecat_news/pages/sign_up/sign_up.dart'; +import 'package:flutter_ducafecat_news/pages/welcome/welcome.dart'; + +Widget zoomInTransition(BuildContext context, Animation animation, + Animation secondaryAnimation, Widget child) { + // you get an animation object and a widget + // make your own transition + return ScaleTransition(scale: animation, child: child); +} + +@MaterialAutoRouter() +class $AppRouter { + @initial + IndexPage indexPageRoute; + + WelcomePage welcomePageRoute; + + SignInPage signInPageRoute; + + SignUpPage signUpPageRoute; + + @GuardedBy([AuthGuard]) + ApplicationPage applicationPageRoute; + + @GuardedBy([AuthGuard]) + DetailsPage detailsPageRoute; +} diff --git a/lib/common/router/router.gr.dart b/lib/common/router/router.gr.dart new file mode 100644 index 0000000..c214770 --- /dev/null +++ b/lib/common/router/router.gr.dart @@ -0,0 +1,144 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ************************************************************************** +// AutoRouteGenerator +// ************************************************************************** + +import 'package:flutter/material.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:flutter_ducafecat_news/pages/index/index.dart'; +import 'package:flutter_ducafecat_news/pages/welcome/welcome.dart'; +import 'package:flutter_ducafecat_news/pages/sign_in/sign_in.dart'; +import 'package:flutter_ducafecat_news/pages/sign_up/sign_up.dart'; +import 'package:flutter_ducafecat_news/pages/application/application.dart'; +import 'package:flutter_ducafecat_news/common/router/auth_grard.dart'; +import 'package:flutter_ducafecat_news/pages/details/details.dart'; + +abstract class Routes { + static const indexPageRoute = '/'; + static const welcomePageRoute = '/welcome-page-route'; + static const signInPageRoute = '/sign-in-page-route'; + static const signUpPageRoute = '/sign-up-page-route'; + static const applicationPageRoute = '/application-page-route'; + static const detailsPageRoute = '/details-page-route'; +} + +class AppRouter extends RouterBase { + @override + Map> get guardedRoutes => { + Routes.applicationPageRoute: [AuthGuard], + Routes.detailsPageRoute: [AuthGuard], + }; + + //This will probably be removed in future versions + //you should call ExtendedNavigator.ofRouter() directly + static ExtendedNavigatorState get navigator => + ExtendedNavigator.ofRouter(); + + @override + Route onGenerateRoute(RouteSettings settings) { + final args = settings.arguments; + switch (settings.name) { + case Routes.indexPageRoute: + if (hasInvalidArgs(args)) { + return misTypedArgsRoute(args); + } + final typedArgs = args as IndexPageArguments ?? IndexPageArguments(); + return MaterialPageRoute( + builder: (_) => IndexPage(key: typedArgs.key), + settings: settings, + ); + case Routes.welcomePageRoute: + if (hasInvalidArgs(args)) { + return misTypedArgsRoute(args); + } + final typedArgs = + args as WelcomePageArguments ?? WelcomePageArguments(); + return MaterialPageRoute( + builder: (_) => WelcomePage(key: typedArgs.key), + settings: settings, + ); + case Routes.signInPageRoute: + if (hasInvalidArgs(args)) { + return misTypedArgsRoute(args); + } + final typedArgs = args as SignInPageArguments ?? SignInPageArguments(); + return MaterialPageRoute( + builder: (_) => SignInPage(key: typedArgs.key), + settings: settings, + ); + case Routes.signUpPageRoute: + if (hasInvalidArgs(args)) { + return misTypedArgsRoute(args); + } + final typedArgs = args as SignUpPageArguments ?? SignUpPageArguments(); + return MaterialPageRoute( + builder: (_) => SignUpPage(key: typedArgs.key), + settings: settings, + ); + case Routes.applicationPageRoute: + if (hasInvalidArgs(args)) { + return misTypedArgsRoute(args); + } + final typedArgs = + args as ApplicationPageArguments ?? ApplicationPageArguments(); + return MaterialPageRoute( + builder: (_) => ApplicationPage(key: typedArgs.key), + settings: settings, + ); + case Routes.detailsPageRoute: + if (hasInvalidArgs(args)) { + return misTypedArgsRoute(args); + } + final typedArgs = + args as DetailsPageArguments ?? DetailsPageArguments(); + return MaterialPageRoute( + builder: (_) => DetailsPage(key: typedArgs.key), + settings: settings, + ); + default: + return unknownRoutePage(settings.name); + } + } +} + +//************************************************************************** +// Arguments holder classes +//*************************************************************************** + +//IndexPage arguments holder class +class IndexPageArguments { + final Key key; + IndexPageArguments({this.key}); +} + +//WelcomePage arguments holder class +class WelcomePageArguments { + final Key key; + WelcomePageArguments({this.key}); +} + +//SignInPage arguments holder class +class SignInPageArguments { + final Key key; + SignInPageArguments({this.key}); +} + +//SignUpPage arguments holder class +class SignUpPageArguments { + final Key key; + SignUpPageArguments({this.key}); +} + +//ApplicationPage arguments holder class +class ApplicationPageArguments { + final Key key; + ApplicationPageArguments({this.key}); +} + +//DetailsPage arguments holder class +class DetailsPageArguments { + final Key key; + DetailsPageArguments({this.key}); +} diff --git a/lib/common/utils/authentication.dart b/lib/common/utils/authentication.dart index 7a4a19b..5c76534 100644 --- a/lib/common/utils/authentication.dart +++ b/lib/common/utils/authentication.dart @@ -1,6 +1,8 @@ import 'dart:async'; +import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_ducafecat_news/common/router/router.gr.dart'; import 'package:flutter_ducafecat_news/common/utils/utils.dart'; import 'package:flutter_ducafecat_news/common/values/values.dart'; import 'package:flutter_ducafecat_news/global.dart'; @@ -20,6 +22,6 @@ Future deleteAuthentication() async { /// 重新登录 Future goLoginPage(BuildContext context) async { await deleteAuthentication(); - Navigator.pushNamedAndRemoveUntil( - context, "/sign-in", (Route route) => false); + ExtendedNavigator.rootNavigator.pushNamedAndRemoveUntil( + Routes.signInPageRoute, (Route route) => false); } diff --git a/lib/global.dart b/lib/global.dart index 1117141..9fd87ad 100644 --- a/lib/global.dart +++ b/lib/global.dart @@ -20,7 +20,7 @@ class Global { /// 是否离线登录 static bool isOfflineLogin = false; - /// 应用状态 + /// 应用状态, static AppState appState = AppState(); /// 是否 release diff --git a/lib/main.dart b/lib/main.dart index e4f9bdf..7bb30d2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,11 +1,11 @@ +import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_ducafecat_news/common/provider/provider.dart'; +import 'package:flutter_ducafecat_news/common/router/auth_grard.dart'; +import 'package:flutter_ducafecat_news/common/router/router.gr.dart'; import 'package:flutter_ducafecat_news/global.dart'; -import 'package:flutter_ducafecat_news/pages/index/index.dart'; -import 'package:flutter_ducafecat_news/routes.dart'; import 'package:provider/provider.dart'; -// void main() => runApp(MyApp()); void main() => Global.init().then((e) => runApp( MultiProvider( providers: [ @@ -31,9 +31,12 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MaterialApp( title: 'ducafecat.tech', - home: IndexPage(), - routes: staticRoutes, debugShowCheckedModeBanner: false, + builder: ExtendedNavigator( + initialRoute: Routes.indexPageRoute, + router: AppRouter(), + guards: [AuthGuard()], + ), ); } } diff --git a/lib/pages/sign_in/sign_in.dart b/lib/pages/sign_in/sign_in.dart index 05b0a68..7e91fb5 100644 --- a/lib/pages/sign_in/sign_in.dart +++ b/lib/pages/sign_in/sign_in.dart @@ -1,6 +1,8 @@ +import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_ducafecat_news/common/apis/apis.dart'; import 'package:flutter_ducafecat_news/common/entitys/entitys.dart'; +import 'package:flutter_ducafecat_news/common/router/router.gr.dart'; import 'package:flutter_ducafecat_news/common/utils/utils.dart'; import 'package:flutter_ducafecat_news/common/values/values.dart'; import 'package:flutter_ducafecat_news/common/widgets/widgets.dart'; @@ -21,10 +23,7 @@ class _SignInPageState extends State { // 跳转 注册界面 _handleNavSignUp() { - Navigator.pushNamed( - context, - "/sign-up", - ); + ExtendedNavigator.rootNavigator.pushNamed(Routes.signUpPageRoute); } // 执行登录操作 @@ -49,13 +48,7 @@ class _SignInPageState extends State { ); Global.saveProfile(userProfile); - // List newsList = await NewsAPI.index(); - // print(newsList.length); - - Navigator.pushNamed( - context, - "/app", - ); + ExtendedNavigator.rootNavigator.pushNamed(Routes.applicationPageRoute); } /////////////////////////////// diff --git a/lib/pages/welcome/welcome.dart b/lib/pages/welcome/welcome.dart index 5d12846..6213f65 100644 --- a/lib/pages/welcome/welcome.dart +++ b/lib/pages/welcome/welcome.dart @@ -1,4 +1,6 @@ +import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_ducafecat_news/common/router/router.gr.dart'; import 'package:flutter_ducafecat_news/common/utils/utils.dart'; import 'package:flutter_ducafecat_news/common/values/values.dart'; @@ -93,10 +95,7 @@ class WelcomePage extends StatelessWidget { borderRadius: Radii.k6pxRadius, ), onPressed: () { - Navigator.pushNamed( - context, - "/sign-in", - ); + ExtendedNavigator.rootNavigator.pushNamed(Routes.signInPageRoute); }, ), ); diff --git a/lib/routes.dart b/lib/routes.dart deleted file mode 100644 index 9f56044..0000000 --- a/lib/routes.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:flutter_ducafecat_news/pages/application/application.dart'; -import 'package:flutter_ducafecat_news/pages/index/index.dart'; -import 'package:flutter_ducafecat_news/pages/sign_in/sign_in.dart'; -import 'package:flutter_ducafecat_news/pages/sign_up/sign_up.dart'; - -/// 静态路由 -var staticRoutes = { - "/index": (context) => IndexPage(), // index - "/sign-in": (context) => SignInPage(), // 登录 - "/sign-up": (context) => SignUpPage(), // 注册 - "/app": (context) => ApplicationPage(), // 主程序 -}; diff --git a/pubspec.lock b/pubspec.lock index 8866e07..9a776c0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,20 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.2.0" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.39.7" archive: dependency: transitive description: @@ -22,6 +36,20 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.4.0" + auto_route: + dependency: "direct main" + description: + name: auto_route + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.4.4" + auto_route_generator: + dependency: "direct dev" + description: + name: auto_route_generator + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.4.4" boolean_selector: dependency: transitive description: @@ -29,6 +57,62 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.0.5" + build: + dependency: transitive + description: + name: build + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.2" + build_config: + dependency: transitive + description: + name: build_config + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.4.2" + build_daemon: + dependency: transitive + description: + name: build_daemon + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.4" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.3.5" + build_runner: + dependency: "direct dev" + description: + name: build_runner + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.8.1" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + url: "https://pub.flutter-io.cn" + source: hosted + version: "5.0.0" + built_collection: + dependency: transitive + description: + name: built_collection + url: "https://pub.flutter-io.cn" + source: hosted + version: "4.3.2" + built_value: + dependency: transitive + description: + name: built_value + url: "https://pub.flutter-io.cn" + source: hosted + version: "7.0.9" cached_network_image: dependency: "direct main" description: @@ -43,6 +127,20 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.1.2" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.2" + code_builder: + dependency: transitive + description: + name: code_builder + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.2.1" collection: dependency: transitive description: @@ -71,6 +169,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.1.3" + csslib: + dependency: transitive + description: + name: csslib + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.16.1" cupertino_icons: dependency: "direct main" description: @@ -78,6 +183,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.1.3" + dart_style: + dependency: transitive + description: + name: dart_style + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.3.4" dio: dependency: "direct main" description: @@ -92,6 +204,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.0.0" + fixnum: + dependency: transitive + description: + name: fixnum + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.10.11" flutter: dependency: "direct main" description: flutter @@ -111,13 +230,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" - flutter_modular: - dependency: "direct main" - description: - name: flutter_modular - url: "https://pub.flutter-io.cn" - source: hosted - version: "1.1.2" flutter_screenutil: dependency: "direct main" description: @@ -142,6 +254,27 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "3.1.3" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.0" + graphs: + dependency: transitive + description: + name: graphs + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.0" + html: + dependency: transitive + description: + name: html + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.14.0+3" http: dependency: transitive description: @@ -149,6 +282,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.12.0+4" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.2.0" http_parser: dependency: transitive description: @@ -170,6 +310,34 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.16.1" + io: + dependency: transitive + description: + name: io + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.3.4" + js: + dependency: transitive + description: + name: js + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.6.1+1" + json_annotation: + dependency: transitive + description: + name: json_annotation + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.1" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.11.4" matcher: dependency: transitive description: @@ -184,6 +352,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.1.8" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.9.6+3" nested: dependency: transitive description: @@ -191,6 +366,27 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.0.4" + node_interop: + dependency: transitive + description: + name: node_interop + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.3" + node_io: + dependency: transitive + description: + name: node_io + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.1+2" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.9.3" path: dependency: transitive description: @@ -254,6 +450,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.0.2" + pool: + dependency: transitive + description: + name: pool + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.4.0" provider: dependency: "direct main" description: @@ -261,6 +464,20 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "4.0.4" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.4.4" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.5" quiver: dependency: transitive description: @@ -296,11 +513,32 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.1.2+4" + shelf: + dependency: transitive + description: + name: shelf + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.7.5" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.3" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.9.5" source_span: dependency: transitive description: @@ -336,6 +574,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.0.0" + stream_transform: + dependency: transitive + description: + name: stream_transform + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.0" string_scanner: dependency: transitive description: @@ -364,6 +609,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.2.11" + timing: + dependency: transitive + description: + name: timing + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.1+2" typed_data: dependency: transitive description: @@ -385,6 +637,20 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.0.8" + watcher: + dependency: transitive + description: + name: watcher + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.9.7+14" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.0" xml: dependency: transitive description: @@ -392,6 +658,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "3.5.0" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.2.0" sdks: dart: ">=2.7.0 <3.0.0" flutter: ">=1.12.13+hotfix.4 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 1881a4c..91d095b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -24,22 +24,25 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.2 + # 路由管理 + auto_route: ^0.4.4 + # 日期格式 intl: ^0.16.1 # 屏幕适配 flutter_screenutil: ^1.0.2 - # ui + # 上下拉刷新 flutter_easyrefresh: ^2.1.0 # 骨架屏 pk_skeleton: ^0.0.2 - # toast + # 提示 toast fluttertoast: ^3.1.3 - # http + # 通讯 http dio: ^3.0.9 cookie_jar: ^1.0.1 dio_cookie_manager: ^1.0.0 @@ -48,7 +51,7 @@ dependencies: shared_preferences: ^0.5.6+3 cached_network_image: ^2.0.0 - # sha + # 加密安全 SHA crypto: ^2.1.3 # 状态管理 @@ -58,6 +61,10 @@ dev_dependencies: flutter_test: sdk: flutter + # 路由生成 + auto_route_generator: ^0.4.4 + build_runner: + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/test/widget_test.dart b/test/widget_test.dart index ca3eb34..0d105b3 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -8,12 +8,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:flutter_ducafecat_news/main.dart'; +// import 'package:flutter_ducafecat_news/main.dart'; void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); + // await tester.pumpWidget(MyApp()); // Verify that our counter starts at 0. expect(find.text('0'), findsOneWidget);