Browse Source

Merge pull request #852 from colinin/flutter

feat(notifications): notify the configuration of local storage
pull/855/head
yx lin 2 years ago
committed by GitHub
parent
commit
c7cb3a7647
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 49
      apps/flutter/core/lib/config/env.config.dart
  2. 37
      apps/flutter/core/lib/config/env.config.g.dart
  3. 4
      apps/flutter/core/lib/models/abp.dto.dart
  4. 2
      apps/flutter/core/lib/services/service.base.dart
  5. 13
      apps/flutter/core/lib/utils/localization.utils.dart
  6. 42
      apps/flutter/dev_app/README.md
  7. 55
      apps/flutter/dev_app/lib/pages/main/controller.dart
  8. 37
      apps/flutter/dev_app/lib/services/notification.send.local.service.dart
  9. 12
      apps/flutter/dev_app/res/config/demo.json
  10. 36
      apps/flutter/notifications/lib/models/common.dart
  11. 3
      apps/flutter/notifications/lib/models/index.dart
  12. 31
      apps/flutter/notifications/lib/models/notification.state.dart
  13. 80
      apps/flutter/notifications/lib/models/notification.state.g.dart
  14. 1
      apps/flutter/notifications/lib/notifications.module.dart
  15. 81
      apps/flutter/notifications/lib/pages/notifier/controller.dart
  16. 2
      apps/flutter/notifications/lib/pages/notifier/widget/notifier_card.dart
  17. 3
      apps/flutter/notifications/lib/services/index.dart
  18. 124
      apps/flutter/notifications/lib/services/notification.state.service.dart

49
apps/flutter/core/lib/config/env.config.dart

@ -15,6 +15,7 @@ class EnvConfig {
this.staticFilesUrl,
this.tenantKey = '__tenant',
this.defaultLanguage = 'en',
this.notifications,
});
String clientId;
String? clientSecret;
@ -24,10 +25,56 @@ class EnvConfig {
String? staticFilesUrl;
String? tenantKey;
String? defaultLanguage;
NotificationConfig? notifications;
factory EnvConfig.fromJson(Map<String, dynamic> json) => _$EnvConfigFromJson(json);
}
@JsonSerializable(createToJson: false)
class NotificationConfig {
NotificationConfig({
this.android,
this.darwin,
this.linux,
});
AndroidNotification? android;
DarwinNotification? darwin;
LinuxNotification? linux;
factory NotificationConfig.fromJson(Map<String, dynamic> json) => _$NotificationConfigFromJson(json);
}
@JsonSerializable(createToJson: false)
class LinuxNotification {
LinuxNotification({
required this.defaultActionName,
});
String defaultActionName;
factory LinuxNotification.fromJson(Map<String, dynamic> json) => _$LinuxNotificationFromJson(json);
}
@JsonSerializable(createToJson: false)
class AndroidNotification {
AndroidNotification({
required this.channelId,
required this.channelName,
this.channelDescription,
});
String channelId;
String channelName;
String? channelDescription;
factory AndroidNotification.fromJson(Map<String, dynamic> json) => _$AndroidNotificationFromJson(json);
}
@JsonSerializable(createToJson: false)
class DarwinNotification {
DarwinNotification();
factory DarwinNotification.fromJson(Map<String, dynamic> json) => _$DarwinNotificationFromJson(json);
}
enum Env {
development('DEV', 'Development'),
profile('PROF', 'Profile'),
@ -53,7 +100,7 @@ class Environment {
fromJson: EnvConfig.fromJson,
);
Environment.current = envlib.Environment.instance().config;
Environment.current = envlib.Environment<EnvConfig>.instance().config;
}
static late EnvConfig current;

37
apps/flutter/core/lib/config/env.config.g.dart

