Browse Source

Merge pull request #857 from colinin/flutter

feat(flutter): add menu drawer
pull/860/head
yx lin 2 years ago
committed by GitHub
parent
commit
ecdf1741c5
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      apps/flutter/components/lib/widgets/menu/index.dart
  2. 2
      apps/flutter/core/lib/models/environment.dart
  3. 6
      apps/flutter/core/lib/models/environment.g.dart
  4. 4
      apps/flutter/dev_app/.gitignore
  5. 13
      apps/flutter/dev_app/lib/pages/main/controller.dart
  6. 14
      apps/flutter/dev_app/lib/pages/public/home/controller.dart
  7. 3
      apps/flutter/dev_app/lib/pages/public/home/state.dart
  8. 87
      apps/flutter/dev_app/lib/pages/public/home/view.dart
  9. 5
      apps/flutter/dev_app/lib/pages/public/home/widget/index.dart
  10. 76
      apps/flutter/dev_app/lib/pages/public/home/widget/menu_drawer.dart
  11. 42
      apps/flutter/dev_app/lib/pages/public/home/widget/my_favorite.dart
  12. 55
      apps/flutter/dev_app/lib/pages/public/home/widget/notification_bar.dart
  13. 33
      apps/flutter/dev_app/lib/pages/public/home/widget/quick_navigation.dart
  14. 17
      apps/flutter/dev_app/lib/services/notification.send.local.service.dart
  15. 20
      apps/flutter/dev_app/lib/services/translation.service.res.service.dart
  16. 14
      apps/flutter/dev_app/res/config/demo.json
  17. BIN
      apps/flutter/dev_app/res/images/notification.png
  18. 1
      apps/flutter/notifications/lib/models/notification.state.dart
  19. 11
      apps/flutter/notifications/lib/services/notification.state.service.dart
  20. 2
      apps/flutter/platform/lib/services/favorite.menu.state.service.dart
  21. 2
      apps/flutter/platform/lib/services/menu.state.service.dart

11
apps/flutter/components/lib/widgets/menu/index.dart

@ -21,11 +21,7 @@ class Navigation extends StatefulWidget {
class _NavigationState extends State<Navigation> { class _NavigationState extends State<Navigation> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SingleChildScrollView( return _renderNavigations(widget.menus);
child: Container(
child: _renderNavigations(widget.menus),
),
);
} }
Widget _renderNavigations(List<Menu> menus) { Widget _renderNavigations(List<Menu> menus) {
@ -59,7 +55,8 @@ class _NavigationState extends State<Navigation> {
return SizedBox( return SizedBox(
height: 30, height: 30,
child: ListTile( child: ListTile(
title: Text(menu.displayName.padLeft(menu.level * 4)), title: Text(
(menu.meta?['displayName']?.toString().tr ?? menu.displayName).padLeft(menu.level * 4)),
), ),
); );
}, },
@ -81,7 +78,7 @@ class _NavigationState extends State<Navigation> {
height: 30, height: 30,
margin: const EdgeInsets.only(top: 10), margin: const EdgeInsets.only(top: 10),
child: Text( child: Text(
menu.displayName.padLeft(menu.level * 8), (menu.meta?['displayName']?.toString().tr ?? menu.displayName).padLeft(menu.level * 8),
), ),
), ),
), ),

2
apps/flutter/core/lib/models/environment.dart

@ -177,10 +177,12 @@ class LocalizationConfig {
this.defaultLanguage, this.defaultLanguage,
this.useLocalResources = true, this.useLocalResources = true,
this.supportedLocales = const [], this.supportedLocales = const [],
this.translationFiles = const {},
}); });
String? defaultLanguage; String? defaultLanguage;
bool? useLocalResources; bool? useLocalResources;
List<LanguageInfo>? supportedLocales; List<LanguageInfo>? supportedLocales;
Map<String, List<String>>? translationFiles;
factory LocalizationConfig.fromJson(Map<String, dynamic> json) => _$LocalizationConfigFromJson(json); factory LocalizationConfig.fromJson(Map<String, dynamic> json) => _$LocalizationConfigFromJson(json);
Map<String, dynamic> toJson() => _$LocalizationConfigToJson(this); Map<String, dynamic> toJson() => _$LocalizationConfigToJson(this);

6
apps/flutter/core/lib/models/environment.g.dart

