committed by
GitHub
18 changed files with 503 additions and 109 deletions
@ -1,5 +1,5 @@ |
|||||
import 'package:get/get.dart'; |
import 'package:get/get.dart'; |
||||
|
|
||||
abstract class ServiceBase extends GetxService { |
abstract class ServiceBase extends GetxService { |
||||
T find<T>() => Get.find<T>(); |
T find<T>({ String? tag}) => Get.find<T>(tag: tag); |
||||
} |
} |
||||
@ -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), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
export 'common.dart'; |
||||
|
export 'notification.dart'; |
||||
|
export 'notification.state.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,86 +1,37 @@ |
|||||
import 'package:core/services/index.dart'; |
|
||||
import 'package:get/get.dart'; |
import 'package:get/get.dart'; |
||||
|
|
||||
|
import '../../models/index.dart'; |
||||
import '../../services/index.dart'; |
import '../../services/index.dart'; |
||||
import '../../tokens/index.dart'; |
|
||||
import './state.dart'; |
|
||||
|
|
||||
class NotifierManageController extends GetxController { |
class NotifierManageController extends GetxController { |
||||
NotificationService get notificationService => Get.find(); |
NotificationStateService get stateService => Get.find(); |
||||
SignalrService get signalrService => Get.find(tag: NotificationTokens.producer); |
|
||||
SessionService get sessionService => Get.find(); |
|
||||
|
|
||||
final Rx<NotifierManageState> _state = Rx<NotifierManageState>(NotifierManageState( |
final Rx<NotificationState> _state = Rx<NotificationState>(NotificationState( |
||||
isEnabled: true, |
isEnabled: true, |
||||
groups: [])); |
groups: [])); |
||||
NotifierManageState get state => _state.value; |
NotificationState get state => _state.value; |
||||
|
|
||||
void _initNotifierConfig() async { |
void _updateState() async { |
||||
if (!sessionService.isAuthenticated) return; |
_state.value = stateService.state; |
||||
var notifiers = await notificationService.getAssignableNotifiersAsync(); |
stateService.getNotificationState$() |
||||
var subscres = await notificationService.getMySubscribedListAsync(); |
.listen((state$) { |
||||
|
_state.update((val) { |
||||
List<NotificationGroup> groups = []; |
val = state$; |
||||
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; |
|
||||
}); |
|
||||
} |
} |
||||
|
|
||||
void onSubscribed(Notification notification, bool isSubscribe) async { |
void onSubscribed(Notification notification, bool isSubscribe) async { |
||||
if (!isSubscribe) { |
await stateService.subscribe(notification, 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; |
|
||||
}); |
|
||||
} |
} |
||||
|
|
||||
void onNotificationEnabled(bool isEnabled) { |
void onNotificationEnabled(bool isEnabled) { |
||||
if (!isEnabled) { |
stateService.subscribeAll(isEnabled); |
||||
signalrService.unsubscribe(NotificationTokens.receiver); |
|
||||
} else { |
|
||||
signalrService.subscribe(NotificationTokens.receiver); |
|
||||
} |
|
||||
_state.update((val) { |
|
||||
val!.isEnabled = isEnabled; |
|
||||
}); |
|
||||
} |
} |
||||
|
|
||||
@override |
@override |
||||
void onInit() { |
void onInit() { |
||||
super.onInit(); |
super.onInit(); |
||||
_initNotifierConfig(); |
_updateState(); |
||||
} |
} |
||||
} |
} |
||||
@ -1 +1,2 @@ |
|||||
export 'notification.service.dart'; |
export 'notification.service.dart'; |
||||
|
export '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…
Reference in new issue