Skip to content

Commit

Permalink
fix(push): Incorrect handling of simple alert (#3502)
Browse files Browse the repository at this point in the history
Fixes #3435.

Simple alerts on iOS take the shape (see [docs](https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html)):

```json
{
  "aps": {
    "alert": "Message"
   }
}
```

This case was not being handled in the deserializer (only the case where `alert` was a Map).
  • Loading branch information
dnys1 authored Aug 2, 2023
1 parent 2e3daaf commit 0d0736b
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,57 +21,74 @@ class PushNotificationMessage
});

factory PushNotificationMessage.fromJson(Map<Object?, Object?> json) {
String? title;
String? body;
String? imageUrl;
String? deeplinkUrl;
String? goToUrl;
ApnsPlatformOptions? apnsOptions;
FcmPlatformOptions? fcmOptions;

final data = (json['data'] as Map<Object?, Object?>?) ?? {};
final aps = json['aps'] as Map<Object?, Object?>?;
if (aps != null) {
final alert = aps['alert'] as Map<Object?, Object?>?;
if (alert != null) {
title = alert['title'] as String?;
body = alert['body'] as String?;
imageUrl = data['media-url'] as String?;

if (data['pinpoint'] != null) {
final pinpointData = data['pinpoint'] as Map<Object?, Object?>;
deeplinkUrl = pinpointData['deeplink'] as String?;
goToUrl = deeplinkUrl;
}
apnsOptions = ApnsPlatformOptions(subtitle: aps['subtitle'] as String?);
}
} else {
final action = json['action'] as Map<Object?, Object?>?;
title = json['title'] as String?;
body = json['body'] as String?;
imageUrl = json['imageUrl'] as String?;
if (action != null) {
deeplinkUrl = action['deeplink'] as String?;
goToUrl = action['url'] as String?;
}
final fcmOptionsMap = json['fcmOptions'] as Map<Object?, Object?>?;
if (fcmOptionsMap != null) {
fcmOptions = FcmPlatformOptions(
channelId: fcmOptionsMap['channelId'] as String?,
messageId: fcmOptionsMap['messageId'] as String?,
final data = (json['data'] as Map<String, Object?>?) ?? const {};
switch (json) {
// `aps` dictionary references:
// - https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification
// - https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html
case {'aps': final Map<String, Object?> aps}:
final title = switch (aps) {
{'alert': final String alert} => alert,
{'alert': {'title': final String title}} => title,
_ => null,
};
final body = switch (aps) {
{'alert': {'body': final String body}} => body,
_ => null,
};
final imageUrl = data['media-url'] as String?;
final deeplinkUrl = switch (data) {
{'pinpoint': {'deeplink': final String deeplink}} => deeplink,
_ => null,
};
final apnsOptions = ApnsPlatformOptions(
subtitle: switch (aps) {
{'alert': {'subtitle': final String subtitle}} => subtitle,
_ => null,
},
);
return PushNotificationMessage(
title: title,
body: body,
imageUrl: imageUrl,
deeplinkUrl: deeplinkUrl,
goToUrl: deeplinkUrl,
apnsOptions: apnsOptions,
data: data,
);
default:
final title = json['title'] as String?;
final body = json['body'] as String?;
final imageUrl = json['imageUrl'] as String?;
final (deeplinkUrl, goToUrl) = switch (json['action']) {
{'deeplink': final String deeplink, 'url': final String url} => (
deeplink,
url
),
{'deeplink': final String deeplink} => (deeplink, null),
{'url': final String url} => (null, url),
_ => (null, null),
};
final fcmOptions = FcmPlatformOptions(
channelId: switch (json['fcmOptions']) {
{'channelId': final String channelId} => channelId,
_ => null,
},
messageId: switch (json['fcmOptions']) {
{'messageId': final String messageId} => messageId,
_ => null,
},
);
return PushNotificationMessage(
title: title,
body: body,
imageUrl: imageUrl,
deeplinkUrl: deeplinkUrl,
goToUrl: goToUrl,
fcmOptions: fcmOptions,
data: data,
);
}
}
return PushNotificationMessage(
title: title,
body: body,
imageUrl: imageUrl,
deeplinkUrl: deeplinkUrl,
goToUrl: goToUrl,
apnsOptions: apnsOptions,
fcmOptions: fcmOptions,
data: data,
);
}

final String? title;
Expand All @@ -81,7 +98,7 @@ class PushNotificationMessage
final String? goToUrl;
final FcmPlatformOptions? fcmOptions;
final ApnsPlatformOptions? apnsOptions;
final Map<Object?, Object?> data;
final Map<String, Object?> data;

@override
String get runtimeTypeName => 'PushNotificationMessage';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ void main() {
'PINPOINT.NOTIFICATION',
);

final parsedSimpleiOSMessage =
PushNotificationMessage.fromJson(simpleAlertiOSMessage);
expect(parsedSimpleiOSMessage.title, 'Hello, world');

final parsediOSMessage =
PushNotificationMessage.fromJson(standardiOSMessage);
expect(parsediOSMessage.title, 'TITTLE');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ const standardiOSMessage = {
},
};

const simpleAlertiOSMessage = {
'aps': {
'alert': 'Hello, world',
},
};

const imageUrliOSMessage = {
'data': {
'media-url': 'TEST_URL',
Expand Down

0 comments on commit 0d0736b

Please sign in to comment.