@ -102,6 +102,11 @@ LocalizationConfig _$LocalizationConfigFromJson(Map<String, dynamic> json) =>
supportedLocales: json['supportedLocales'] != null supportedLocales: json['supportedLocales'] != null
? (json['supportedLocales'] as List<dynamic>).map((e) => LanguageInfo.fromJson(e)).toList() ? (json['supportedLocales'] as List<dynamic>).map((e) => LanguageInfo.fromJson(e)).toList()
: null, : null,
translationFiles: json['translationFiles'] != null
? (json['translationFiles'] as Map<String, dynamic>)
.map((key, value) => MapEntry(key, (value as List<dynamic>)
.map((e) => e as String).toList()))
: null,
); );
Map<String, dynamic> _$LocalizationConfigToJson(LocalizationConfig instance) => Map<String, dynamic> _$LocalizationConfigToJson(LocalizationConfig instance) =>
@ -109,6 +114,7 @@ Map<String, dynamic> _$LocalizationConfigToJson(LocalizationConfig instance) =>
'defaultLanguage': instance.defaultLanguage, 'defaultLanguage': instance.defaultLanguage,
'useLocalResources': instance.useLocalResources, 'useLocalResources': instance.useLocalResources,
'supportedLocales': instance.supportedLocales, 'supportedLocales': instance.supportedLocales,
'translationFiles': instance.translationFiles,
}; };
RemoteService _$RemoteServiceFromJson(Map<String, dynamic> json) => RemoteService _$RemoteServiceFromJson(Map<String, dynamic> json) =>

4
apps/flutter/dev_app/.gitignore

@ -45,3 +45,7 @@ app.*.map.json
# Environment config # Environment config
/res/config/development.json /res/config/development.json
# Ignored translations
/res/translations/merge-en.json
/res/translations/merge-zh-Hans.json

13
apps/flutter/dev_app/lib/pages/main/controller.dart

@ -1,13 +1,13 @@
import 'package:core/dependency/index.dart'; import 'package:core/dependency/index.dart';
import 'package:core/abstracts/signalr.service.dart'; import 'package:core/abstracts/signalr.service.dart';
import 'package:core/services/environment.service.dart'; import 'package:core/services/environment.service.dart';
import 'package:core/services/notification.send.service.dart';
import 'package:dev_app/handlers/index.dart'; import 'package:dev_app/handlers/index.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:core/services/session.service.dart'; import 'package:core/services/session.service.dart';
import 'package:core/services/subscription.service.dart'; import 'package:core/services/subscription.service.dart';
import 'package:core/utils/index.dart'; import 'package:core/utils/index.dart';
import 'package:notifications/models/index.dart'; import 'package:notifications/models/index.dart';
import 'package:notifications/services/notification.state.service.dart';
import 'package:notifications/tokens/index.dart'; import 'package:notifications/tokens/index.dart';
class MainController extends GetxController { class MainController extends GetxController {
@ -17,7 +17,7 @@ class MainController extends GetxController {
SessionService get _sessionService => injector.get(); SessionService get _sessionService => injector.get();
SubscriptionService get _subscriptionService => injector.get(tag: NotificationTokens.consumer); SubscriptionService get _subscriptionService => injector.get(tag: NotificationTokens.consumer);
SignalrService get _signalrService => injector.get(tag: NotificationTokens.producer); SignalrService get _signalrService => injector.get(tag: NotificationTokens.producer);
NotificationSendService get _notificationSendService => injector.get(); NotificationStateService get _notificationStateService => injector.get();
EnvironmentService get _environmentService => injector.get(); EnvironmentService get _environmentService => injector.get();
ErrorHandler get _errorHandler => injector.get(); ErrorHandler get _errorHandler => injector.get();
@ -37,14 +37,7 @@ class MainController extends GetxController {
if (data == null) continue; if (data == null) continue;
// //
var notification = NotificationInfo.fromJson(data as dynamic); var notification = NotificationInfo.fromJson(data as dynamic);
// _notificationStateService.addNotification(notification);
var payload = NotificationPaylod.fromNotification(notification);
//
await _notificationSendService.send(
payload.title,
payload.body,
payload.payload,
);
} }
}, },
); );

14
apps/flutter/dev_app/lib/pages/public/home/controller.dart

