Prep flutter for android data-messages

This commit is contained in:
Mike Schwörer 2024-06-15 18:24:18 +02:00
parent c68a53e4cd
commit b0a6736f70
Signed by: Mikescher
GPG Key ID: D3C7172E0A70F8CF
4 changed files with 501 additions and 115 deletions

View File

@ -12,6 +12,7 @@ import 'package:simplecloudnotifier/nav_layout.dart';
import 'package:simplecloudnotifier/state/app_bar_state.dart'; import 'package:simplecloudnotifier/state/app_bar_state.dart';
import 'package:simplecloudnotifier/state/app_theme.dart'; import 'package:simplecloudnotifier/state/app_theme.dart';
import 'package:simplecloudnotifier/state/application_log.dart'; import 'package:simplecloudnotifier/state/application_log.dart';
import 'package:simplecloudnotifier/state/fb_message.dart';
import 'package:simplecloudnotifier/state/globals.dart'; import 'package:simplecloudnotifier/state/globals.dart';
import 'package:simplecloudnotifier/state/request_log.dart'; import 'package:simplecloudnotifier/state/request_log.dart';
import 'package:simplecloudnotifier/state/app_auth.dart'; import 'package:simplecloudnotifier/state/app_auth.dart';
@ -40,6 +41,7 @@ void main() async {
Hive.registerAdapter(SCNLogLevelAdapter()); Hive.registerAdapter(SCNLogLevelAdapter());
Hive.registerAdapter(MessageAdapter()); Hive.registerAdapter(MessageAdapter());
Hive.registerAdapter(ChannelAdapter()); Hive.registerAdapter(ChannelAdapter());
Hive.registerAdapter(FBMessageAdapter());
print('[INIT] Load Hive<scn-requests>...'); print('[INIT] Load Hive<scn-requests>...');
@ -81,6 +83,16 @@ void main() async {
ApplicationLog.error('Failed to open Hive-Box: scn-channel-cache' + exc.toString(), trace: trace); ApplicationLog.error('Failed to open Hive-Box: scn-channel-cache' + exc.toString(), trace: trace);
} }
print('[INIT] Load Hive<scn-fb-messages>...');
try {
await Hive.openBox<FBMessage>('scn-fb-messages');
} catch (exc, trace) {
Hive.deleteBoxFromDisk('scn-fb-messages');
await Hive.openBox<FBMessage>('scn-fb-messages');
ApplicationLog.error('Failed to open Hive-Box: scn-fb-messages' + exc.toString(), trace: trace);
}
print('[INIT] Load AppAuth...'); print('[INIT] Load AppAuth...');
final appAuth = AppAuth(); // ensure UserAccount is loaded final appAuth = AppAuth(); // ensure UserAccount is loaded
@ -128,6 +140,9 @@ void main() async {
} catch (exc, trace) { } catch (exc, trace) {
ApplicationLog.error('Failed to get+set firebase token: ' + exc.toString(), trace: trace); ApplicationLog.error('Failed to get+set firebase token: ' + exc.toString(), trace: trace);
} }
FirebaseMessaging.onBackgroundMessage(_onBackgroundMessage);
FirebaseMessaging.onMessage.listen(_onForegroundMessage);
} else { } else {
print('[INIT] Skip Firebase init (Platform == Linux)...'); print('[INIT] Skip Firebase init (Platform == Linux)...');
} }
@ -146,6 +161,33 @@ void main() async {
); );
} }
class SCNApp extends StatelessWidget {
SCNApp({super.key});
@override
Widget build(BuildContext context) {
return ToastificationWrapper(
config: ToastificationConfig(
itemWidth: 440,
marginBuilder: (alignment) => EdgeInsets.symmetric(vertical: 64),
animationDuration: Duration(milliseconds: 200),
),
child: Consumer<AppTheme>(
builder: (context, appTheme, child) => MaterialApp(
title: 'SimpleCloudNotifier',
navigatorObservers: [Navi.routeObserver, Navi.modalRouteObserver],
theme: ThemeData(
//TODO color settings
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue, brightness: appTheme.darkMode ? Brightness.dark : Brightness.light),
useMaterial3: true,
),
home: SCNNavLayout(),
),
),
);
}
}
void setFirebaseToken(String fcmToken) async { void setFirebaseToken(String fcmToken) async {
final acc = AppAuth(); final acc = AppAuth();
@ -182,29 +224,18 @@ void setFirebaseToken(String fcmToken) async {
} }
} }
class SCNApp extends StatelessWidget { Future<void> _onBackgroundMessage(RemoteMessage message) async {
SCNApp({super.key}); await _receiveMessage(message, false);
}
@override void _onForegroundMessage(RemoteMessage message) {
Widget build(BuildContext context) { _receiveMessage(message, true);
return ToastificationWrapper(
config: ToastificationConfig(
itemWidth: 440,
marginBuilder: (alignment) => EdgeInsets.symmetric(vertical: 64),
animationDuration: Duration(milliseconds: 200),
),
child: Consumer<AppTheme>(
builder: (context, appTheme, child) => MaterialApp(
title: 'SimpleCloudNotifier',
navigatorObservers: [Navi.routeObserver, Navi.modalRouteObserver],
theme: ThemeData(
//TODO color settings
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue, brightness: appTheme.darkMode ? Brightness.dark : Brightness.light),
useMaterial3: true,
),
home: SCNNavLayout(),
),
),
);
} }
Future<void> _receiveMessage(RemoteMessage message, bool foreground) async {
// ensure init
Hive.openBox<SCNLog>('scn-logs');
ApplicationLog.info('Received FB message (${foreground ? 'foreground' : 'background'}): ${message.messageId ?? 'NULL'}');
FBMessageLog.insert(message);
} }

