Skip to content

Commit f6e67f2

Browse files
authored
Fix logic for first run to fix shouldShowMessage behavior (#228)
* Adding new `_firstRun` * Remove redundant `_clientShowedMessage` var * Enhance test to add incrementing + new tool * Update version * Clean up dartdoc * Update workflow_test.dart * Set private _showMessage in method scope * Format fix
1 parent b97bd5c commit f6e67f2

File tree

4 files changed

+129
-37
lines changed

4 files changed

+129
-37
lines changed

pkgs/unified_analytics/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
## 5.8.1
22

3+
- Refactor logic for `okToSend` and `shouldShowMessage`
34
- Check devtools config file for legacy opt out status
45

56
## 5.8.0

pkgs/unified_analytics/lib/src/analytics.dart

+28-35
Original file line numberDiff line numberDiff line change
@@ -333,26 +333,16 @@ class AnalyticsImpl implements Analytics {
333333
/// message has been updated by the package.
334334
late bool _showMessage;
335335

336-
/// This will be switch to true once it has been confirmed by the
337-
/// client using this package that they have shown the
338-
/// consent message to the developer.
339-
///
340-
/// If the tool using this package as already shown the consent message
341-
/// and it has been added to the config file, it will be set as true.
342-
///
343-
/// It will also be set to true once the tool using this package has
344-
/// invoked [clientShowedMessage].
345-
///
346-
/// If this is false, all events will be blocked from being sent.
347-
bool _clientShowedMessage = false;
348-
349336
/// When set to `true`, various assert statements will be enabled
350337
/// to ensure usage of this class is within GA4 limitations.
351338
final bool _enableAsserts;
352339

353340
/// Telemetry suppression flag that is set via [Analytics.suppressTelemetry].
354341
bool _telemetrySuppressed = false;
355342

343+
/// Indicates if this is the first run for a given tool.
344+
bool _firstRun = false;
345+
356346
/// The list of futures that will contain all of the send events
357347
/// from the [GAClient].
358348
final _futures = <Future<Response>>[];
@@ -388,7 +378,13 @@ class AnalyticsImpl implements Analytics {
388378
toolsMessageVersion: toolsMessageVersion,
389379
);
390380
initializer.run();
391-
_showMessage = initializer.firstRun;
381+
if (initializer.firstRun) {
382+
_showMessage = true;
383+
_firstRun = true;
384+
} else {
385+
_showMessage = false;
386+
_firstRun = false;
387+
}
392388

393389
// Create the config handler that will parse the config file
394390
_configHandler = ConfigHandler(
@@ -397,13 +393,6 @@ class AnalyticsImpl implements Analytics {
397393
initializer: initializer,
398394
);
399395

400-
// If the tool has already been added to the config file
401-
// we can assume that the client has successfully shown
402-
// the consent message
403-
if (_configHandler.parsedTools.containsKey(tool.label)) {
404-
_clientShowedMessage = true;
405-
}
406-
407396
// Check if the tool has already been onboarded, and if it
408397
// has, check if the latest message version is greater to
409398
// prompt the client to show a message
@@ -414,6 +403,11 @@ class AnalyticsImpl implements Analytics {
414403
_configHandler.parsedTools[tool.label]?.versionNumber ?? -1;
415404
if (currentVersion < toolsMessageVersion) {
416405
_showMessage = true;
406+
407+
// If the message version has been updated, it will be considered
408+
// as if it was a first run and any events attempting to get sent
409+
// will be blocked
410+
_firstRun = true;
417411
}
418412

419413
_clientIdFile = fs.file(
@@ -464,22 +458,19 @@ class AnalyticsImpl implements Analytics {
464458
/// Checking the [telemetryEnabled] boolean reflects what the
465459
/// config file reflects.
466460
///
467-
/// Checking the [_showMessage] boolean indicates if this the first
468-
/// time the tool is using analytics or if there has been an update
469-
/// the messaging found in constants.dart - in both cases, analytics
470-
/// will not be sent until the second time the tool is used.
471-
///
472-
/// Additionally, if the client has not invoked
473-
/// [Analytics.clientShowedMessage], then no events shall be sent.
461+
/// Checking the [_showMessage] boolean indicates if the consent
462+
/// message has been shown for the user, this boolean is set to `true`
463+
/// when the tool using this package invokes the [clientShowedMessage]
464+
/// method.
474465
///
475466
/// If the user has suppressed telemetry [_telemetrySuppressed] will
476467
/// return `true` to prevent events from being sent for current invocation.
468+
///
469+
/// Checking if it is the first time a tool is running with this package
470+
/// as indicated by [_firstRun].
477471
@override
478472
bool get okToSend =>
479-
telemetryEnabled &&
480-
!_showMessage &&
481-
_clientShowedMessage &&
482-
!_telemetrySuppressed;
473+
telemetryEnabled && !_showMessage && !_telemetrySuppressed && !_firstRun;
483474

484475
@override
485476
Map<String, ToolInfo> get parsedTools => _configHandler.parsedTools;
@@ -496,22 +487,24 @@ class AnalyticsImpl implements Analytics {
496487

497488
@override
498489
void clientShowedMessage() {
490+
// Check the tool needs to be added to the config file
499491
if (!_configHandler.parsedTools.containsKey(tool.label)) {
500492
_configHandler.addTool(
501493
tool: tool.label,
502494
versionNumber: toolsMessageVersion,
503495
);
504-
_showMessage = true;
505496
}
497+
498+
// When the tool already exists but the consent message version
499+
// has been updated
506500
if (_configHandler.parsedTools[tool.label]!.versionNumber <
507501
toolsMessageVersion) {
508502
_configHandler.incrementToolVersion(
509503
tool: tool.label,
510504
newVersionNumber: toolsMessageVersion,
511505
);
512-
_showMessage = true;
513506
}
514-
_clientShowedMessage = true;
507+
_showMessage = false;
515508
}
516509

517510
@override

pkgs/unified_analytics/test/unified_analytics_test.dart

+7-2
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ void main() {
7474
fs: fs,
7575
platform: platform,
7676
);
77+
expect(initializationAnalytics.shouldShowMessage, true);
7778
initializationAnalytics.clientShowedMessage();
79+
expect(initializationAnalytics.shouldShowMessage, false);
7880

7981
// The main analytics instance, other instances can be spawned within tests
8082
// to test how to instances running together work
@@ -143,8 +145,6 @@ void main() {
143145
expect(dartToolDirectory.listSync().length, equals(5),
144146
reason:
145147
'There should only be 5 files in the $kDartToolDirectoryName directory');
146-
expect(initializationAnalytics.shouldShowMessage, true,
147-
reason: 'For the first run, the message should be shown');
148148
expect(configFile.readAsLinesSync().length,
149149
kConfigString.split('\n').length + 1,
150150
reason: 'The number of lines should equal lines in constant value + 1 '
@@ -430,7 +430,12 @@ void main() {
430430
fs: fs,
431431
platform: platform,
432432
);
433+
expect(secondAnalytics.shouldShowMessage, true);
434+
expect(secondAnalytics.okToSend, false);
433435
secondAnalytics.clientShowedMessage();
436+
expect(secondAnalytics.shouldShowMessage, false);
437+
expect(secondAnalytics.okToSend, false,
438+
reason: 'New version for the message will be treated as a first run');
434439

435440
expect(secondAnalytics.parsedTools[initialTool.label]?.versionNumber,
436441
toolsMessageVersion + 1,

pkgs/unified_analytics/test/workflow_test.dart

+93
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,99 @@ void main() {
5959
.childFile(kDismissedSurveyFileName);
6060
});
6161

62+
test('Confirm workflow for first run', () {
63+
final firstAnalytics = Analytics.test(
64+
tool: initialTool,
65+
homeDirectory: home,
66+
measurementId: measurementId,
67+
apiSecret: apiSecret,
68+
flutterChannel: flutterChannel,
69+
toolsMessageVersion: toolsMessageVersion,
70+
toolsMessage: toolsMessage,
71+
flutterVersion: flutterVersion,
72+
dartVersion: dartVersion,
73+
fs: fs,
74+
platform: platform,
75+
);
76+
77+
expect(firstAnalytics.shouldShowMessage, true);
78+
expect(firstAnalytics.okToSend, false);
79+
80+
firstAnalytics.clientShowedMessage();
81+
expect(firstAnalytics.shouldShowMessage, false);
82+
expect(firstAnalytics.okToSend, false,
83+
reason: 'On the first run, we should not be ok '
84+
'to send any events, even if the user accepts');
85+
});
86+
87+
test('Confirm workflow for updated tools message version + new tool', () {
88+
// Helper function to check the state of the instance
89+
void checkAnalyticsInstance(Analytics instance) {
90+
expect(instance.shouldShowMessage, true);
91+
expect(instance.okToSend, false);
92+
93+
instance.clientShowedMessage();
94+
expect(instance.shouldShowMessage, false);
95+
expect(instance.okToSend, false,
96+
reason: 'On the first run, we should not be ok '
97+
'to send any events, even if the user accepts');
98+
}
99+
100+
final firstAnalytics = Analytics.test(
101+
tool: initialTool,
102+
homeDirectory: home,
103+
measurementId: measurementId,
104+
apiSecret: apiSecret,
105+
flutterChannel: flutterChannel,
106+
toolsMessageVersion: toolsMessageVersion,
107+
toolsMessage: toolsMessage,
108+
flutterVersion: flutterVersion,
109+
dartVersion: dartVersion,
110+
fs: fs,
111+
platform: platform,
112+
);
113+
114+
checkAnalyticsInstance(firstAnalytics);
115+
116+
// Instance where we increment the version of the message
117+
final secondAnalytics = Analytics.test(
118+
tool: initialTool,
119+
homeDirectory: home,
120+
measurementId: measurementId,
121+
apiSecret: apiSecret,
122+
flutterChannel: flutterChannel,
123+
toolsMessageVersion: toolsMessageVersion + 1, // Incrementing version
124+
toolsMessage: toolsMessage,
125+
flutterVersion: flutterVersion,
126+
dartVersion: dartVersion,
127+
fs: fs,
128+
platform: platform,
129+
);
130+
131+
// Running the same checks for the second instance, it should
132+
// behave the same as if it was a first run
133+
checkAnalyticsInstance(secondAnalytics);
134+
135+
// Instance for a different tool with the incremented version
136+
final thirdAnalytics = Analytics.test(
137+
tool: secondTool, // Different tool
138+
homeDirectory: home,
139+
measurementId: measurementId,
140+
apiSecret: apiSecret,
141+
flutterChannel: flutterChannel,
142+
toolsMessageVersion: toolsMessageVersion + 1, // Incrementing version
143+
toolsMessage: toolsMessage,
144+
flutterVersion: flutterVersion,
145+
dartVersion: dartVersion,
146+
fs: fs,
147+
platform: platform,
148+
);
149+
150+
// The instance with a new tool getting onboarded should be
151+
// treated the same as the 2 previous instances
152+
checkAnalyticsInstance(thirdAnalytics);
153+
});
154+
62155
test('Confirm workflow for checking tools into the config file', () {
63156
final firstAnalytics = Analytics.test(
64157
tool: initialTool,

0 commit comments

Comments
 (0)