@ -13,6 +13,39 @@ EnvConfig _$EnvConfigFromJson(Map<String, dynamic> json) => EnvConfig(
baseUrl: json['baseUrl'] as String,
uploadFilesUrl: json['uploadFilesUrl'] as String?,
staticFilesUrl: json['staticFilesUrl'] as String?,
tenantKey: json['tenantKey'] as String?,
defaultLanguage: json['defaultLanguage'] as String?,
tenantKey: json['tenantKey'] as String? ?? '__tenant',
defaultLanguage: json['defaultLanguage'] as String? ?? 'en',
notifications: json['notifications'] == null
? null
: NotificationConfig.fromJson(
json['notifications'] as Map<String, dynamic>),
);
NotificationConfig _$NotificationConfigFromJson(Map<String, dynamic> json) =>
NotificationConfig(
android: json['android'] == null
? null
: AndroidNotification.fromJson(
json['android'] as Map<String, dynamic>),
darwin: json['darwin'] == null
? null
: DarwinNotification.fromJson(json['darwin'] as Map<String, dynamic>),
linux: json['linux'] == null
? null
: LinuxNotification.fromJson(json['linux'] as Map<String, dynamic>),
);
LinuxNotification _$LinuxNotificationFromJson(Map<String, dynamic> json) =>
LinuxNotification(
defaultActionName: json['defaultActionName'] as String,
);
AndroidNotification _$AndroidNotificationFromJson(Map<String, dynamic> json) =>
AndroidNotification(
channelId: json['channelId'] as String,
channelName: json['channelName'] as String,
channelDescription: json['channelDescription'] as String?,
);
DarwinNotification _$DarwinNotificationFromJson(Map<String, dynamic> json) =>
DarwinNotification();

4
apps/flutter/core/lib/models/abp.dto.dart

@ -2,18 +2,22 @@ class LocalizableStringInfo {
LocalizableStringInfo({
required this.resourceName,
required this.name,
this.values,
});
String resourceName;
String name;
Map<String, dynamic>? values;
factory LocalizableStringInfo.fromJson(Map<String, dynamic> json) =>
LocalizableStringInfo(
resourceName: json['resourceName'] as String,
name: json['name'] as String,
values: json['values'] as Map<String, dynamic>?,
);
Map<String, dynamic> toJson() => <String, dynamic>{
'resourceName': resourceName,
'name': name,
'values': values,
};
}

2
apps/flutter/core/lib/services/service.base.dart

@ -1,5 +1,5 @@
import 'package:get/get.dart';
abstract class ServiceBase extends GetxService {
T find<T>() => Get.find<T>();
T find<T>({ String? tag}) => Get.find<T>(tag: tag);
}

13
apps/flutter/core/lib/utils/localization.utils.dart

@ -1,4 +1,5 @@
import 'package:core/utils/string.extensions.dart';
import 'package:get/get.dart';
import '../proxy/volo/abp/asp-net-core/mvc/index.dart';
@ -64,4 +65,16 @@ class LocalizedText {
String? resourceName;
String? key;
String? localized;
}
extension AbpTranslationsExtensions on String {
String trFormat([Map<String, String> params = const {}]) {
var trans = tr;
if (params.isNotEmpty) {
params.forEach((key, value) {
trans = trans.replaceAll('{$key}', value);
});
}
return trans;
}
}

42
apps/flutter/dev_app/README.md