View File

@ -6,6 +6,8 @@ import 'package:simplecloudnotifier/models/message.dart';
import 'package:simplecloudnotifier/pages/debug/debug_persistence_hive.dart'; import 'package:simplecloudnotifier/pages/debug/debug_persistence_hive.dart';
import 'package:simplecloudnotifier/pages/debug/debug_persistence_sharedprefs.dart'; import 'package:simplecloudnotifier/pages/debug/debug_persistence_sharedprefs.dart';
import 'package:simplecloudnotifier/state/application_log.dart'; import 'package:simplecloudnotifier/state/application_log.dart';
import 'package:simplecloudnotifier/state/fb_message.dart';
import 'package:simplecloudnotifier/state/interfaces.dart';
import 'package:simplecloudnotifier/state/request_log.dart'; import 'package:simplecloudnotifier/state/request_log.dart';
import 'package:simplecloudnotifier/utils/navi.dart'; import 'package:simplecloudnotifier/utils/navi.dart';
@ -31,7 +33,19 @@ class _DebugPersistencePageState extends State<DebugPersistencePage> {
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
Card.outlined( _buildSharedPrefCard(context),
_buildHiveCard(context, () => Hive.box<SCNRequest>('scn-requests'), 'scn-requests'),
_buildHiveCard(context, () => Hive.box<SCNLog>('scn-logs'), 'scn-logs'),
_buildHiveCard(context, () => Hive.box<Message>('scn-message-cache'), 'scn-message-cache'),
_buildHiveCard(context, () => Hive.box<Channel>('scn-channel-cache'), 'scn-channel-cache'),
_buildHiveCard(context, () => Hive.box<FBMessage>('scn-fb-messages'), 'scn-fb-messages'),
],
),
);
}
Widget _buildSharedPrefCard(BuildContext context) {
return Card.outlined(
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: GestureDetector( child: GestureDetector(
@ -48,81 +62,27 @@ class _DebugPersistencePageState extends State<DebugPersistencePage> {
), ),
), ),
), ),
), );
Card.outlined( }
Widget _buildHiveCard(BuildContext context, Box<FieldDebuggable> Function() boxFunc, String boxname) {
return Card.outlined(
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
Navi.push(context, () => DebugHiveBoxPage(boxName: 'scn-requests', box: Hive.box<SCNRequest>('scn-requests'))); Navi.push(context, () => DebugHiveBoxPage(boxName: boxname, box: Hive.box<FBMessage>(boxname)));
}, },
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
SizedBox(width: 30, child: Text('')), SizedBox(width: 30, child: Text('')),
Expanded(child: Text('Hive [scn-requests]', style: TextStyle(fontWeight: FontWeight.bold), textAlign: TextAlign.center)), Expanded(child: Text('Hive [$boxname]', style: TextStyle(fontWeight: FontWeight.bold), textAlign: TextAlign.center)),
SizedBox(width: 40, child: Text('${Hive.box<SCNRequest>('scn-requests').length.toString()}', textAlign: TextAlign.end)), SizedBox(width: 40, child: Text('${boxFunc().length.toString()}', textAlign: TextAlign.end)),
], ],
), ),
), ),
), ),
),
Card.outlined(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: () {
Navi.push(context, () => DebugHiveBoxPage(boxName: 'scn-requests', box: Hive.box<SCNLog>('scn-logs')));
},
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(width: 30, child: Text('')),
Expanded(child: Text('Hive [scn-logs]', style: TextStyle(fontWeight: FontWeight.bold), textAlign: TextAlign.center)),
SizedBox(width: 40, child: Text('${Hive.box<SCNLog>('scn-logs').length.toString()}', textAlign: TextAlign.end)),
],
),
),
),
),
Card.outlined(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: () {
Navi.push(context, () => DebugHiveBoxPage(boxName: 'scn-message-cache', box: Hive.box<Message>('scn-message-cache')));
},
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(width: 30, child: Text('')),
Expanded(child: Text('Hive [scn-message-cache]', style: TextStyle(fontWeight: FontWeight.bold), textAlign: TextAlign.center)),
SizedBox(width: 40, child: Text('${Hive.box<Message>('scn-message-cache').length.toString()}', textAlign: TextAlign.end)),
],
),
),
),
),
Card.outlined(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: () {
Navi.push(context, () => DebugHiveBoxPage(boxName: 'scn-channel-cache', box: Hive.box<Channel>('scn-channel-cache')));
},
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(width: 30, child: Text('')),
Expanded(child: Text('Hive [scn-channel-cache]', style: TextStyle(fontWeight: FontWeight.bold), textAlign: TextAlign.center)),
SizedBox(width: 40, child: Text('${Hive.box<Channel>('scn-channel-cache').length.toString()}', textAlign: TextAlign.end)),
],
),
),
),
),
],
),
); );
} }
} }