@ -1,6 +1,7 @@
import 'package:core/models/common.dart'; import 'package:core/models/common.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:core/dependency/index.dart'; import 'package:core/dependency/index.dart';
import 'package:notifications/services/notification.state.service.dart';
import 'package:platforms/services/index.dart'; import 'package:platforms/services/index.dart';
import 'state.dart'; import 'state.dart';
@ -8,6 +9,7 @@ import 'state.dart';
class HomeController extends GetxController { class HomeController extends GetxController {
MenuStateService get _menuStateService => injector.get<MenuStateService>(); MenuStateService get _menuStateService => injector.get<MenuStateService>();
FavoriteMenuStateService get _favoriteMenuStateService => injector.get<FavoriteMenuStateService>(); FavoriteMenuStateService get _favoriteMenuStateService => injector.get<FavoriteMenuStateService>();
NotificationStateService get _notificationStateService => injector.get<NotificationStateService>();
final Rx<HomeState> _state = Rx<HomeState>(HomeState()); final Rx<HomeState> _state = Rx<HomeState>(HomeState());
HomeState get state => _state.value; HomeState get state => _state.value;
@ -27,6 +29,18 @@ class HomeController extends GetxController {
val?.favoriteMenus = menus; val?.favoriteMenus = menus;
}); });
}); });
_notificationStateService.getNotifications$()
.listen((payload) {
var notifications = state.notifications.reversed.take(5).toList();
notifications.add(payload);
_state.update((val) {
val?.notifications = notifications;
});
});
}
Future<void> refreshMenus() async {
await _menuStateService.refreshState();
} }
void redirectToRoute(String route) { void redirectToRoute(String route) {

3
apps/flutter/dev_app/lib/pages/public/home/state.dart

@ -1,4 +1,5 @@
import 'package:core/models/common.dart'; import 'package:core/models/common.dart';
import 'package:notifications/models/common.dart';
import 'package:platforms/modes/menu.dto.dart'; import 'package:platforms/modes/menu.dto.dart';
class HomeState { class HomeState {
@ -6,10 +7,12 @@ class HomeState {
this.activedMenu, this.activedMenu,
this.menus = const [], this.menus = const [],
this.favoriteMenus = const [], this.favoriteMenus = const [],
this.notifications = const [],
}); });
String? activedMenu; String? activedMenu;
List<MenuDto> menus; List<MenuDto> menus;
List<UserFavoriteMenuDto> favoriteMenus; List<UserFavoriteMenuDto> favoriteMenus;
List<NotificationPaylod> notifications;
List<Menu> getMenus() => _buildTreeRecursive(menus, null, 0); List<Menu> getMenus() => _buildTreeRecursive(menus, null, 0);

87
apps/flutter/dev_app/lib/pages/public/home/view.dart

@ -1,13 +1,13 @@
import 'package:account/pages/route.name.dart'; import 'package:account/pages/route.name.dart';
import 'package:components/index.dart'; import 'package:components/index.dart';
import 'package:core/utils/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:dev_app/pages/system/route.name.dart';
import 'package:flex_color_scheme/flex_color_scheme.dart'; import 'package:flex_color_scheme/flex_color_scheme.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'controller.dart'; import 'controller.dart';
import './widget/index.dart';
class HomePage extends BasePage<HomeController> { class HomePage extends BasePage<HomeController> {
const HomePage({super.key}); const HomePage({super.key});
@ -35,20 +35,9 @@ class HomePage extends BasePage<HomeController> {
), ),
body: ListView( body: ListView(
children: [ children: [
ExpansionTile( Obx(() => NotificationBar(notifications: bloc.state.notifications)),
initiallyExpanded: true, QuickNavigation(
title: Text('Label:QuickNavigation'.tr, menus: [
style: Theme.of(context).textTheme.titleMedium,
),
children: [
SizedBox(
height: 120,
child: GridView.count(
shrinkWrap: true,
crossAxisCount: 4,
crossAxisSpacing: 5,
physics: const NeverScrollableScrollPhysics(),
children: [
_buildMenu( _buildMenu(
SystemRoutes.settings, SystemRoutes.settings,
SystemRoutes.settings, SystemRoutes.settings,
@ -63,28 +52,9 @@ class HomePage extends BasePage<HomeController> {
color: const Color.fromARGB(255, 68, 160, 206).hex), color: const Color.fromARGB(255, 68, 160, 206).hex),
], ],
), ),
), Obx(() => MyFavorite(
], favoriteMenus: bloc.state.favoriteMenus,
), favoriteMenuBuilder: (favoriteMenu) {
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( return _buildMenu(
favoriteMenu.name, favoriteMenu.name,
favoriteMenu.path, favoriteMenu.path,
@ -96,54 +66,17 @@ class HomePage extends BasePage<HomeController> {
displayName: favoriteMenu.displayName, displayName: favoriteMenu.displayName,
); );
}, },
), )),
],
),
], ],
), ),
drawer: SafeArea( drawer: SafeArea(
child: Container( child: Obx(() => MenuDrawer(
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, activedMenu: bloc.state.activedMenu,
menus: bloc.state.getMenus(), menus: bloc.state.getMenus(),
onMenuExpanded: bloc.onMenuExpanded, onMenuExpanded: bloc.onMenuExpanded,
onMenuRefresh: bloc.refreshMenus,
)), )),
), ),
],
),
)
),
); );
} }