@ -14,3 +14,45 @@ A few resources to get you started if this is your first Flutter project:
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
## Environment
* **baseUrl**: 服务器连接地址(必输)
* **clientId**: 客户端标识(必输)
* **clientSecret**: 客户端密钥(可选)
* **authority**: 身份认证服务器地址(必输)
* **uploadFilesUrl**: 上传文件路径(可选)
* **staticFilesUrl**: 静态文件路径(可选)
* **tenantKey**: 多租户标识(可选)
* **defaultLanguage**: 应用程序默认语言, 优先级低于用户配置(可选)
* **notifications**: 通知相关设置(可选)
* ***android***: android端通知设置(可选)
* ***channelId***: 通道标识(配置了android节点后为必输)
* ***channelName***: 通道名称(配置了android节点后为必输)
* ***channelDescription***: 通道说明(可选)
* ***linux***: linux端通知设置(可选)
* ***defaultActionName***: 默认点击方法名称(配置了linux节点后为必输)
* ***darwin***: iOS/Mac os端通知设置(可选)
```json
{
"baseUrl": "http://127.0.0.1:30000",
"clientId": "abp-flutter",
"clientSecret": "1q2w3e*",
"authority": "http://127.0.0.1:30000",
"uploadFilesUrl": "",
"staticFilesUrl": "",
"tenantKey": "__tenant",
"defaultLanguage": "en",
"notifications": {
"android": {
"channelId": "abp-flutter",
"channelName": "abp-flutter",
"channelDescription": "适用于Android端的通知通道定义"
},
"linux": {
"defaultActionName": "Open notification"
}
}
}
```

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