View File

@ -0,0 +1,236 @@
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:simplecloudnotifier/state/interfaces.dart';
part 'fb_message.g.dart';
class FBMessageLog {
//TODO max size, auto clear old
static void insert(RemoteMessage msg) {
Hive.box<FBMessage>('scn-fb-messages').add(FBMessage.fromRemoteMessage(msg));
}
}
@HiveType(typeId: 106)
class FBMessage extends HiveObject implements FieldDebuggable {
@HiveField(0)
final String? senderId;
@HiveField(1)
final String? category;
@HiveField(2)
final String? collapseKey;
@HiveField(3)
final bool contentAvailable;
@HiveField(4)
final Map<String, String> data;
@HiveField(5)
final String? from;
@HiveField(6)
final String? messageId;
@HiveField(7)
final String? messageType;
@HiveField(8)
final bool mutableContent;
@HiveField(9)
final RemoteNotification? notification;
@HiveField(10)
final DateTime? sentTime;
@HiveField(11)
final String? threadId;
@HiveField(12)
final int? ttl;
@HiveField(20)
final String? notificationAndroidChannelId;
@HiveField(21)
final String? notificationAndroidClickAction;
@HiveField(22)
final String? notificationAndroidColor;
@HiveField(23)
final int? notificationAndroidCount;
@HiveField(24)
final String? notificationAndroidImageUrl;
@HiveField(25)
final String? notificationAndroidLink;
@HiveField(26)
final AndroidNotificationPriority? notificationAndroidPriority;
@HiveField(27)
final String? notificationAndroidSmallIcon;
@HiveField(28)
final String? notificationAndroidSound;
@HiveField(29)
final String? notificationAndroidTicker;
@HiveField(30)
final AndroidNotificationVisibility? notificationAndroidVisibility;
@HiveField(31)
final String? notificationAndroidTag;
@HiveField(40)
final String? notificationAppleBadge;
@HiveField(41)
final AppleNotificationSound? notificationAppleSound;
@HiveField(42)
final String? notificationAppleImageUrl;
@HiveField(43)
final String? notificationAppleSubtitle;
@HiveField(44)
final List<String>? notificationAppleSubtitleLocArgs;
@HiveField(45)
final String? notificationAppleSubtitleLocKey;
@HiveField(50)
final String? notificationWebAnalyticsLabel;
@HiveField(51)
final String? notificationWebImage;
@HiveField(52)
final String? notificationWebLink;
@HiveField(60)
final String? notificationTitle;
@HiveField(61)
final List<String>? notificationTitleLocArgs;
@HiveField(62)
final String? notificationTitleLocKey;
@HiveField(63)
final String? notificationBody;
@HiveField(64)
final List<String>? notificationBodyLocArgs;
@HiveField(65)
final String? notificationBodyLocKey;
FBMessage({
required this.senderId,
required this.category,
required this.collapseKey,
required this.contentAvailable,
required this.data,
required this.from,
required this.messageId,
required this.messageType,
required this.mutableContent,
required this.notification,
required this.sentTime,
required this.threadId,
required this.ttl,
required this.notificationAndroidChannelId,
required this.notificationAndroidClickAction,
required this.notificationAndroidColor,
required this.notificationAndroidCount,
required this.notificationAndroidImageUrl,
required this.notificationAndroidLink,
required this.notificationAndroidPriority,
required this.notificationAndroidSmallIcon,
required this.notificationAndroidSound,
required this.notificationAndroidTicker,
required this.notificationAndroidVisibility,
required this.notificationAndroidTag,
required this.notificationAppleBadge,
required this.notificationAppleSound,
required this.notificationAppleImageUrl,
required this.notificationAppleSubtitle,
required this.notificationAppleSubtitleLocArgs,
required this.notificationAppleSubtitleLocKey,
required this.notificationWebAnalyticsLabel,
required this.notificationWebImage,
required this.notificationWebLink,
required this.notificationTitle,
required this.notificationTitleLocArgs,
required this.notificationTitleLocKey,
required this.notificationBody,
required this.notificationBodyLocArgs,
required this.notificationBodyLocKey,
});
FBMessage.fromRemoteMessage(RemoteMessage rmsg)
: this.senderId = rmsg.senderId,
this.category = rmsg.category,
this.collapseKey = rmsg.collapseKey,
this.contentAvailable = rmsg.contentAvailable,
this.data = rmsg.data.map((key, value) => MapEntry(key, value?.toString() ?? '')),
this.from = rmsg.from,
this.messageId = rmsg.messageId,
this.messageType = rmsg.messageType,
this.mutableContent = rmsg.mutableContent,
this.notification = rmsg.notification,
this.sentTime = rmsg.sentTime,
this.threadId = rmsg.threadId,
this.ttl = rmsg.ttl,
this.notificationAndroidChannelId = rmsg.notification?.android?.channelId,
this.notificationAndroidClickAction = rmsg.notification?.android?.clickAction,
this.notificationAndroidColor = rmsg.notification?.android?.color,
this.notificationAndroidCount = rmsg.notification?.android?.count,
this.notificationAndroidImageUrl = rmsg.notification?.android?.imageUrl,
this.notificationAndroidLink = rmsg.notification?.android?.link,
this.notificationAndroidPriority = rmsg.notification?.android?.priority,
this.notificationAndroidSmallIcon = rmsg.notification?.android?.smallIcon,
this.notificationAndroidSound = rmsg.notification?.android?.sound,
this.notificationAndroidTicker = rmsg.notification?.android?.ticker,
this.notificationAndroidVisibility = rmsg.notification?.android?.visibility,
this.notificationAndroidTag = rmsg.notification?.android?.tag,
this.notificationAppleBadge = rmsg.notification?.apple?.badge,
this.notificationAppleSound = rmsg.notification?.apple?.sound,
this.notificationAppleImageUrl = rmsg.notification?.apple?.imageUrl,
this.notificationAppleSubtitle = rmsg.notification?.apple?.subtitle,
this.notificationAppleSubtitleLocArgs = rmsg.notification?.apple?.subtitleLocArgs,
this.notificationAppleSubtitleLocKey = rmsg.notification?.apple?.subtitleLocKey,
this.notificationWebAnalyticsLabel = rmsg.notification?.web?.analyticsLabel,
this.notificationWebImage = rmsg.notification?.web?.image,
this.notificationWebLink = rmsg.notification?.web?.link,
this.notificationTitle = rmsg.notification?.title,
this.notificationTitleLocArgs = rmsg.notification?.titleLocArgs,
this.notificationTitleLocKey = rmsg.notification?.titleLocKey,
this.notificationBody = rmsg.notification?.body,
this.notificationBodyLocArgs = rmsg.notification?.bodyLocArgs,
this.notificationBodyLocKey = rmsg.notification?.bodyLocKey {}
@override
String toString() {
return 'FBMessage[${this.messageId ?? 'NULL'}]';
}
List<(String, String)> debugFieldList() {
return [
('senderId', this.senderId ?? ''),
('category', this.category ?? ''),
('collapseKey', this.collapseKey ?? ''),
('contentAvailable', this.contentAvailable.toString()),
('data', this.data.toString()),
('from', this.from ?? ''),
('messageId', this.messageId ?? ''),
('messageType', this.messageType ?? ''),
('mutableContent', this.mutableContent.toString()),
('notification', this.notification?.toString() ?? ''),
('sentTime', this.sentTime?.toString() ?? ''),
('threadId', this.threadId ?? ''),
('ttl', this.ttl?.toString() ?? ''),
('notification.Android.ChannelId', this.notificationAndroidChannelId ?? ''),
('notification.Android.ClickAction', this.notificationAndroidClickAction ?? ''),
('notification.Android.Color', this.notificationAndroidColor ?? ''),
('notification.Android.Count', this.notificationAndroidCount?.toString() ?? ''),
('notification.Android.ImageUrl', this.notificationAndroidImageUrl ?? ''),
('notification.Android.Link', this.notificationAndroidLink ?? ''),
('notification.Android.Priority', this.notificationAndroidPriority?.toString() ?? ''),
('notification.Android.SmallIcon', this.notificationAndroidSmallIcon ?? ''),
('notification.Android.Sound', this.notificationAndroidSound ?? ''),
('notification.Android.Ticker', this.notificationAndroidTicker ?? ''),
('notification.Android.Visibility', this.notificationAndroidVisibility?.toString() ?? ''),
('notification.Android.Tag', this.notificationAndroidTag ?? ''),
('notification.Apple.Badge', this.notificationAppleBadge ?? ''),
('notification.Apple.Sound', this.notificationAppleSound?.toString() ?? ''),
('notification.Apple.ImageUrl', this.notificationAppleImageUrl ?? ''),
('notification.Apple.Subtitle', this.notificationAppleSubtitle ?? ''),
('notification.Apple.SubtitleLocArgs', this.notificationAppleSubtitleLocArgs?.toString() ?? ''),
('notification.Apple.SubtitleLocKey', this.notificationAppleSubtitleLocKey ?? ''),
('notification.Web.AnalyticsLabel', this.notificationWebAnalyticsLabel ?? ''),
('notification.Web.Image', this.notificationWebImage ?? ''),
('notification.Web.Link', this.notificationWebLink ?? ''),
('notification.Title', this.notificationTitle ?? ''),
('notification.TitleLocArgs', this.notificationTitleLocArgs?.toString() ?? ''),
('notification.TitleLocKey', this.notificationTitleLocKey ?? ''),
('notification.Body', this.notificationBody ?? ''),
('notification.BodyLocArgs', this.notificationBodyLocArgs?.toString() ?? ''),
('notification.BodyLocKey', this.notificationBodyLocKey ?? ''),
];
}
}

