diff --git a/apps/flutter/components/lib/widgets/index.dart b/apps/flutter/components/lib/widgets/index.dart index a3d62f746..98afe17da 100644 --- a/apps/flutter/components/lib/widgets/index.dart +++ b/apps/flutter/components/lib/widgets/index.dart @@ -2,4 +2,5 @@ export 'avatar/index.dart'; export 'action-button/index.dart'; export 'back-to-top/index.dart'; export 'bottom-button/index.dart'; -export 'empty/index.dart'; \ No newline at end of file +export 'empty/index.dart'; +export 'menu/index.dart'; \ No newline at end of file diff --git a/apps/flutter/components/lib/widgets/menu/index.dart b/apps/flutter/components/lib/widgets/menu/index.dart new file mode 100644 index 000000000..b060f7e82 --- /dev/null +++ b/apps/flutter/components/lib/widgets/menu/index.dart @@ -0,0 +1,90 @@ +import 'package:core/models/common.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class Navigation extends StatefulWidget { + const Navigation({ + super.key, + this.activedMenu, + this.menus = const [], + this.onMenuExpanded, + }); + + final List menus; + final String? activedMenu; + final void Function(Menu menu)? onMenuExpanded; + + @override + State createState() => _NavigationState(); +} + +class _NavigationState extends State { + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Container( + child: _renderNavigations(widget.menus), + ), + ); + } + + Widget _renderNavigations(List menus) { + var mainMenus = menus.where((menu) => menu.children?.isNotEmpty == false); + var subMenus = menus.where((menu) => menu.children?.isNotEmpty == true); + + return Column( + children: [ + _renderMenus(subMenus.toList()), + ...mainMenus.map((menu) => _buildMenuItem(menu)), + ], + ); + } + + Widget _renderMenus(List menus) { + return ExpansionPanelList.radio( + initialOpenPanelValue: widget.activedMenu, + expandedHeaderPadding: const EdgeInsets.all(0), + expansionCallback: (panelIndex, isExpanded) { + if (widget.onMenuExpanded != null) { + widget.onMenuExpanded!(menus[panelIndex]); + } + }, + children: menus.map((Menu menu) { + var body = menu.children?.isNotEmpty == true + ? _renderNavigations(menu.children!) + : _buildMenuItem(menu); + return ExpansionPanelRadio( + canTapOnHeader: true, + headerBuilder: (BuildContext context, bool isExpanded) { + return SizedBox( + height: 30, + child: ListTile( + title: Text(menu.displayName.padLeft(menu.level * 4)), + ), + ); + }, + body: body, + value: menu.name, + ); + }).toList(), + ); + } + + Widget _buildMenuItem(Menu menu) { + return InkWell( + onTap: () { + Get.toNamed(menu.path); + }, + child: FractionallySizedBox( + widthFactor: 1, + child: Container( + height: 30, + margin: const EdgeInsets.only(top: 10), + child: Text( + menu.displayName.padLeft(menu.level * 8), + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/apps/flutter/components/lib/widgets/menu/state.dart b/apps/flutter/components/lib/widgets/menu/state.dart new file mode 100644 index 000000000..2d3ff8350 --- /dev/null +++ b/apps/flutter/components/lib/widgets/menu/state.dart @@ -0,0 +1,3 @@ +class MenuState { + +} \ No newline at end of file diff --git a/apps/flutter/core/lib/models/common.dart b/apps/flutter/core/lib/models/common.dart index 2573eacc6..29cb93da9 100644 --- a/apps/flutter/core/lib/models/common.dart +++ b/apps/flutter/core/lib/models/common.dart @@ -42,3 +42,26 @@ class SignalrMessage { String method; List data; } + +class Menu { + Menu({ + required this.path, + required this.name, + required this.displayName, + this.id = 0, + this.level = 0, + this.description, + this.redirect, + this.meta, + this.children, + }); + String path; + String name; + String displayName; + String? description; + String? redirect; + int level; + int id; + Map? meta; + List? children; +} diff --git a/apps/flutter/core/lib/utils/color.utils.dart b/apps/flutter/core/lib/utils/color.utils.dart new file mode 100644 index 000000000..65eb7943f --- /dev/null +++ b/apps/flutter/core/lib/utils/color.utils.dart @@ -0,0 +1,16 @@ +import 'dart:ui'; + +class ColorUtils { + static Color fromHex(String hexString) { + final buffer = StringBuffer(); + if (hexString.length == 6 || hexString.length == 7) buffer.write('ff'); + buffer.write(hexString.replaceFirst('#', '')); + return Color(int.parse(buffer.toString(), radix: 16)); + } +} + +extension HexStringToColor on String { + Color toColor() { + return ColorUtils.fromHex(this); + } +} \ No newline at end of file diff --git a/apps/flutter/core/lib/utils/index.dart b/apps/flutter/core/lib/utils/index.dart index fe2eb5beb..602f60d90 100644 --- a/apps/flutter/core/lib/utils/index.dart +++ b/apps/flutter/core/lib/utils/index.dart @@ -1,3 +1,4 @@ +export 'color.utils.dart'; export 'environment.utils.dart'; export 'internal.store.dart'; export 'localization.utils.dart'; diff --git a/apps/flutter/dev_app/lib/main.dart b/apps/flutter/dev_app/lib/main.dart index f99928b23..1ee8c93b6 100644 --- a/apps/flutter/dev_app/lib/main.dart +++ b/apps/flutter/dev_app/lib/main.dart @@ -2,10 +2,12 @@ import 'package:core/dependency/index.dart'; import 'package:core/utils/theme.utils.dart'; import 'package:core/utils/logging.dart'; import 'package:dev_app/main.module.dart'; +import 'package:dev_app/pages/index.dart'; +import 'package:dev_app/pages/public/route.name.dart'; import 'package:dev_app/utils/localization.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter/material.dart'; import 'package:get/get.dart'; Future main() async { @@ -25,8 +27,9 @@ class MyApp extends StatelessWidget { theme: ThemeUtils.lightTheme, darkTheme: ThemeUtils.darkTheme, themeMode: ThemeMode.system, - initialRoute: '/', + initialRoute: PublicRoutes.main, getPages: module.getRoutes(), + unknownRoute: PublicRoute.notFound, debugShowMaterialGrid: false, enableLog: true, builder: EasyLoading.init(), diff --git a/apps/flutter/dev_app/lib/main.module.dart b/apps/flutter/dev_app/lib/main.module.dart index a0dc8c9b3..ed7fca5a9 100644 --- a/apps/flutter/dev_app/lib/main.module.dart +++ b/apps/flutter/dev_app/lib/main.module.dart @@ -1,5 +1,6 @@ import 'package:components/index.dart'; import 'package:dev_app/pages/index.dart'; +import 'package:dev_app/pages/public/route.name.dart'; import 'package:dev_app/services/index.dart'; import 'package:dev_app/utils/initial.utils.dart'; import 'package:dev_app/utils/loading.dart'; @@ -30,7 +31,7 @@ class MainModule extends Module { @override List get routes => [ GetPage( - name: '/', + name: PublicRoutes.main, page: () => const MainPage(), bindings: [ MainBinding(), diff --git a/apps/flutter/dev_app/lib/pages/public/center/controller.dart b/apps/flutter/dev_app/lib/pages/public/center/controller.dart index 653c1a1f7..c40367fd5 100644 --- a/apps/flutter/dev_app/lib/pages/public/center/controller.dart +++ b/apps/flutter/dev_app/lib/pages/public/center/controller.dart @@ -44,15 +44,15 @@ class CenterController extends GetxController { } void onClickFeedback() { - + redirectToRoute('/feedback'); } void onClickHelp() { - + redirectToRoute('/help'); } void onClickInfo() { - + redirectToRoute('/info'); } void onClickMessage() { diff --git a/apps/flutter/dev_app/lib/pages/public/error/index.dart b/apps/flutter/dev_app/lib/pages/public/error/index.dart new file mode 100644 index 000000000..aa4da5d13 --- /dev/null +++ b/apps/flutter/dev_app/lib/pages/public/error/index.dart @@ -0,0 +1 @@ +export './not_found/index.dart'; \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/pages/public/error/not_found/index.dart b/apps/flutter/dev_app/lib/pages/public/error/not_found/index.dart new file mode 100644 index 000000000..3205d6a40 --- /dev/null +++ b/apps/flutter/dev_app/lib/pages/public/error/not_found/index.dart @@ -0,0 +1 @@ +export 'view.dart'; \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/pages/public/error/not_found/view.dart b/apps/flutter/dev_app/lib/pages/public/error/not_found/view.dart new file mode 100644 index 000000000..e25c60e1a --- /dev/null +++ b/apps/flutter/dev_app/lib/pages/public/error/not_found/view.dart @@ -0,0 +1,23 @@ +import 'package:bruno/bruno.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class PageNotFound extends StatelessWidget { + const PageNotFound({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("404Message".tr) + ), + body: BrnAbnormalStateWidget( + img: Image.asset( + 'res/images/no_data.png', + scale: 3.0, + ), + content: "404MessageDetail".tr, + ), + ); + } +} \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/pages/public/home/controller.dart b/apps/flutter/dev_app/lib/pages/public/home/controller.dart index 0e8bd7cdd..b6884ba1c 100644 --- a/apps/flutter/dev_app/lib/pages/public/home/controller.dart +++ b/apps/flutter/dev_app/lib/pages/public/home/controller.dart @@ -1,3 +1,4 @@ +import 'package:core/models/common.dart'; import 'package:get/get.dart'; import 'package:core/dependency/index.dart'; import 'package:platforms/services/index.dart'; @@ -14,17 +15,27 @@ class HomeController extends GetxController { @override void onInit() { super.onInit(); - // _menuStateService.getMyMenus$() - // .listen((menus) { - // _state.update((val) { - // val?.menus = menus; - // }); - // }); - // _favoriteMenuStateService.getFavoriteMenus$() - // .listen((menus) { - // _state.update((val) { - // val?.favoriteMenus = menus; - // }); - // }); + _menuStateService.getMyMenus$() + .listen((menus) { + _state.update((val) { + val?.menus = menus; + }); + }); + _favoriteMenuStateService.getFavoriteMenus$() + .listen((menus) { + _state.update((val) { + val?.favoriteMenus = menus; + }); + }); + } + + void redirectToRoute(String route) { + Get.toNamed(route); + } + + void onMenuExpanded(Menu menu) { + _state.update((val) { + val?.activedMenu = menu.name; + }); } } \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/pages/public/home/state.dart b/apps/flutter/dev_app/lib/pages/public/home/state.dart index a810abe02..cafd45fd6 100644 --- a/apps/flutter/dev_app/lib/pages/public/home/state.dart +++ b/apps/flutter/dev_app/lib/pages/public/home/state.dart @@ -1,10 +1,35 @@ +import 'package:core/models/common.dart'; import 'package:platforms/modes/menu.dto.dart'; class HomeState { HomeState({ + this.activedMenu, this.menus = const [], this.favoriteMenus = const [], }); + String? activedMenu; List menus; List favoriteMenus; + + List getMenus() => _buildTreeRecursive(menus, null, 0); + + List _buildTreeRecursive(List treeMenus, String? parentId, int level) { + List results = []; + var tempList = treeMenus.where((menu) => menu.parentId == parentId).toList(); + for (int i = 0; i < tempList.length; i++) { + var menu = Menu( + id: tempList[i].id.hashCode, + path: tempList[i].path, + name: tempList[i].name, + displayName: tempList[i].displayName, + description: tempList[i].description, + redirect: tempList[i].redirect, + meta: tempList[i].meta, + level: level + 1 + ); + menu.children = _buildTreeRecursive(treeMenus, tempList[i].id, menu.level); + results.add(menu); + } + return results; + } } \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/pages/public/home/view.dart b/apps/flutter/dev_app/lib/pages/public/home/view.dart index 5dcc92008..b6a77950c 100644 --- a/apps/flutter/dev_app/lib/pages/public/home/view.dart +++ b/apps/flutter/dev_app/lib/pages/public/home/view.dart @@ -1,6 +1,11 @@ +import 'package:account/pages/route.name.dart'; import 'package:components/index.dart'; +import 'package:core/utils/index.dart'; import 'package:dev_app/pages/public/home/widget/search.dart'; +import 'package:dev_app/pages/system/route.name.dart'; +import 'package:flex_color_scheme/flex_color_scheme.dart'; import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import 'controller.dart'; @@ -20,26 +25,165 @@ class HomePage extends BasePage { onPressed: () { showSearch(context: context, delegate: SearchBarDelegate(menus: bloc.state.menus)); }, - child: const Row( + child: Row( children: [ - Icon(Icons.search), - Expanded(child: Text('搜索功能')) + const Icon(Icons.search), + Expanded(child: Text('Label:SearchFeatures'.tr)) ], ), ), ), - body: Column( + body: ListView( children: [ - Expanded( - child: ListView.builder( - itemCount: bloc.state.favoriteMenus.length, - itemBuilder: (context, index) { - var favoriteMenu = bloc.state.favoriteMenus[index]; - return Text(favoriteMenu.displayName ?? favoriteMenu.name); - }, + ExpansionTile( + initiallyExpanded: true, + title: Text('Label:QuickNavigation'.tr, + style: Theme.of(context).textTheme.titleMedium, + ), + children: [ + SizedBox( + height: 120, + child: GridView.count( + shrinkWrap: true, + crossAxisCount: 4, + crossAxisSpacing: 5, + physics: const NeverScrollableScrollPhysics(), + children: [ + _buildMenu( + SystemRoutes.settings, + SystemRoutes.settings, + icon: 'res/images/setting.png', + displayName: "Label:SystemSettings".tr, + color: Colors.red.hex), + _buildMenu( + AccountRoutes.profile, + AccountRoutes.profile, + icon: 'res/images/profile.png', + displayName: "Page:UserProfile".tr, + color: const Color.fromARGB(255, 68, 160, 206).hex), + ], + ), + ), + ], ), + ExpansionTile( + initiallyExpanded: true, + title: Text('Label:MyFavorite'.tr, + style: Theme.of(context).textTheme.titleMedium, + ), + children: [ + GridView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: bloc.state.favoriteMenus.length, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 4, + crossAxisSpacing: 5, + ), + itemBuilder: (BuildContext context, int index) { + if (index >= bloc.state.favoriteMenus.length) { + return Empty.none; + } + var favoriteMenu = bloc.state.favoriteMenus[index]; + return _buildMenu( + favoriteMenu.name, + favoriteMenu.path, + aliasName: favoriteMenu.aliasName, + //icon: favoriteMenu.icon, + // TODO: 需要各个模块自行提供本地图标 + icon: 'res/images/setting.png', + color: favoriteMenu.color, + displayName: favoriteMenu.displayName, + ); + }, + ), + ], + ), + ], + ), + drawer: SafeArea( + child: Container( + width: 260, + color: const Color.fromARGB(255, 44, 115, 141), + child: Column( + children: [ + Container( + height: 24, + margin: const EdgeInsets.all(10), + child: Row( + children: [ + Padding( + padding: const EdgeInsets.only(left: 10), + child: Image.asset( + 'res/images/logo.png', + height: 20, + width: 20, + ), + ), + const Padding( + padding: EdgeInsets.only(left: 10), + child: Text( + 'abp flutter', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w400, + ), + ), + ), + ], + ), + ), + Expanded( + child: Obx(() => Navigation( + activedMenu: bloc.state.activedMenu, + menus: bloc.state.getMenus(), + onMenuExpanded: bloc.onMenuExpanded, + )), + ), + ], ), - ], + ) + ), + ); + } + + Widget _buildMenu( + String name, + String path, + { + String? aliasName, + String? icon, + String? color, + String? displayName, + } + ) { + return InkWell( + onTap: () { + bloc.redirectToRoute(path); + }, + child: SizedBox( + height: 20, + width: 30, + child: Column( + children: [ + const SizedBox(height: 10), + icon != null + ? Image.asset( + icon, + height: 40, + width: 40, + color: color.isNullOrWhiteSpace() ? null : ColorUtils.fromHex(color!), + ) + : Empty.none, + Text( + displayName ?? aliasName ?? name, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 14 + ), + ) + ], + ), ), ); } diff --git a/apps/flutter/dev_app/lib/pages/public/home/widget/search.dart b/apps/flutter/dev_app/lib/pages/public/home/widget/search.dart index 99c8e4998..46baf8ae6 100644 --- a/apps/flutter/dev_app/lib/pages/public/home/widget/search.dart +++ b/apps/flutter/dev_app/lib/pages/public/home/widget/search.dart @@ -13,8 +13,7 @@ class SearchBarDelegate extends SearchDelegate { List? buildActions(BuildContext context) { Widget button = IconButton( onPressed: () { - query = ""; - showSuggestions(context); + close(context, "error"); }, icon: const Icon(Icons.clear), ); @@ -24,15 +23,17 @@ class SearchBarDelegate extends SearchDelegate { @override Widget? buildLeading(BuildContext context) { - return IconButton( - onPressed: () { - close(context, "error"); - }, - icon: AnimatedIcon( - icon: AnimatedIcons.menu_arrow, - progress: transitionAnimation, - ), - ); + // return IconButton( + // onPressed: () { + // query = ""; + // showSuggestions(context); + // }, + // icon: AnimatedIcon( + // icon: AnimatedIcons.menu_arrow, + // progress: transitionAnimation, + // ), + // ); + return null; } @override diff --git a/apps/flutter/dev_app/lib/pages/public/index.dart b/apps/flutter/dev_app/lib/pages/public/index.dart index aee3141ae..7d24fe4b5 100644 --- a/apps/flutter/dev_app/lib/pages/public/index.dart +++ b/apps/flutter/dev_app/lib/pages/public/index.dart @@ -1,3 +1,4 @@ export './center/index.dart'; export './home/index.dart'; -export './work/index.dart'; \ No newline at end of file +export './work/index.dart'; +export './error/index.dart'; \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/pages/public/route.name.dart b/apps/flutter/dev_app/lib/pages/public/route.name.dart index 4361f2488..2f5830c89 100644 --- a/apps/flutter/dev_app/lib/pages/public/route.name.dart +++ b/apps/flutter/dev_app/lib/pages/public/route.name.dart @@ -1,5 +1,7 @@ class PublicRoutes { + static String main = '/main'; static String home = '/home'; static String work = '/work'; static String center = '/center'; + static String notFound = '/error/not_found'; } \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/pages/public/route.public.dart b/apps/flutter/dev_app/lib/pages/public/route.public.dart index b4d6a39f5..9ade2f155 100644 --- a/apps/flutter/dev_app/lib/pages/public/route.public.dart +++ b/apps/flutter/dev_app/lib/pages/public/route.public.dart @@ -4,7 +4,13 @@ import 'index.dart'; import 'route.name.dart'; class PublicRoute { + static GetPage notFound = GetPage( + name: PublicRoutes.notFound, + page: () => const PageNotFound(), + ); + static List routes = [ + notFound, GetPage( name: PublicRoutes.home, page: () => const HomePage(), diff --git a/apps/flutter/dev_app/pubspec.lock b/apps/flutter/dev_app/pubspec.lock index bb2298370..bd7d65046 100644 --- a/apps/flutter/dev_app/pubspec.lock +++ b/apps/flutter/dev_app/pubspec.lock @@ -40,6 +40,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.11.0" + bindings_compatible: + dependency: transitive + description: + name: bindings_compatible + sha256: "5dd5189f7512aff8ec180a8a11bd59230aa34a2d743e65e427192b7292a78d87" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.1" boolean_selector: dependency: transitive description: @@ -48,6 +56,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.1.1" + bruno: + dependency: "direct main" + description: + name: bruno + sha256: "8bd461a658996000eab1111a93fb4826ade878103f5a9afa29a414046805448b" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.4.1" build: dependency: transitive description: @@ -307,6 +323,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "3.0.5" + flutter_easyrefresh: + dependency: transitive + description: + name: flutter_easyrefresh + sha256: "5d161ee5dcac34da9065116568147d742dd25fb9bff3b10024d9054b195087ad" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.2.2" flutter_highlight: dependency: transitive description: @@ -514,6 +538,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.2.0" + lpinyin: + dependency: transitive + description: + name: lpinyin + sha256: "0bb843363f1f65170efd09fbdfc760c7ec34fc6354f9fcb2f89e74866a0d814a" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.3" markdown: dependency: transitive description: @@ -608,6 +640,22 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.8.3" + path_drawing: + dependency: transitive + description: + name: path_drawing + sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977 + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.1" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.1" path_provider: dependency: transitive description: @@ -664,6 +712,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "5.4.0" + photo_view: + dependency: transitive + description: + name: photo_view + sha256: "8036802a00bae2a78fc197af8a158e3e2f7b500561ed23b4c458107685e645bb" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.14.0" platform: dependency: transitive description: diff --git a/apps/flutter/dev_app/pubspec.yaml b/apps/flutter/dev_app/pubspec.yaml index 7336089e5..db627ecaf 100644 --- a/apps/flutter/dev_app/pubspec.yaml +++ b/apps/flutter/dev_app/pubspec.yaml @@ -49,6 +49,7 @@ dependencies: platforms: path: '../platform' + bruno: ^3.3.0 dio: ^5.2.0+1 flutter_easyloading: ^3.0.5 flutter_picker: ^2.1.0 diff --git a/apps/flutter/dev_app/res/images/no_data.png b/apps/flutter/dev_app/res/images/no_data.png new file mode 100644 index 000000000..10d07379d Binary files /dev/null and b/apps/flutter/dev_app/res/images/no_data.png differ diff --git a/apps/flutter/dev_app/res/images/profile.png b/apps/flutter/dev_app/res/images/profile.png new file mode 100644 index 000000000..0d8bf21d4 Binary files /dev/null and b/apps/flutter/dev_app/res/images/profile.png differ diff --git a/apps/flutter/dev_app/res/images/setting.png b/apps/flutter/dev_app/res/images/setting.png new file mode 100644 index 000000000..46c201588 Binary files /dev/null and b/apps/flutter/dev_app/res/images/setting.png differ diff --git a/apps/flutter/dev_app/res/translations/en.json b/apps/flutter/dev_app/res/translations/en.json index 602e12384..e52514ca9 100644 --- a/apps/flutter/dev_app/res/translations/en.json +++ b/apps/flutter/dev_app/res/translations/en.json @@ -5,6 +5,7 @@ "404Message": "Page not found", "404MessageDetail": "Sorry, there's nothing at this address.", "500Message": "Internal Server Error", + "Avatar": "Avatar", "Center:Feedback": "Feedback", "Center:Help": "Help", "Center:Info": "Info", @@ -12,6 +13,9 @@ "Center:Settings": "Settings", "DisplayName:Abp.Localization.DefaultLanguage": "Default language", "Description:Abp.Localization.DefaultLanguage": "The default language of the application.", + "DisplayName:UserName": "User Name", + "DisplayName:Email": "Email", + "DisplayName:PhoneNumber": "Phone Number", "DefaultErrorMessage": "An error has occurred!", "DefaultErrorMessageDetail": "Error detail not sent by server.", "DefaultErrorMessage401": "You are not authenticated!", @@ -37,6 +41,7 @@ "Label:NotifierSettings": "Notifier Settings", "Label:PasswordRequired": "Please enter password", "Label:PhoneNumberNotBound": "PhoneNumber Not Bound", + "Label:SearchFeatures": "Search Features", "Label:Submit": "Submit", "Label:SwitchTheme": "Switch Theme", "Label:SystemSettings": "System Settings", @@ -45,6 +50,8 @@ "Label:Cancel": "Cancel", "Label:Confirm": "Confirm", "Label:LoginToPortal": "Login To Portal", + "Label:QuickNavigation": "Quick navigation", + "Label:MyFavorite": "My favorites", "Languages": "Languages", "Page:Center": "Center", "Page:Home": "Home", diff --git a/apps/flutter/dev_app/res/translations/zh-Hans.json b/apps/flutter/dev_app/res/translations/zh-Hans.json index bf9ae99b8..c5ad416ab 100644 --- a/apps/flutter/dev_app/res/translations/zh-Hans.json +++ b/apps/flutter/dev_app/res/translations/zh-Hans.json @@ -2,9 +2,10 @@ "401Message": "未授权", "403Message": "禁止访问", "403MessageDetail": "您没有权限执行此操作!", - "404Message": "网页未找到", + "404Message": "页面未找到", "404MessageDetail": "抱歉, 这个地址是空的.", "500Message": "内部服务器错误", + "Avatar": "头像", "Center:Feedback": "意见反馈", "Center:Help": "在线帮助", "Center:Info": "关于", @@ -12,6 +13,9 @@ "Center:Settings": "设置", "DisplayName:Abp.Localization.DefaultLanguage": "默认语言", "Description:Abp.Localization.DefaultLanguage": "应用程序的默认语言.", + "DisplayName:UserName": "用户名", + "DisplayName:Email": "邮件地址", + "DisplayName:PhoneNumber": "手机号码", "DefaultErrorMessage": "发生错误!", "DefaultErrorMessageDetail": "服务器未发送错误的详细信息.", "DefaultErrorMessage401": "未通过身份验证!", @@ -37,6 +41,7 @@ "Label:NotifierSettings": "通知设置", "Label:PasswordRequired": "请输入密码", "Label:PhoneNumberNotBound": "未绑定手机号", + "Label:SearchFeatures": "搜索功能", "Label:Submit": "提交", "Label:SwitchTheme": "切换主题", "Label:SystemSettings": "系统设置", @@ -45,6 +50,8 @@ "Label:Cancel": "取消", "Label:Confirm": "确认", "Label:LoginToPortal": "登录到门户", + "Label:QuickNavigation": "快捷导航", + "Label:MyFavorite": "我的收藏", "Languages": "语言", "Page:Center": "个人中心", "Page:Home": "首页", diff --git a/apps/flutter/platform/lib/services/favorite.menu.state.service.dart b/apps/flutter/platform/lib/services/favorite.menu.state.service.dart index 1114b2403..eb9e6b272 100644 --- a/apps/flutter/platform/lib/services/favorite.menu.state.service.dart +++ b/apps/flutter/platform/lib/services/favorite.menu.state.service.dart @@ -1,5 +1,6 @@ import 'package:core/services/environment.service.dart'; import 'package:core/services/service.base.dart'; +import 'package:core/services/session.service.dart'; import 'package:core/utils/index.dart'; import 'package:platforms/modes/state.dart'; import 'package:platforms/modes/menu.dto.dart'; @@ -10,13 +11,24 @@ class FavoriteMenuStateService extends ServiceBase { final InternalStore _state = InternalStore(state: FavoriteMenuState()); + SessionService get _sessionService => resolve(); EnvironmentService get _environmentService => resolve(); FavoriteMenuService get _favoriteMenuService => resolve(); @override void onInit() { super.onInit(); - refreshState(); + _initState(); + } + + void _initState() { + _sessionService.getToken$() + .listen((token) { + _state.patch((state) => state.menus = []); + if (token != null) { + refreshState(); + } + }); } Future refreshState() async { diff --git a/apps/flutter/platform/lib/services/menu.state.service.dart b/apps/flutter/platform/lib/services/menu.state.service.dart index d6575bb67..ac302d6d8 100644 --- a/apps/flutter/platform/lib/services/menu.state.service.dart +++ b/apps/flutter/platform/lib/services/menu.state.service.dart @@ -1,5 +1,6 @@ import 'package:core/services/environment.service.dart'; import 'package:core/services/service.base.dart'; +import 'package:core/services/session.service.dart'; import 'package:core/utils/index.dart'; import 'package:platforms/modes/state.dart'; import 'package:platforms/modes/menu.dto.dart'; @@ -11,12 +12,23 @@ class MenuStateService extends ServiceBase { final InternalStore _state = InternalStore(state: MenuState()); EnvironmentService get _environmentService => resolve(); + SessionService get _sessionService => resolve(); MenuService get _menuService => resolve(); @override void onInit() { super.onInit(); - refreshState(); + _initState(); + } + + void _initState() { + _sessionService.getToken$() + .listen((token) { + _state.patch((state) => state.menus = []); + if (token != null) { + refreshState(); + } + }); } Future refreshState() async {