@ -1,52 +1,65 @@
import 'package:core/services/notification.send.service.dart';
import 'package:get/get.dart';
import 'package:core/config/index.dart';
import 'package:core/services/config.state.service.dart';
import 'package:core/services/session.service.dart';
import 'package:core/services/signalr.service.dart';
import 'package:core/services/subscription.service.dart';
import 'package:core/tokens/index.dart';
import 'package:core/utils/index.dart';
import 'package:notifications/models/notification.dart';
import 'package:notifications/models/index.dart';
class MainController extends GetxController {
final RxInt _pageIndex = RxInt(0);
int get currentIndex => _pageIndex.value;
SessionService get sessionService => Get.find();
ConfigStateService get configStateService => Get.find();
SubscriptionService get subscriptionService => Get.find(tag: NotificationTokens.consumer);
SignalrService get signalrService => Get.find(tag: NotificationTokens.producer);
SessionService get _sessionService => Get.find();
SubscriptionService get _subscriptionService => Get.find(tag: NotificationTokens.consumer);
SignalrService get _signalrService => Get.find(tag: NotificationTokens.producer);
NotificationSendService get _notificationSendService => Get.find();
@override
void onInit() async {
super.onInit();
subscriptionService.addOne(signalrService.onClose(logger.debug));
subscriptionService.addOne(signalrService.onReconnected(logger.debug));
subscriptionService.addOne(signalrService.onReconnecting(logger.debug));
subscriptionService.subscribe(
signalrService.subscribe(NotificationTokens.receiver),
(message) {
var notification = NotificationInfo.fromJson(message.data.first as dynamic);
logger.debug(notification);
_subscriptionService.addOne(_signalrService.onClose(logger.debug));
_subscriptionService.addOne(_signalrService.onReconnected(logger.debug));
_subscriptionService.addOne(_signalrService.onReconnecting(logger.debug));
// SignalR Hub之上再次订阅
_subscriptionService.subscribe(
// SignalR Hub
_signalrService.subscribe(NotificationTokens.receiver),
(message) async {
for (var data in message.data) {
if (data == null) continue;
//
var notification = NotificationInfo.fromJson(data as dynamic);
//
var payload = NotificationPaylod.fromData(notification.data);
//
await _notificationSendService.send(
payload.title,
payload.body,
payload.payload,
);
}
},
);
sessionService.getToken$()
_sessionService.getToken$()
.listen((token) async {
if (token == null) {
await signalrService.stop();
await _signalrService.stop();
} else {
await signalrService.start();
await _signalrService.start();
}
});
if (sessionService.currentLanguage.isNullOrWhiteSpace()) {
sessionService.setLanguage(Environment.current.defaultLanguage ?? 'en');
if (_sessionService.currentLanguage.isNullOrWhiteSpace()) {
_sessionService.setLanguage(Environment.current.defaultLanguage ?? 'en');
}
}
@override
void onClose() {
subscriptionService.closeAll()
.whenComplete(() => signalrService.stop());
_subscriptionService.closeAll()
.whenComplete(() => _signalrService.stop());
super.onClose();
}

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

@ -1,4 +1,5 @@
import 'dart:async';
import 'package:core/config/index.dart';
import 'package:get/get.dart';
import 'package:rxdart/rxdart.dart' hide Notification;
@ -11,11 +12,12 @@ class FlutterLocalNotificationsSendService extends NotificationSendService {
final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
final Subject<Notification> _notifications$ = BehaviorSubject<Notification>();
final Subject<String?> _selectedNotifications$ = BehaviorSubject<String?>();
final EnvConfig _env = Environment.current;
Future<void> initAsync() async {
const initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/logo');
const initializationSettingsLinux = LinuxInitializationSettings(
defaultActionName: 'Open notification',
var initializationSettingsLinux = LinuxInitializationSettings(
defaultActionName: _env.notifications?.linux?.defaultActionName ?? 'Open notification',
);
var initializationSettingsDarwin = DarwinInitializationSettings(
onDidReceiveLocalNotification: (id, title, body, payload) {
@ -46,17 +48,28 @@ class FlutterLocalNotificationsSendService extends NotificationSendService {
@override
Future<void> send(String title, [String? body, String? payload]) async {
nid.value += 1;
const androidDetails = AndroidNotificationDetails(
'abp-flutter',
'abp-flutter');
const details = NotificationDetails(
await _flutterLocalNotificationsPlugin.show(
nid.value, title, body, _buildDetails(), payload: payload);
}
NotificationDetails _buildDetails() {
var androidDetails = AndroidNotificationDetails(
_env.notifications?.android?.channelId ?? 'abp-flutter',
_env.notifications?.android?.channelName ?? 'abp-flutter',
channelDescription: _env.notifications?.android?.channelDescription);
const darwinDetails = DarwinNotificationDetails();
const linuxDetails = LinuxNotificationDetails();
var details = NotificationDetails(
android: androidDetails,
iOS: darwinDetails,
macOS: darwinDetails,
linux: linuxDetails,
);
await _flutterLocalNotificationsPlugin.show(
nid.value,
title,
body,
details,
payload: payload);
return details;
}
}

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

@ -6,5 +6,15 @@
"uploadFilesUrl": "",
"staticFilesUrl": "",
"tenantKey": "__tenant",
"defaultLanguage": "en"
"defaultLanguage": "en",
"notifications": {
"android": {
"channelId": "abp-flutter",
"channelName": "abp-flutter",
"channelDescription": "适用于Android端的通知通道定义"
},
"linux": {
"defaultActionName": "Open notification"
}
}
}

36
apps/flutter/notifications/lib/models/common.dart

@ -0,0 +1,36 @@
import 'dart:convert';
import 'package:core/models/abp.dto.dart';
import 'package:core/utils/localization.utils.dart';
import 'notification.dart';
class NotificationPaylod {
NotificationPaylod({
this.id,
required this.title,
required this.body,
this.payload,
});
int? id;
String title;
String body;
String? payload;
factory NotificationPaylod.fromData(NotificationData data) {
if (data.extraProperties['L'] == true) {
var title = LocalizableStringInfo.fromJson(data.extraProperties['title']);
var message = LocalizableStringInfo.fromJson(data.extraProperties['message']);
return NotificationPaylod(
title: title.name.trFormat(title.values?.map((key, value) => MapEntry(key, value?.toString() ?? '')) ?? {}),
body: message.name.trFormat(message.values?.map((key, value) => MapEntry(key, value?.toString() ?? '')) ?? {}),
payload: jsonEncode(data.extraProperties),
);
}
return NotificationPaylod(
title: data.extraProperties['title'] as String,
body: data.extraProperties['message'] as String,
payload: jsonEncode(data.extraProperties),
);
}
}

3
apps/flutter/notifications/lib/models/index.dart

@ -0,0 +1,3 @@
export 'common.dart';
export 'notification.dart';
export 'notification.state.dart';

31
apps/flutter/notifications/lib/pages/notifier/state.dart → apps/flutter/notifications/lib/models/notification.state.dart

@ -1,21 +1,37 @@
import 'package:get/get.dart';
import 'package:json_annotation/json_annotation.dart';
import '../../models/notification.dart';
import 'notification.dart';
class NotifierManageState {
NotifierManageState({
part 'notification.state.g.dart';
@JsonSerializable()
class NotificationState {
NotificationState({
required this.isEnabled,
required this.groups,
});
bool isEnabled;
List<NotificationGroup> groups;
NotificationGroup? find(String name) {
NotificationGroup? findGroup(String name) {
return groups.firstWhereOrNull((item) => item.name == name);
}
Notification? findNotification(String name) {
for (var group in groups) {
var find = group.find(name);
if (find != null) return find;
}
return null;
}
factory NotificationState.fromJson(Map<String, dynamic> json) => _$NotificationStateFromJson(json);
Map<String, dynamic> toJson() => _$NotificationStateToJson(this);
}
@JsonSerializable()
class NotificationGroup {
NotificationGroup({
required this.name,
@ -29,8 +45,12 @@ class NotificationGroup {
Notification? find(String name) {
return notifications.firstWhereOrNull((item) => item.name == name);
}
factory NotificationGroup.fromJson(Map<String, dynamic> json) => _$NotificationGroupFromJson(json);
Map<String, dynamic> toJson() => _$NotificationGroupToJson(this);
}
@JsonSerializable()
class Notification {
Notification({
required this.name,
@ -50,4 +70,7 @@ class Notification {
NotificationLifetime lifetime;
NotificationType type;
NotificationContentType contentType;
factory Notification.fromJson(Map<String, dynamic> json) => _$NotificationFromJson(json);
Map<String, dynamic> toJson() => _$NotificationToJson(this);
}

80
apps/flutter/notifications/lib/models/notification.state.g.dart

@ -0,0 +1,80 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'notification.state.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
NotificationState _$NotificationStateFromJson(Map<String, dynamic> json) =>
NotificationState(
isEnabled: json['isEnabled'] as bool,
groups: (json['groups'] as List<dynamic>)
.map((e) => NotificationGroup.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$NotificationStateToJson(NotificationState instance) =>
<String, dynamic>{
'isEnabled': instance.isEnabled,
'groups': instance.groups,
};
NotificationGroup _$NotificationGroupFromJson(Map<String, dynamic> json) =>
NotificationGroup(
name: json['name'] as String,
displayName: json['displayName'] as String,
notifications: (json['notifications'] as List<dynamic>)
.map((e) => Notification.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$NotificationGroupToJson(NotificationGroup instance) =>
<String, dynamic>{
'name': instance.name,
'displayName': instance.displayName,
'notifications': instance.notifications,
};
Notification _$NotificationFromJson(Map<String, dynamic> json) => Notification(
name: json['name'] as String,
groupName: json['groupName'] as String,
displayName: json['displayName'] as String,
isSubscribed: json['isSubscribed'] as bool,
description: json['description'] as String?,
lifetime: $enumDecode(_$NotificationLifetimeEnumMap, json['lifetime']),
type: $enumDecode(_$NotificationTypeEnumMap, json['type']),
contentType:
$enumDecode(_$NotificationContentTypeEnumMap, json['contentType']),
);
Map<String, dynamic> _$NotificationToJson(Notification instance) =>
<String, dynamic>{
'name': instance.name,
'groupName': instance.groupName,
'displayName': instance.displayName,
'isSubscribed': instance.isSubscribed,
'description': instance.description,
'lifetime': _$NotificationLifetimeEnumMap[instance.lifetime]!,
'type': _$NotificationTypeEnumMap[instance.type]!,
'contentType': _$NotificationContentTypeEnumMap[instance.contentType]!,
};
const _$NotificationLifetimeEnumMap = {
NotificationLifetime.persistent: 0,
NotificationLifetime.onlyOne: 1,
};
const _$NotificationTypeEnumMap = {
NotificationType.application: 0,
NotificationType.system: 10,
NotificationType.user: 20,
NotificationType.serviceCallback: 30,
};
const _$NotificationContentTypeEnumMap = {
NotificationContentType.text: 0,
NotificationContentType.html: 1,
NotificationContentType.markdown: 2,
NotificationContentType.json: 3,
};

1
apps/flutter/notifications/lib/notifications.module.dart

@ -12,5 +12,6 @@ class NotificationsModule extends Module {
void configureServices() {
inject<NotificationsModule>(this);
lazyInject(() => NotificationService(), fenix: true);
lazyInject(() => NotificationStateService(), fenix: true);
}
}

81
apps/flutter/notifications/lib/pages/notifier/controller.dart

@ -1,86 +1,37 @@
import 'package:core/services/index.dart';
import 'package:get/get.dart';
import '../../models/index.dart';
import '../../services/index.dart';
import '../../tokens/index.dart';
import './state.dart';
class NotifierManageController extends GetxController {
NotificationService get notificationService => Get.find();
SignalrService get signalrService => Get.find(tag: NotificationTokens.producer);
SessionService get sessionService => Get.find();
NotificationStateService get stateService => Get.find();
final Rx<NotifierManageState> _state = Rx<NotifierManageState>(NotifierManageState(
final Rx<NotificationState> _state = Rx<NotificationState>(NotificationState(
isEnabled: true,
groups: []));
NotifierManageState get state => _state.value;
void _initNotifierConfig() async {
if (!sessionService.isAuthenticated) return;
var notifiers = await notificationService.getAssignableNotifiersAsync();
var subscres = await notificationService.getMySubscribedListAsync();
List<NotificationGroup> groups = [];
for (var notifierGroup in notifiers.items) {
if (notifierGroup.notifications == null && notifierGroup.notifications?.isEmpty == true) {
continue;
}
List<Notification> notifications = [];
for (var notifier in notifierGroup.notifications!) {
notifications.add(Notification(
name: notifier.name,
groupName: notifierGroup.name,
displayName: notifier.displayName ?? notifier.name,
description: notifier.description,
type: notifier.type,
contentType: notifier.contentType,
lifetime: notifier.lifetime,
isSubscribed: subscres.items.any((item) => item.name == notifier.name),
));
}
groups.add(NotificationGroup(
name: notifierGroup.name,
displayName: notifierGroup.displayName ?? notifierGroup.name,
notifications: notifications,
));
}
_state.update((val) {
val!.groups = groups;
});
NotificationState get state => _state.value;
void _updateState() async {
_state.value = stateService.state;
stateService.getNotificationState$()
.listen((state$) {
_state.update((val) {
val = state$;
});
});
}
void onSubscribed(Notification notification, bool isSubscribe) async {
if (!isSubscribe) {
await notificationService.unSubscribe(notification.name);
} else {
await notificationService.subscribe(notification.name);
}
_state.update((val) {
var group = val!.find(notification.groupName);
if (group == null) return;
var findNotification = group.find(notification.name);
if (findNotification == null) return;
findNotification.isSubscribed = isSubscribe;
});
await stateService.subscribe(notification, isSubscribe);
}
void onNotificationEnabled(bool isEnabled) {
if (!isEnabled) {
signalrService.unsubscribe(NotificationTokens.receiver);
} else {
signalrService.subscribe(NotificationTokens.receiver);
}
_state.update((val) {
val!.isEnabled = isEnabled;
});
stateService.subscribeAll(isEnabled);
}
@override
void onInit() {
super.onInit();
_initNotifierConfig();
_updateState();
}
}

2
apps/flutter/notifications/lib/pages/notifier/widget/notifier_card.dart

@ -1,6 +1,6 @@
import 'package:flutter/material.dart' hide Notification;
import '../state.dart';
import '../../../models/index.dart';
class NotifierCard extends StatelessWidget {
const NotifierCard({

3
apps/flutter/notifications/lib/services/index.dart

@ -1 +1,2 @@
export 'notification.service.dart';
export 'notification.service.dart';
export 'notification.state.service.dart';

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

@ -0,0 +1,124 @@
import 'dart:convert';
import 'package:core/services/session.service.dart';
import 'package:core/services/service.base.dart';
import 'package:core/services/signalr.service.dart';
import 'package:core/services/storage.service.dart';
import 'package:core/utils/internal.store.dart';
import 'package:notifications/models/notification.state.dart';
import '../tokens/notifications.token.dart';
import 'notification.service.dart';
class NotificationStateService extends ServiceBase {
static const String configKey = '_abp_notification_';
SessionService get _sessionService => find();
NotificationService get _notificationService => find();
StorageService get _storageService => find();
SignalrService get _signalrService => find(tag: NotificationTokens.producer);
final InternalStore<NotificationState> _store = InternalStore<NotificationState>(
state: _initState()
);
NotificationState get state => _store.state;
void subscribeAll(bool isEnabled) {
if (isEnabled) {
_signalrService.subscribe(NotificationTokens.receiver);
} else {
_signalrService.unsubscribe(NotificationTokens.receiver);
}
_store.patch((val) {
val.isEnabled = isEnabled;
});
}
Stream<NotificationState> getNotificationState$() {
return _store.sliceUpdate((state) => state);
}
NotificationGroup? findGroup(String name) {
return _store.state.findGroup(name);
}
Notification? findNotification(String name) {
return _store.state.findNotification(name);
}
Future<void> subscribe(Notification notification, bool isSubscribe) async {
if (isSubscribe) {
await _notificationService.subscribe(notification.name);
} else {
await _notificationService.unSubscribe(notification.name);
}
_changeSubscribedState(notification, isSubscribe);
}
@override
void onInit() {
super.onInit();
_sessionService.getProfile$()
.listen((profile) async {
if (_sessionService.isAuthenticated) {
await _refreshState();
}
});
var notification$ = _store.sliceUpdate((state) => state);
notification$.listen((notification) {
_storageService.setItem(configKey, jsonEncode(notification.toJson()));
});
}
static NotificationState _initState() {
var configState = StorageService.initStorage(configKey,
(value) => NotificationState.fromJson(jsonDecode(value)));
return configState ?? NotificationState(isEnabled: true, groups: []);
}
Future<void> _refreshState() async {
var notifiers = await _notificationService.getAssignableNotifiersAsync();
var subscres = await _notificationService.getMySubscribedListAsync();
List<NotificationGroup> groups = [];
for (var notifierGroup in notifiers.items) {
if (notifierGroup.notifications == null && notifierGroup.notifications?.isEmpty == true) {
continue;
}
List<Notification> notifications = [];
for (var notifier in notifierGroup.notifications!) {
notifications.add(Notification(
name: notifier.name,
groupName: notifierGroup.name,
displayName: notifier.displayName ?? notifier.name,
description: notifier.description,
type: notifier.type,
contentType: notifier.contentType,
lifetime: notifier.lifetime,
isSubscribed: subscres.items.any((item) => item.name == notifier.name),
));
}
groups.add(NotificationGroup(
name: notifierGroup.name,
displayName: notifierGroup.displayName ?? notifierGroup.name,
notifications: notifications,
));
}
_store.patch((state) {
state.groups = groups;
});
}
void _changeSubscribedState(Notification notification, bool isSubscribe) {
_store.patch((val) {
var group = val.findGroup(notification.groupName);
if (group == null) return;
var findNotification = group.find(notification.name);
if (findNotification == null) return;
findNotification.isSubscribed = true;
});
}
}
Loading…
Cancel
Save