View File

@ -0,0 +1,159 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'fb_message.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class FBMessageAdapter extends TypeAdapter<FBMessage> {
@override
final int typeId = 106;
@override
FBMessage read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return FBMessage(
senderId: fields[0] as String?,
category: fields[1] as String?,
collapseKey: fields[2] as String?,
contentAvailable: fields[3] as bool,
data: (fields[4] as Map).cast<String, String>(),
from: fields[5] as String?,
messageId: fields[6] as String?,
messageType: fields[7] as String?,
mutableContent: fields[8] as bool,
notification: fields[9] as RemoteNotification?,
sentTime: fields[10] as DateTime?,
threadId: fields[11] as String?,
ttl: fields[12] as int?,
notificationAndroidChannelId: fields[20] as String?,
notificationAndroidClickAction: fields[21] as String?,
notificationAndroidColor: fields[22] as String?,
notificationAndroidCount: fields[23] as int?,
notificationAndroidImageUrl: fields[24] as String?,
notificationAndroidLink: fields[25] as String?,
notificationAndroidPriority: fields[26] as AndroidNotificationPriority?,
notificationAndroidSmallIcon: fields[27] as String?,
notificationAndroidSound: fields[28] as String?,
notificationAndroidTicker: fields[29] as String?,
notificationAndroidVisibility:
fields[30] as AndroidNotificationVisibility?,
notificationAndroidTag: fields[31] as String?,
notificationAppleBadge: fields[40] as String?,
notificationAppleSound: fields[41] as AppleNotificationSound?,
notificationAppleImageUrl: fields[42] as String?,
notificationAppleSubtitle: fields[43] as String?,
notificationAppleSubtitleLocArgs: (fields[44] as List?)?.cast<String>(),
notificationAppleSubtitleLocKey: fields[45] as String?,
notificationWebAnalyticsLabel: fields[50] as String?,
notificationWebImage: fields[51] as String?,
notificationWebLink: fields[52] as String?,
notificationTitle: fields[60] as String?,
notificationTitleLocArgs: (fields[61] as List?)?.cast<String>(),
notificationTitleLocKey: fields[62] as String?,
notificationBody: fields[63] as String?,
notificationBodyLocArgs: (fields[64] as List?)?.cast<String>(),
notificationBodyLocKey: fields[65] as String?,
);
}
@override
void write(BinaryWriter writer, FBMessage obj) {
writer
..writeByte(40)
..writeByte(0)
..write(obj.senderId)
..writeByte(1)
..write(obj.category)
..writeByte(2)
..write(obj.collapseKey)
..writeByte(3)
..write(obj.contentAvailable)
..writeByte(4)
..write(obj.data)
..writeByte(5)
..write(obj.from)
..writeByte(6)
..write(obj.messageId)
..writeByte(7)
..write(obj.messageType)
..writeByte(8)
..write(obj.mutableContent)
..writeByte(9)
..write(obj.notification)
..writeByte(10)
..write(obj.sentTime)
..writeByte(11)
..write(obj.threadId)
..writeByte(12)
..write(obj.ttl)
..writeByte(20)
..write(obj.notificationAndroidChannelId)
..writeByte(21)
..write(obj.notificationAndroidClickAction)
..writeByte(22)
..write(obj.notificationAndroidColor)
..writeByte(23)
..write(obj.notificationAndroidCount)
..writeByte(24)
..write(obj.notificationAndroidImageUrl)
..writeByte(25)
..write(obj.notificationAndroidLink)
..writeByte(26)
..write(obj.notificationAndroidPriority)
..writeByte(27)
..write(obj.notificationAndroidSmallIcon)
..writeByte(28)
..write(obj.notificationAndroidSound)
..writeByte(29)
..write(obj.notificationAndroidTicker)
..writeByte(30)
..write(obj.notificationAndroidVisibility)
..writeByte(31)
..write(obj.notificationAndroidTag)
..writeByte(40)
..write(obj.notificationAppleBadge)
..writeByte(41)
..write(obj.notificationAppleSound)
..writeByte(42)
..write(obj.notificationAppleImageUrl)
..writeByte(43)
..write(obj.notificationAppleSubtitle)
..writeByte(44)
..write(obj.notificationAppleSubtitleLocArgs)
..writeByte(45)
..write(obj.notificationAppleSubtitleLocKey)
..writeByte(50)
..write(obj.notificationWebAnalyticsLabel)
..writeByte(51)
..write(obj.notificationWebImage)
..writeByte(52)
..write(obj.notificationWebLink)
..writeByte(60)
..write(obj.notificationTitle)
..writeByte(61)
..write(obj.notificationTitleLocArgs)
..writeByte(62)
..write(obj.notificationTitleLocKey)
..writeByte(63)
..write(obj.notificationBody)
..writeByte(64)
..write(obj.notificationBodyLocArgs)
..writeByte(65)
..write(obj.notificationBodyLocKey);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is FBMessageAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}