5
apps/flutter/dev_app/lib/pages/public/home/widget/index.dart

@ -0,0 +1,5 @@
export 'search.dart';
export 'menu_drawer.dart';
export 'my_favorite.dart';
export 'notification_bar.dart';
export 'quick_navigation.dart';

76
apps/flutter/dev_app/lib/pages/public/home/widget/menu_drawer.dart

@ -0,0 +1,76 @@
import 'package:components/widgets/menu/index.dart';
import 'package:core/models/common.dart';
import 'package:flutter/material.dart';
class MenuDrawer extends StatelessWidget {
const MenuDrawer({
super.key,
this.activedMenu,
this.menus = const [],
required this.onMenuRefresh,
this.onMenuExpanded,
});
final String? activedMenu;
final List<Menu> menus;
final void Function(Menu menu)? onMenuExpanded;
final Future<void> Function() onMenuRefresh;
@override
Widget build(BuildContext context) {
return RefreshIndicator(
onRefresh: onMenuRefresh,
child: Drawer(
width: 260,
child: Column(
children: [
_buildLogo(),
Expanded(
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: Column(
children: [
Navigation(
activedMenu: activedMenu,
menus: menus,
onMenuExpanded: onMenuExpanded,
),
],
),
)
),
],
),
),
);
}
Widget _buildLogo() {
return 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,
),
),
),
],
),
);
}
}

42
apps/flutter/dev_app/lib/pages/public/home/widget/my_favorite.dart

@ -0,0 +1,42 @@
import 'package:components/widgets/empty/index.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:platforms/modes/menu.dto.dart';
class MyFavorite extends StatelessWidget {
const MyFavorite({
super.key,
required this.favoriteMenus,
required this.favoriteMenuBuilder,
});
final List<UserFavoriteMenuDto> favoriteMenus;
final Widget Function(UserFavoriteMenuDto favoriteMenu) favoriteMenuBuilder;
@override
Widget build(BuildContext context) {
return ExpansionTile(
initiallyExpanded: true,
title: Text('Label:MyFavorite'.tr,
style: Theme.of(context).textTheme.titleMedium,
),
children: [
GridView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: favoriteMenus.length,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
crossAxisSpacing: 5,
),
itemBuilder: (BuildContext context, int index) {
if (index >= favoriteMenus.length) {
return Empty.none;
}
return favoriteMenuBuilder(favoriteMenus[index]);
},
),
],
);
}
}

55
apps/flutter/dev_app/lib/pages/public/home/widget/notification_bar.dart

@ -0,0 +1,55 @@
import 'package:bruno/bruno.dart';
import 'package:components/widgets/empty/index.dart';
import 'package:flutter/material.dart';
import 'package:notifications/models/common.dart';
import 'package:notifications/models/notification.dart';
class NotificationBar extends StatelessWidget {
const NotificationBar({
super.key,
required this.notifications
});
final List<NotificationPaylod> notifications;
@override
Widget build(BuildContext context) {
if (notifications.isEmpty) {
return Empty.none;
}
return SizedBox(
height: 40,
child: SingleChildScrollView(
child: Column(
children: notifications.map<BrnNoticeBar>((payload) {
return BrnNoticeBar(
padding: const EdgeInsets.only(left: 5, right: 5, top: 3),
leftWidget: Image.asset(
'res/images/notification.png',
height: 30,
width: 30,
),
content: payload.title,
marquee: true,
noticeStyle: _mapNoticeStyles(payload.severity),
);
}).toList(),
),
),
);
}
NoticeStyle _mapNoticeStyles(NotificationSeverity? severity) {
if (severity == null) return NoticeStyles.normalNoticeWithArrow;
switch (severity) {
case NotificationSeverity.info:
case NotificationSeverity.success:
return NoticeStyles.succeedWithArrow;
case NotificationSeverity.fatal:
case NotificationSeverity.error:
return NoticeStyles.failWithArrow;
case NotificationSeverity.warn:
return NoticeStyles.warningWithArrow;
}
}
}

