✨ Notification screen
This commit is contained in:
parent
63499df99f
commit
85a1dd3053
@ -22,6 +22,7 @@
|
||||
"screenRealm": "Realm",
|
||||
"screenRealmManage": "Edit Realm",
|
||||
"screenRealmNew": "New Realm",
|
||||
"screenNotification": "Notification",
|
||||
"dialogOkay": "Okay",
|
||||
"dialogCancel": "Cancel",
|
||||
"dialogConfirm": "Confirm",
|
||||
@ -174,5 +175,15 @@
|
||||
},
|
||||
"addAttachmentFromAlbum": "Add from album",
|
||||
"addAttachmentFromClipboard": "Paste file",
|
||||
"attachmentPastedImage": "Pasted Image"
|
||||
"attachmentPastedImage": "Pasted Image",
|
||||
"notificationUnread": "未读",
|
||||
"notificationRead": "已读",
|
||||
"notificationMarkAllRead": "Mark all notifications as read",
|
||||
"notificationMarkAllReadDescription": "Are you sure you want to mark all notifications as read? This operation is irreversible.",
|
||||
"notificationMarkAllReadPrompt": {
|
||||
"zero": "Marked 0 notification as read.",
|
||||
"one": "Marked {} notification as read.",
|
||||
"other": "Marked {} notifications as read."
|
||||
},
|
||||
"notificationMarkOneReadPrompt": "Marked notification {} as read."
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
"screenRealm": "领域",
|
||||
"screenRealmManage": "编辑领域",
|
||||
"screenRealmNew": "新建领域",
|
||||
"screenNotification": "通知",
|
||||
"dialogOkay": "好的",
|
||||
"dialogCancel": "取消",
|
||||
"dialogConfirm": "确认",
|
||||
@ -174,5 +175,15 @@
|
||||
},
|
||||
"addAttachmentFromAlbum": "从相册中添加附件",
|
||||
"addAttachmentFromClipboard": "粘贴附件",
|
||||
"attachmentPastedImage" : "粘贴的图片"
|
||||
"attachmentPastedImage" : "粘贴的图片",
|
||||
"notificationUnread": "未读",
|
||||
"notificationRead": "已读",
|
||||
"notificationMarkAllRead": "已读所有通知",
|
||||
"notificationMarkAllReadDescription": "您确定要将所有通知设置为已读吗?该操作不可撤销。",
|
||||
"notificationMarkAllReadPrompt": {
|
||||
"zero": "已将 0 个通知标记为已读。",
|
||||
"one": "已将 {} 个通知标记为已读。",
|
||||
"other": "已将 {} 个通知标记为已读。"
|
||||
},
|
||||
"notificationMarkOneReadPrompt": "已将通知 {} 标记为已读。"
|
||||
}
|
||||
|
@ -63,6 +63,11 @@ class NavigationProvider extends ChangeNotifier {
|
||||
screen: 'album',
|
||||
label: 'screenAlbum',
|
||||
),
|
||||
AppNavDestination(
|
||||
icon: Icon(Symbols.notifications, weight: 400, opticalSize: 20),
|
||||
screen: 'notification',
|
||||
label: 'screenNotification',
|
||||
),
|
||||
];
|
||||
static const List<String> kDefaultPinnedDestination = [
|
||||
'home',
|
||||
|
@ -14,6 +14,7 @@ import 'package:surface/screens/chat/manage.dart';
|
||||
import 'package:surface/screens/chat/room.dart';
|
||||
import 'package:surface/screens/explore.dart';
|
||||
import 'package:surface/screens/home.dart';
|
||||
import 'package:surface/screens/notification.dart';
|
||||
import 'package:surface/screens/post/post_detail.dart';
|
||||
import 'package:surface/screens/post/post_editor.dart';
|
||||
import 'package:surface/screens/realm.dart';
|
||||
@ -175,6 +176,13 @@ final _appRoutes = [
|
||||
child: const AlbumScreen(),
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/notification',
|
||||
name: 'notification',
|
||||
pageBuilder: (context, state) => NoTransitionPage(
|
||||
child: const NotificationScreen(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
ShellRoute(
|
||||
|
244
lib/screens/notification.dart
Normal file
244
lib/screens/notification.dart
Normal file
@ -0,0 +1,244 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:relative_time/relative_time.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
import 'package:surface/providers/sn_network.dart';
|
||||
import 'package:surface/types/notification.dart';
|
||||
import 'package:surface/types/post.dart';
|
||||
import 'package:surface/widgets/dialog.dart';
|
||||
import 'package:surface/widgets/loading_indicator.dart';
|
||||
import 'package:surface/widgets/markdown_content.dart';
|
||||
import 'package:surface/widgets/post/post_item.dart';
|
||||
import 'package:very_good_infinite_list/very_good_infinite_list.dart';
|
||||
|
||||
class NotificationScreen extends StatefulWidget {
|
||||
const NotificationScreen({super.key});
|
||||
|
||||
@override
|
||||
State<NotificationScreen> createState() => _NotificationScreenState();
|
||||
}
|
||||
|
||||
class _NotificationScreenState extends State<NotificationScreen> {
|
||||
bool _isBusy = false;
|
||||
bool _isFirstLoading = true;
|
||||
bool _isSubmitting = false;
|
||||
|
||||
final List<SnNotification> _notifications = List.empty(growable: true);
|
||||
int? _totalCount;
|
||||
|
||||
static const Map<String, IconData> kNotificationTopicIcons = {
|
||||
'passport.security.alert': Symbols.gpp_maybe,
|
||||
'interactive.subscription': Symbols.subscriptions,
|
||||
'interactive.feedback': Symbols.add_reaction,
|
||||
'messaging.callStart': Symbols.call_received,
|
||||
};
|
||||
|
||||
Future<void> _fetchNotifications() async {
|
||||
setState(() => _isBusy = true);
|
||||
|
||||
try {
|
||||
final sn = context.read<SnNetworkProvider>();
|
||||
final resp = await sn.client.get('/cgi/id/notifications?take=10');
|
||||
_totalCount = resp.data['count'];
|
||||
_notifications.addAll(
|
||||
resp.data['data']
|
||||
?.map((e) => SnNotification.fromJson(e))
|
||||
.cast<SnNotification>() ??
|
||||
[],
|
||||
);
|
||||
} catch (err) {
|
||||
if (!mounted) return;
|
||||
context.showErrorDialog(err);
|
||||
} finally {
|
||||
_isFirstLoading = false;
|
||||
setState(() => _isBusy = false);
|
||||
}
|
||||
}
|
||||
|
||||
void _markAllAsRead() async {
|
||||
if (_notifications.isEmpty) return;
|
||||
|
||||
final confirm = await context.showConfirmDialog(
|
||||
'notificationMarkAllRead'.tr(),
|
||||
'notificationMarkAllReadDescription'.tr(),
|
||||
);
|
||||
if (!confirm) return;
|
||||
|
||||
if (!mounted) return;
|
||||
setState(() => _isSubmitting = true);
|
||||
|
||||
List<int> markList = List.empty(growable: true);
|
||||
for (final element in _notifications) {
|
||||
if (element.id <= 0) continue;
|
||||
if (element.readAt != null) continue;
|
||||
markList.add(element.id);
|
||||
}
|
||||
|
||||
try {
|
||||
final sn = context.read<SnNetworkProvider>();
|
||||
await sn.client.put('/cgi/id/notifications/read', data: {
|
||||
'messages': markList,
|
||||
});
|
||||
_notifications.clear();
|
||||
_fetchNotifications();
|
||||
|
||||
if (!mounted) return;
|
||||
context.showSnackbar(
|
||||
'notificationMarkAllReadPrompt'.plural(markList.length),
|
||||
);
|
||||
} catch (err) {
|
||||
if (!mounted) return;
|
||||
context.showErrorDialog(err);
|
||||
} finally {
|
||||
setState(() => _isSubmitting = false);
|
||||
}
|
||||
}
|
||||
|
||||
void _markOneAsRead(SnNotification notification) async {
|
||||
if (notification.readAt != null) return;
|
||||
|
||||
setState(() => _isSubmitting = true);
|
||||
|
||||
try {
|
||||
final sn = context.read<SnNetworkProvider>();
|
||||
await sn.client.put('/cgi/id/notifications/read/${notification.id}');
|
||||
_notifications.clear();
|
||||
_fetchNotifications();
|
||||
|
||||
if (!mounted) return;
|
||||
context.showSnackbar(
|
||||
'notificationMarkOneReadPrompt'.tr(args: ['#${notification.id}']),
|
||||
);
|
||||
} catch (err) {
|
||||
if (!mounted) return;
|
||||
context.showErrorDialog(err);
|
||||
} finally {
|
||||
setState(() => _isSubmitting = false);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_fetchNotifications();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('screenNotification').tr(),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.checklist),
|
||||
onPressed: _isSubmitting ? null : _markAllAsRead,
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
LoadingIndicator(isActive: _isFirstLoading),
|
||||
Expanded(
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () {
|
||||
_notifications.clear();
|
||||
return _fetchNotifications();
|
||||
},
|
||||
child: InfiniteList(
|
||||
padding: EdgeInsets.only(
|
||||
top: 16,
|
||||
bottom: math.max(MediaQuery.of(context).padding.bottom, 16),
|
||||
),
|
||||
itemCount: _notifications.length,
|
||||
onFetchData: () {
|
||||
_fetchNotifications();
|
||||
},
|
||||
isLoading: _isBusy,
|
||||
hasReachedMax: _totalCount != null &&
|
||||
_notifications.length >= _totalCount!,
|
||||
itemBuilder: (context, idx) {
|
||||
final nty = _notifications[idx];
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Icon(kNotificationTopicIcons[nty.topic]),
|
||||
const Gap(16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (nty.readAt == null)
|
||||
StyledWidget(Badge(
|
||||
label: Text('notificationUnread').tr(),
|
||||
)).padding(bottom: 4),
|
||||
Text(
|
||||
nty.title,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
if (nty.subtitle != null)
|
||||
Text(
|
||||
nty.subtitle!,
|
||||
style: Theme.of(context).textTheme.titleSmall,
|
||||
),
|
||||
if (nty.subtitle != null) const Gap(4),
|
||||
MarkdownTextContent(
|
||||
content: nty.body,
|
||||
isAutoWarp: true,
|
||||
isSelectable: true,
|
||||
),
|
||||
if ([
|
||||
'interactive.feedback',
|
||||
'interactive.subscription'
|
||||
].contains(nty.topic) &&
|
||||
nty.metadata['related_post'] != null)
|
||||
PostItem(
|
||||
data: SnPost.fromJson(
|
||||
nty.metadata['related_post']!,
|
||||
),
|
||||
),
|
||||
const Gap(8),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
DateFormat('yy/MM/dd').format(nty.createdAt),
|
||||
).fontSize(12),
|
||||
const Gap(4),
|
||||
Text(
|
||||
'·',
|
||||
style: TextStyle(fontSize: 12),
|
||||
),
|
||||
const Gap(4),
|
||||
Text(
|
||||
RelativeTime(context).format(nty.createdAt),
|
||||
).fontSize(12),
|
||||
],
|
||||
).opacity(0.75),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Gap(16),
|
||||
IconButton(
|
||||
icon: const Icon(Symbols.check),
|
||||
padding: EdgeInsets.all(0),
|
||||
visualDensity:
|
||||
const VisualDensity(horizontal: -4, vertical: -4),
|
||||
onPressed:
|
||||
_isSubmitting ? null : () => _markOneAsRead(nty),
|
||||
),
|
||||
],
|
||||
).padding(horizontal: 16);
|
||||
},
|
||||
separatorBuilder: (_, __) => const Divider(),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
26
lib/types/notification.dart
Normal file
26
lib/types/notification.dart
Normal file
@ -0,0 +1,26 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'notification.freezed.dart';
|
||||
part 'notification.g.dart';
|
||||
|
||||
@freezed
|
||||
class SnNotification with _$SnNotification {
|
||||
const factory SnNotification({
|
||||
required int id,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
required DateTime? deletedAt,
|
||||
required String topic,
|
||||
required String title,
|
||||
required String? subtitle,
|
||||
required String body,
|
||||
@Default({}) Map<String, dynamic> metadata,
|
||||
required int priority,
|
||||
required int? senderId,
|
||||
required int accountId,
|
||||
required DateTime? readAt,
|
||||
}) = _SnNotification;
|
||||
|
||||
factory SnNotification.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnNotificationFromJson(json);
|
||||
}
|
438
lib/types/notification.freezed.dart
Normal file
438
lib/types/notification.freezed.dart
Normal file
@ -0,0 +1,438 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'notification.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
SnNotification _$SnNotificationFromJson(Map<String, dynamic> json) {
|
||||
return _SnNotification.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SnNotification {
|
||||
int get id => throw _privateConstructorUsedError;
|
||||
DateTime get createdAt => throw _privateConstructorUsedError;
|
||||
DateTime get updatedAt => throw _privateConstructorUsedError;
|
||||
DateTime? get deletedAt => throw _privateConstructorUsedError;
|
||||
String get topic => throw _privateConstructorUsedError;
|
||||
String get title => throw _privateConstructorUsedError;
|
||||
String? get subtitle => throw _privateConstructorUsedError;
|
||||
String get body => throw _privateConstructorUsedError;
|
||||
Map<String, dynamic> get metadata => throw _privateConstructorUsedError;
|
||||
int get priority => throw _privateConstructorUsedError;
|
||||
int? get senderId => throw _privateConstructorUsedError;
|
||||
int get accountId => throw _privateConstructorUsedError;
|
||||
DateTime? get readAt => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this SnNotification to a JSON map.
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of SnNotification
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$SnNotificationCopyWith<SnNotification> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $SnNotificationCopyWith<$Res> {
|
||||
factory $SnNotificationCopyWith(
|
||||
SnNotification value, $Res Function(SnNotification) then) =
|
||||
_$SnNotificationCopyWithImpl<$Res, SnNotification>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{int id,
|
||||
DateTime createdAt,
|
||||
DateTime updatedAt,
|
||||
DateTime? deletedAt,
|
||||
String topic,
|
||||
String title,
|
||||
String? subtitle,
|
||||
String body,
|
||||
Map<String, dynamic> metadata,
|
||||
int priority,
|
||||
int? senderId,
|
||||
int accountId,
|
||||
DateTime? readAt});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$SnNotificationCopyWithImpl<$Res, $Val extends SnNotification>
|
||||
implements $SnNotificationCopyWith<$Res> {
|
||||
_$SnNotificationCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of SnNotification
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? id = null,
|
||||
Object? createdAt = null,
|
||||
Object? updatedAt = null,
|
||||
Object? deletedAt = freezed,
|
||||
Object? topic = null,
|
||||
Object? title = null,
|
||||
Object? subtitle = freezed,
|
||||
Object? body = null,
|
||||
Object? metadata = null,
|
||||
Object? priority = null,
|
||||
Object? senderId = freezed,
|
||||
Object? accountId = null,
|
||||
Object? readAt = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
id: null == id
|
||||
? _value.id
|
||||
: id // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
createdAt: null == createdAt
|
||||
? _value.createdAt
|
||||
: createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
updatedAt: null == updatedAt
|
||||
? _value.updatedAt
|
||||
: updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
deletedAt: freezed == deletedAt
|
||||
? _value.deletedAt
|
||||
: deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
topic: null == topic
|
||||
? _value.topic
|
||||
: topic // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
title: null == title
|
||||
? _value.title
|
||||
: title // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
subtitle: freezed == subtitle
|
||||
? _value.subtitle
|
||||
: subtitle // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
body: null == body
|
||||
? _value.body
|
||||
: body // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
metadata: null == metadata
|
||||
? _value.metadata
|
||||
: metadata // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>,
|
||||
priority: null == priority
|
||||
? _value.priority
|
||||
: priority // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
senderId: freezed == senderId
|
||||
? _value.senderId
|
||||
: senderId // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
accountId: null == accountId
|
||||
? _value.accountId
|
||||
: accountId // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
readAt: freezed == readAt
|
||||
? _value.readAt
|
||||
: readAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$SnNotificationImplCopyWith<$Res>
|
||||
implements $SnNotificationCopyWith<$Res> {
|
||||
factory _$$SnNotificationImplCopyWith(_$SnNotificationImpl value,
|
||||
$Res Function(_$SnNotificationImpl) then) =
|
||||
__$$SnNotificationImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{int id,
|
||||
DateTime createdAt,
|
||||
DateTime updatedAt,
|
||||
DateTime? deletedAt,
|
||||
String topic,
|
||||
String title,
|
||||
String? subtitle,
|
||||
String body,
|
||||
Map<String, dynamic> metadata,
|
||||
int priority,
|
||||
int? senderId,
|
||||
int accountId,
|
||||
DateTime? readAt});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$SnNotificationImplCopyWithImpl<$Res>
|
||||
extends _$SnNotificationCopyWithImpl<$Res, _$SnNotificationImpl>
|
||||
implements _$$SnNotificationImplCopyWith<$Res> {
|
||||
__$$SnNotificationImplCopyWithImpl(
|
||||
_$SnNotificationImpl _value, $Res Function(_$SnNotificationImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of SnNotification
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? id = null,
|
||||
Object? createdAt = null,
|
||||
Object? updatedAt = null,
|
||||
Object? deletedAt = freezed,
|
||||
Object? topic = null,
|
||||
Object? title = null,
|
||||
Object? subtitle = freezed,
|
||||
Object? body = null,
|
||||
Object? metadata = null,
|
||||
Object? priority = null,
|
||||
Object? senderId = freezed,
|
||||
Object? accountId = null,
|
||||
Object? readAt = freezed,
|
||||
}) {
|
||||
return _then(_$SnNotificationImpl(
|
||||
id: null == id
|
||||
? _value.id
|
||||
: id // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
createdAt: null == createdAt
|
||||
? _value.createdAt
|
||||
: createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
updatedAt: null == updatedAt
|
||||
? _value.updatedAt
|
||||
: updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
deletedAt: freezed == deletedAt
|
||||
? _value.deletedAt
|
||||
: deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
topic: null == topic
|
||||
? _value.topic
|
||||
: topic // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
title: null == title
|
||||
? _value.title
|
||||
: title // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
subtitle: freezed == subtitle
|
||||
? _value.subtitle
|
||||
: subtitle // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
body: null == body
|
||||
? _value.body
|
||||
: body // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
metadata: null == metadata
|
||||
? _value._metadata
|
||||
: metadata // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>,
|
||||
priority: null == priority
|
||||
? _value.priority
|
||||
: priority // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
senderId: freezed == senderId
|
||||
? _value.senderId
|
||||
: senderId // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
accountId: null == accountId
|
||||
? _value.accountId
|
||||
: accountId // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
readAt: freezed == readAt
|
||||
? _value.readAt
|
||||
: readAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$SnNotificationImpl implements _SnNotification {
|
||||
const _$SnNotificationImpl(
|
||||
{required this.id,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
required this.deletedAt,
|
||||
required this.topic,
|
||||
required this.title,
|
||||
required this.subtitle,
|
||||
required this.body,
|
||||
final Map<String, dynamic> metadata = const {},
|
||||
required this.priority,
|
||||
required this.senderId,
|
||||
required this.accountId,
|
||||
required this.readAt})
|
||||
: _metadata = metadata;
|
||||
|
||||
factory _$SnNotificationImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$SnNotificationImplFromJson(json);
|
||||
|
||||
@override
|
||||
final int id;
|
||||
@override
|
||||
final DateTime createdAt;
|
||||
@override
|
||||
final DateTime updatedAt;
|
||||
@override
|
||||
final DateTime? deletedAt;
|
||||
@override
|
||||
final String topic;
|
||||
@override
|
||||
final String title;
|
||||
@override
|
||||
final String? subtitle;
|
||||
@override
|
||||
final String body;
|
||||
final Map<String, dynamic> _metadata;
|
||||
@override
|
||||
@JsonKey()
|
||||
Map<String, dynamic> get metadata {
|
||||
if (_metadata is EqualUnmodifiableMapView) return _metadata;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableMapView(_metadata);
|
||||
}
|
||||
|
||||
@override
|
||||
final int priority;
|
||||
@override
|
||||
final int? senderId;
|
||||
@override
|
||||
final int accountId;
|
||||
@override
|
||||
final DateTime? readAt;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnNotification(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, topic: $topic, title: $title, subtitle: $subtitle, body: $body, metadata: $metadata, priority: $priority, senderId: $senderId, accountId: $accountId, readAt: $readAt)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$SnNotificationImpl &&
|
||||
(identical(other.id, id) || other.id == id) &&
|
||||
(identical(other.createdAt, createdAt) ||
|
||||
other.createdAt == createdAt) &&
|
||||
(identical(other.updatedAt, updatedAt) ||
|
||||
other.updatedAt == updatedAt) &&
|
||||
(identical(other.deletedAt, deletedAt) ||
|
||||
other.deletedAt == deletedAt) &&
|
||||
(identical(other.topic, topic) || other.topic == topic) &&
|
||||
(identical(other.title, title) || other.title == title) &&
|
||||
(identical(other.subtitle, subtitle) ||
|
||||
other.subtitle == subtitle) &&
|
||||
(identical(other.body, body) || other.body == body) &&
|
||||
const DeepCollectionEquality().equals(other._metadata, _metadata) &&
|
||||
(identical(other.priority, priority) ||
|
||||
other.priority == priority) &&
|
||||
(identical(other.senderId, senderId) ||
|
||||
other.senderId == senderId) &&
|
||||
(identical(other.accountId, accountId) ||
|
||||
other.accountId == accountId) &&
|
||||
(identical(other.readAt, readAt) || other.readAt == readAt));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
id,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
deletedAt,
|
||||
topic,
|
||||
title,
|
||||
subtitle,
|
||||
body,
|
||||
const DeepCollectionEquality().hash(_metadata),
|
||||
priority,
|
||||
senderId,
|
||||
accountId,
|
||||
readAt);
|
||||
|
||||
/// Create a copy of SnNotification
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$SnNotificationImplCopyWith<_$SnNotificationImpl> get copyWith =>
|
||||
__$$SnNotificationImplCopyWithImpl<_$SnNotificationImpl>(
|
||||
this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$SnNotificationImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _SnNotification implements SnNotification {
|
||||
const factory _SnNotification(
|
||||
{required final int id,
|
||||
required final DateTime createdAt,
|
||||
required final DateTime updatedAt,
|
||||
required final DateTime? deletedAt,
|
||||
required final String topic,
|
||||
required final String title,
|
||||
required final String? subtitle,
|
||||
required final String body,
|
||||
final Map<String, dynamic> metadata,
|
||||
required final int priority,
|
||||
required final int? senderId,
|
||||
required final int accountId,
|
||||
required final DateTime? readAt}) = _$SnNotificationImpl;
|
||||
|
||||
factory _SnNotification.fromJson(Map<String, dynamic> json) =
|
||||
_$SnNotificationImpl.fromJson;
|
||||
|
||||
@override
|
||||
int get id;
|
||||
@override
|
||||
DateTime get createdAt;
|
||||
@override
|
||||
DateTime get updatedAt;
|
||||
@override
|
||||
DateTime? get deletedAt;
|
||||
@override
|
||||
String get topic;
|
||||
@override
|
||||
String get title;
|
||||
@override
|
||||
String? get subtitle;
|
||||
@override
|
||||
String get body;
|
||||
@override
|
||||
Map<String, dynamic> get metadata;
|
||||
@override
|
||||
int get priority;
|
||||
@override
|
||||
int? get senderId;
|
||||
@override
|
||||
int get accountId;
|
||||
@override
|
||||
DateTime? get readAt;
|
||||
|
||||
/// Create a copy of SnNotification
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$SnNotificationImplCopyWith<_$SnNotificationImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
46
lib/types/notification.g.dart
Normal file
46
lib/types/notification.g.dart
Normal file
@ -0,0 +1,46 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'notification.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$SnNotificationImpl _$$SnNotificationImplFromJson(Map<String, dynamic> json) =>
|
||||
_$SnNotificationImpl(
|
||||
id: (json['id'] as num).toInt(),
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
deletedAt: json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
topic: json['topic'] as String,
|
||||
title: json['title'] as String,
|
||||
subtitle: json['subtitle'] as String?,
|
||||
body: json['body'] as String,
|
||||
metadata: json['metadata'] as Map<String, dynamic>? ?? const {},
|
||||
priority: (json['priority'] as num).toInt(),
|
||||
senderId: (json['sender_id'] as num?)?.toInt(),
|
||||
accountId: (json['account_id'] as num).toInt(),
|
||||
readAt: json['read_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['read_at'] as String),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$SnNotificationImplToJson(
|
||||
_$SnNotificationImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
'topic': instance.topic,
|
||||
'title': instance.title,
|
||||
'subtitle': instance.subtitle,
|
||||
'body': instance.body,
|
||||
'metadata': instance.metadata,
|
||||
'priority': instance.priority,
|
||||
'sender_id': instance.senderId,
|
||||
'account_id': instance.accountId,
|
||||
'read_at': instance.readAt?.toIso8601String(),
|
||||
};
|
@ -29,7 +29,7 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
|
||||
Widget build(BuildContext context) {
|
||||
final nav = context.watch<NavigationProvider>();
|
||||
|
||||
final backgroundColor = ResponsiveBreakpoints.of(context).largerThan(MOBILE)
|
||||
final backgroundColor = ResponsiveBreakpoints.of(context).largerThan(TABLET)
|
||||
? Colors.transparent
|
||||
: null;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user