Skip to content

Commit c81cba1

Browse files
committed
fix(examples): retry on recipients=0 response
1 parent 1101b49 commit c81cba1

6 files changed

Lines changed: 22 additions & 52 deletions

File tree

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
import 'package:flutter/material.dart';
2-
31
enum InAppMessageType {
4-
topBanner('Top Banner', 'top_banner', Icons.vertical_align_top),
5-
bottomBanner('Bottom Banner', 'bottom_banner', Icons.vertical_align_bottom),
6-
centerModal('Center Modal', 'center_modal', Icons.crop_square),
7-
fullScreen('Full Screen', 'full_screen', Icons.fullscreen);
2+
topBanner('Top Banner', 'top_banner'),
3+
bottomBanner('Bottom Banner', 'bottom_banner'),
4+
centerModal('Center Modal', 'center_modal'),
5+
fullScreen('Full Screen', 'full_screen');
86

97
final String label;
108
final String triggerValue;
11-
final IconData icon;
129

13-
const InAppMessageType(this.label, this.triggerValue, this.icon);
10+
const InAppMessageType(this.label, this.triggerValue);
1411
}

examples/demo/lib/services/onesignal_api_service.dart

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,11 @@ class OneSignalApiService {
7979
// Retry while the OneSignal backend hasn't yet indexed the freshly
8080
// created subscription. The /notifications endpoint reports this race in a
8181
// few different shapes, all of which return HTTP 200:
82-
// - {"errors":{"invalid_player_ids":[...]}}
82+
// - {"id":"...","recipients":0} (user just switched, push token not yet attached)
83+
// - {"id":"...","errors":{"invalid_player_ids":[...]}}
8384
// - {"id":"","errors":["All included players are not subscribed"]}
8485
// - {"id":"","errors":[...]}
85-
// Treat any 200 response without a real notification id as transient.
86+
// Treat any 200 response with no real id, populated errors, or recipients=0 as transient.
8687
for (var attempt = 1; attempt <= maxAttempts; attempt++) {
8788
try {
8889
final response = await http.post(
@@ -123,11 +124,13 @@ class OneSignalApiService {
123124
if (decoded is! Map<String, dynamic>) return false;
124125
final id = decoded['id'];
125126
final errors = decoded['errors'];
127+
final recipients = decoded['recipients'];
126128
final hasErrors =
127129
(errors is List && errors.isNotEmpty) ||
128130
(errors is Map && errors.isNotEmpty);
129131
final missingId = id is! String || id.isEmpty;
130-
return hasErrors || missingId;
132+
final zeroRecipients = recipients is num && recipients == 0;
133+
return hasErrors || missingId || zeroRecipients;
131134
}
132135

133136
Future<bool> updateLiveActivity(

examples/demo/lib/widgets/sections/send_iam_section.dart

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'package:provider/provider.dart';
44
import '../../models/in_app_message_type.dart';
55
import '../../theme.dart';
66
import '../../viewmodels/app_viewmodel.dart';
7+
import '../action_button.dart';
78
import '../section_card.dart';
89

910
class SendIamSection extends StatelessWidget {
@@ -22,32 +23,10 @@ class SendIamSection extends StatelessWidget {
2223
child: Column(
2324
spacing: AppSpacing.gap,
2425
children: InAppMessageType.values.map((type) {
25-
return Semantics(
26-
identifier: 'send_iam_${type.triggerValue}_button',
27-
container: true,
28-
button: true,
29-
child: SizedBox(
30-
width: double.infinity,
31-
child: ElevatedButton(
32-
onPressed: () => vm.sendInAppMessage(type),
33-
style: ElevatedButton.styleFrom(
34-
backgroundColor: AppColors.osPrimary,
35-
foregroundColor: Colors.white,
36-
minimumSize: const Size(double.infinity, 48),
37-
shape: RoundedRectangleBorder(
38-
borderRadius: BorderRadius.circular(8),
39-
),
40-
),
41-
child: Row(
42-
mainAxisAlignment: MainAxisAlignment.start,
43-
children: [
44-
Icon(type.icon, size: 18),
45-
const SizedBox(width: 8),
46-
Text(type.label.toUpperCase()),
47-
],
48-
),
49-
),
50-
),
26+
return PrimaryButton(
27+
label: type.label.toUpperCase(),
28+
onPressed: () => vm.sendInAppMessage(type),
29+
semanticsLabel: 'send_iam_${type.triggerValue}_button',
5130
);
5231
}).toList(),
5332
),

examples/demo/lib/widgets/sections/user_section.dart

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,6 @@ class UserSection extends StatelessWidget {
8888
);
8989
if (result != null && context.mounted) {
9090
await vm.loginUser(result);
91-
if (context.mounted) {
92-
context.showSnackBar('Logged in as $result');
93-
}
9491
}
9592
},
9693
),
@@ -101,9 +98,6 @@ class UserSection extends StatelessWidget {
10198
semanticsLabel: 'logout_user_button',
10299
onPressed: () async {
103100
await vm.logoutUser();
104-
if (context.mounted) {
105-
context.showSnackBar('User logged out');
106-
}
107101
},
108102
),
109103
],

examples/demo_pods/lib/services/onesignal_api_service.dart

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,11 @@ class OneSignalApiService {
7979
// Retry while the OneSignal backend hasn't yet indexed the freshly
8080
// created subscription. The /notifications endpoint reports this race in a
8181
// few different shapes, all of which return HTTP 200:
82-
// - {"errors":{"invalid_player_ids":[...]}}
82+
// - {"id":"...","recipients":0} (user just switched, push token not yet attached)
83+
// - {"id":"...","errors":{"invalid_player_ids":[...]}}
8384
// - {"id":"","errors":["All included players are not subscribed"]}
8485
// - {"id":"","errors":[...]}
85-
// Treat any 200 response without a real notification id as transient.
86+
// Treat any 200 response with no real id, populated errors, or recipients=0 as transient.
8687
for (var attempt = 1; attempt <= maxAttempts; attempt++) {
8788
try {
8889
final response = await http.post(
@@ -123,11 +124,13 @@ class OneSignalApiService {
123124
if (decoded is! Map<String, dynamic>) return false;
124125
final id = decoded['id'];
125126
final errors = decoded['errors'];
127+
final recipients = decoded['recipients'];
126128
final hasErrors =
127129
(errors is List && errors.isNotEmpty) ||
128130
(errors is Map && errors.isNotEmpty);
129131
final missingId = id is! String || id.isEmpty;
130-
return hasErrors || missingId;
132+
final zeroRecipients = recipients is num && recipients == 0;
133+
return hasErrors || missingId || zeroRecipients;
131134
}
132135

133136
Future<bool> updateLiveActivity(

examples/demo_pods/lib/widgets/sections/user_section.dart

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,6 @@ class UserSection extends StatelessWidget {
8383
);
8484
if (result != null && context.mounted) {
8585
await vm.loginUser(result);
86-
if (context.mounted) {
87-
context.showSnackBar('Logged in as $result');
88-
}
8986
}
9087
},
9188
),
@@ -96,9 +93,6 @@ class UserSection extends StatelessWidget {
9693
semanticsLabel: 'logout_user_button',
9794
onPressed: () async {
9895
await vm.logoutUser();
99-
if (context.mounted) {
100-
context.showSnackBar('User logged out');
101-
}
10296
},
10397
),
10498
],

0 commit comments

Comments
 (0)