33
apps/flutter/dev_app/lib/pages/public/home/widget/quick_navigation.dart

@ -0,0 +1,33 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class QuickNavigation extends StatelessWidget {
const QuickNavigation({
super.key,
this.menus = const [],
});
final List<Widget> menus;
@override
Widget build(BuildContext context) {
return 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: menus,
),
),
],
);
}
}

17
apps/flutter/dev_app/lib/services/notification.send.local.service.dart

@ -1,6 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'package:core/index.dart'; import 'package:core/index.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:notifications/services/notification.state.service.dart';
import 'package:rxdart/rxdart.dart' hide Notification; import 'package:rxdart/rxdart.dart' hide Notification;
import 'package:core/models/notifications.dart'; import 'package:core/models/notifications.dart';
@ -14,6 +15,22 @@ class FlutterLocalNotificationsSendService extends NotificationSendService {
final Subject<String?> _selectedNotifications$ = BehaviorSubject<String?>(); final Subject<String?> _selectedNotifications$ = BehaviorSubject<String?>();
EnvironmentService get _environmentService => resolve<EnvironmentService>(); EnvironmentService get _environmentService => resolve<EnvironmentService>();
NotificationStateService get _notificationStateService => resolve<NotificationStateService>();
@override
void onInit() {
super.onInit();
_notificationStateService
.getNotifications$()
.listen((payload) async {
//
await send(
payload.title,
payload.body,
payload.payload,
);
});
}
Future<void> initAsync() async { Future<void> initAsync() async {
var environment = _environmentService.getEnvironment(); var environment = _environmentService.getEnvironment();

20
apps/flutter/dev_app/lib/services/translation.service.res.service.dart

@ -1,5 +1,6 @@
import 'dart:ui'; import 'dart:ui';
import 'package:core/services/environment.service.dart';
import 'package:core/services/localization.service.dart'; import 'package:core/services/localization.service.dart';
import 'package:core/services/service.base.dart'; import 'package:core/services/service.base.dart';
import 'package:core/services/session.service.dart'; import 'package:core/services/session.service.dart';
@ -17,6 +18,7 @@ class TranslationResService extends ServiceBase implements TranslationService {
final InternalStore<TranslationState> _store = InternalStore<TranslationState>(state: TranslationState()); final InternalStore<TranslationState> _store = InternalStore<TranslationState>(state: TranslationState());
SessionService get _sessionService => resolve<SessionService>(); SessionService get _sessionService => resolve<SessionService>();
EnvironmentService get _environmentService => resolve<EnvironmentService>();
LocalizationService get _localizationService => resolve<LocalizationService>(); LocalizationService get _localizationService => resolve<LocalizationService>();
@override @override
@ -44,13 +46,21 @@ class TranslationResService extends ServiceBase implements TranslationService {
Future<TranslationState> _mapTranslationsMap(String language) async { Future<TranslationState> _mapTranslationsMap(String language) async {
Map<String, Map<String, String>> translationsMap = {}; Map<String, Map<String, String>> translationsMap = {};
var filePath = 'res/translations/$language.json'; var environment = _environmentService.getEnvironment();
var translationFiles = environment.localization.translationFiles?[language] ?? ['$language.json'];
for (var translationFile in translationFiles) {
try {
var filePath = 'res/translations/$translationFile';
var content = await rootBundle.loadString(filePath); var content = await rootBundle.loadString(filePath);
var translationsObject = jsonDecode(content) as Map<String, dynamic>; var translationsObject = jsonDecode(content) as Map<String, dynamic>;
translationsMap.putIfAbsent( var translations = translationsMap[language] ?? {};
language, translations.addAll(translationsObject.map((key, value) => MapEntry(key, value)));
() => translationsObject.map((key, value) => MapEntry(key, value)) translationsMap.putIfAbsent(language, () => translations);
); } catch (e) {
logger.error(e);
}
}
return TranslationState( return TranslationState(
language: language, language: language,
translations: translationsMap, translations: translationsMap,

14
apps/flutter/dev_app/res/config/demo.json

@ -13,6 +13,20 @@
"localization": { "localization": {
"useLocalResources": true, "useLocalResources": true,
"defaultLanguage": "zh-Hans", "defaultLanguage": "zh-Hans",
"translationFiles": {
"zh-Hans": [
"zh-Hans.json"
],
"zh_CN": [
"zh-Hans.json"
],
"en": [
"en.json"
],
"en_US": [
"en.json"
]
},
"supportedLocales": [ "supportedLocales": [
{ {
"cultureName": "en", "cultureName": "en",

BIN
apps/flutter/dev_app/res/images/notification.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

1
apps/flutter/notifications/lib/models/notification.state.dart

@ -15,6 +15,7 @@ class NotificationState {
bool isEnabled; bool isEnabled;
List<NotificationGroup> groups; List<NotificationGroup> groups;
NotificationGroup? findGroup(String name) { NotificationGroup? findGroup(String name) {
return groups.firstWhereOrNull((item) => item.name == name); return groups.firstWhereOrNull((item) => item.name == name);
} }

11
apps/flutter/notifications/lib/services/notification.state.service.dart

@ -1,4 +1,5 @@
import 'dart:convert'; import 'dart:convert';
import 'package:notifications/models/common.dart';
import 'package:rxdart/rxdart.dart' hide Notification; import 'package:rxdart/rxdart.dart' hide Notification;
import 'package:notifications/models/notification.dart'; import 'package:notifications/models/notification.dart';
import 'package:core/services/session.service.dart'; import 'package:core/services/session.service.dart';
@ -20,6 +21,8 @@ class NotificationStateService extends ServiceBase {
NotificationService get _notificationService => resolve<NotificationService>(); NotificationService get _notificationService => resolve<NotificationService>();
SignalrService get _signalrService => resolve<SignalrService>(tag: NotificationTokens.producer); SignalrService get _signalrService => resolve<SignalrService>(tag: NotificationTokens.producer);
final BehaviorSubject<NotificationPaylod> _notifications = BehaviorSubject<NotificationPaylod>();
final InternalStore<NotificationState> _store = InternalStore<NotificationState>( final InternalStore<NotificationState> _store = InternalStore<NotificationState>(
state: _initState() state: _initState()
); );
@ -41,6 +44,10 @@ class NotificationStateService extends ServiceBase {
return _store.sliceUpdate((state) => state); return _store.sliceUpdate((state) => state);
} }
Stream<NotificationPaylod> getNotifications$() {
return _notifications;
}
NotificationGroup? findGroup(String name) { NotificationGroup? findGroup(String name) {
return _store.state.findGroup(name); return _store.state.findGroup(name);
} }
@ -75,6 +82,10 @@ class NotificationStateService extends ServiceBase {
return configState ?? NotificationState(isEnabled: true, groups: []); return configState ?? NotificationState(isEnabled: true, groups: []);
} }
void addNotification(NotificationInfo notification) {
_notifications.add(NotificationPaylod.fromNotification(notification));
}
Future<List<NotificationGroup>> getGroupAndCombineWithNotification(List<NotificationGroupDto> groupItems) { Future<List<NotificationGroup>> getGroupAndCombineWithNotification(List<NotificationGroupDto> groupItems) {
return _notificationService.getMySubscribedListAsync() return _notificationService.getMySubscribedListAsync()
.then((subscres) { .then((subscres) {

2
apps/flutter/platform/lib/services/favorite.menu.state.service.dart

@ -33,7 +33,7 @@ class FavoriteMenuStateService extends ServiceBase {
Future<void> refreshState() async { Future<void> refreshState() async {
var environment = _environmentService.getEnvironment(); var environment = _environmentService.getEnvironment();
var framework = environment.application.framework ?? 'flutter'; var framework = environment.application.framework ?? 'abp-flutter';
var result = await _favoriteMenuService.getMyFavoriteMenuList(framework); var result = await _favoriteMenuService.getMyFavoriteMenuList(framework);
_state.patch((state) => state.menus = result.items); _state.patch((state) => state.menus = result.items);
} }

2
apps/flutter/platform/lib/services/menu.state.service.dart

@ -33,7 +33,7 @@ class MenuStateService extends ServiceBase {
Future<void> refreshState() async { Future<void> refreshState() async {
var environment = _environmentService.getEnvironment(); var environment = _environmentService.getEnvironment();
var framework = environment.application.framework ?? 'flutter'; var framework = environment.application.framework ?? 'abp-flutter';
var result = await _menuService.getCurrentUserMenuList(framework); var result = await _menuService.getCurrentUserMenuList(framework);
_state.patch((state) => state.menus = result.items); _state.patch((state) => state.menus = result.items);
} }

Loading…
Cancel
Save