|
| 1 | +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file |
| 2 | +// for details. All rights reserved. Use of this source code is governed by a |
| 3 | +// BSD-style license that can be found in the LICENSE file. |
| 4 | + |
| 5 | +import 'package:clock/clock.dart'; |
| 6 | +import 'package:file/file.dart'; |
| 7 | +import 'package:file/memory.dart'; |
| 8 | + |
| 9 | +import 'package:unified_analytics/src/constants.dart'; |
| 10 | +import 'package:unified_analytics/src/enums.dart'; |
| 11 | +import 'package:unified_analytics/src/survey_handler.dart'; |
| 12 | +import 'package:unified_analytics/unified_analytics.dart'; |
| 13 | + |
| 14 | +/// This example code is intended to only be used as guidance for |
| 15 | +/// clients using this package. Clients using this package should avoid |
| 16 | +/// the use of the [Analytics.test] constructor. |
| 17 | +/// |
| 18 | +/// It was used in this example file so that the real [FileSystem] was swapped |
| 19 | +/// out for a [MemoryFileSystem] so that repeated runs of this script yield |
| 20 | +/// the same results. |
| 21 | +void main() async { |
| 22 | + late final MemoryFileSystem fs; |
| 23 | + late final Analytics analytics; |
| 24 | + late final Directory home; |
| 25 | + // We need to initialize with a fake clock since the surveys have |
| 26 | + // a period of time they are valid for |
| 27 | + await withClock(Clock.fixed(DateTime(2023, 3, 3, 12, 0)), () async { |
| 28 | + // Use a memory file system to repeatedly run this example |
| 29 | + // file with the test instance |
| 30 | + fs = MemoryFileSystem(style: FileSystemStyle.posix); |
| 31 | + home = fs.directory('home'); |
| 32 | + home.createSync(); |
| 33 | + |
| 34 | + // The purpose of `initialAnalytics` is so that the tool is able to |
| 35 | + // send events after its first run; this instance won't be used below |
| 36 | + // |
| 37 | + // ignore: invalid_use_of_visible_for_testing_member |
| 38 | + final initialAnalytics = Analytics.test( |
| 39 | + tool: DashTool.flutterTool, |
| 40 | + homeDirectory: home, |
| 41 | + measurementId: 'measurementId', |
| 42 | + apiSecret: 'apiSecret', |
| 43 | + dartVersion: 'dartVersion', |
| 44 | + fs: fs, |
| 45 | + platform: DevicePlatform.macos, |
| 46 | + ); |
| 47 | + // The below command allows `DashTool.flutterTool` to send telemetry |
| 48 | + initialAnalytics.clientShowedMessage(); |
| 49 | + |
| 50 | + // ignore: invalid_use_of_visible_for_testing_member |
| 51 | + analytics = Analytics.test( |
| 52 | + tool: DashTool.flutterTool, |
| 53 | + homeDirectory: home, |
| 54 | + measurementId: 'measurementId', |
| 55 | + apiSecret: 'apiSecret', |
| 56 | + dartVersion: 'dartVersion', |
| 57 | + fs: fs, |
| 58 | + platform: DevicePlatform.macos, |
| 59 | + surveyHandler: FakeSurveyHandler.fromList( |
| 60 | + homeDirectory: home, |
| 61 | + fs: fs, |
| 62 | + initializedSurveys: [ |
| 63 | + Survey( |
| 64 | + uniqueId: 'uniqueId', |
| 65 | + startDate: DateTime(2023, 1, 1), |
| 66 | + endDate: DateTime(2023, 5, 31), |
| 67 | + description: 'description', |
| 68 | + snoozeForMinutes: 10, |
| 69 | + samplingRate: 1.0, |
| 70 | + conditionList: [], |
| 71 | + buttonList: [ |
| 72 | + SurveyButton( |
| 73 | + buttonText: 'View Survey', |
| 74 | + action: 'accept', |
| 75 | + promptRemainsVisible: false, |
| 76 | + url: 'http://example.com', |
| 77 | + ), |
| 78 | + SurveyButton( |
| 79 | + buttonText: 'More Info', |
| 80 | + action: 'snooze', |
| 81 | + promptRemainsVisible: true, |
| 82 | + url: 'http://example2.com', |
| 83 | + ), |
| 84 | + SurveyButton( |
| 85 | + buttonText: 'Dismiss Survey', |
| 86 | + action: 'dismiss', |
| 87 | + promptRemainsVisible: false, |
| 88 | + ) |
| 89 | + ], |
| 90 | + ), |
| 91 | + ], |
| 92 | + )); |
| 93 | + }); |
| 94 | + |
| 95 | + // Each client of this package will be able to fetch all of |
| 96 | + // the available surveys with the below method |
| 97 | + // |
| 98 | + // Sample rate will be applied automatically; it also won't |
| 99 | + // fetch any surveys in the snooze period or if they have |
| 100 | + // been dismissed |
| 101 | + final surveyList = await analytics.fetchAvailableSurveys(); |
| 102 | + assert(surveyList.length == 1); |
| 103 | + |
| 104 | + // Grab the first and only survey to simulate displaying it to a user |
| 105 | + final survey = surveyList.first; |
| 106 | + print('Simulating displaying the survey with a print below:'); |
| 107 | + print('Survey id: ${survey.uniqueId}\n'); |
| 108 | + |
| 109 | + // Immediately after displaying the survey, the method below |
| 110 | + // should be run so that no other clients using this tool will show |
| 111 | + // it at the same time |
| 112 | + // |
| 113 | + // It will "snoozed" when the below is run as well as reported to |
| 114 | + // Google Analytics 4 that this survey was shown |
| 115 | + analytics.surveyShown(survey); |
| 116 | + |
| 117 | + // Get the file where this is persisted to show it getting updated |
| 118 | + final persistedSurveyFile = home |
| 119 | + .childDirectory(kDartToolDirectoryName) |
| 120 | + .childFile(kDismissedSurveyFileName); |
| 121 | + print('The contents of the json file ' |
| 122 | + 'after invoking `analytics.surveyShown(survey);`'); |
| 123 | + print('${persistedSurveyFile.readAsStringSync()}\n'); |
| 124 | + |
| 125 | + // Change the index below to decide which button to simulate pressing |
| 126 | + // |
| 127 | + // 0 - accept |
| 128 | + // 1 - snooze |
| 129 | + // 2 - dismiss |
| 130 | + final selectedButtonIndex = 1; |
| 131 | + assert([0, 1, 2].contains(selectedButtonIndex)); |
| 132 | + |
| 133 | + // Get the survey button by index that will need to be passed along with |
| 134 | + // the survey to simulate an interaction with the survey |
| 135 | + final selectedSurveyButton = survey.buttonList[selectedButtonIndex]; |
| 136 | + print('The simulated button pressed was: ' |
| 137 | + '"${selectedSurveyButton.buttonText}" ' |
| 138 | + '(action = ${selectedSurveyButton.action})\n'); |
| 139 | + |
| 140 | + // The below method will handle whatever action the button |
| 141 | + analytics.surveyInteracted( |
| 142 | + survey: survey, |
| 143 | + surveyButton: selectedSurveyButton, |
| 144 | + ); |
| 145 | + |
| 146 | + // Conditional to check if there is a URl to route to |
| 147 | + if (selectedSurveyButton.url != null) { |
| 148 | + print('***This button also has a survey URL link ' |
| 149 | + 'to route to at "${selectedSurveyButton.url}"***\n'); |
| 150 | + } |
| 151 | + |
| 152 | + // Conditional to check what simulating a popup to stay up |
| 153 | + if (selectedSurveyButton.promptRemainsVisible) { |
| 154 | + print('***This button has its promptRemainsVisible field set to `true` ' |
| 155 | + 'so this simulates what seeing a pop up again would look like***\n'); |
| 156 | + } |
| 157 | + |
| 158 | + print('The contents of the json file ' |
| 159 | + 'after invoking ' |
| 160 | + '`analytics.surveyInteracted(survey: survey, ' |
| 161 | + 'surveyButton: selectedSurveyButton);`'); |
| 162 | + print('${persistedSurveyFile.readAsStringSync()}\n'); |
| 163 | + |
| 164 | + // Demonstrating that the survey doesn't get returned again |
| 165 | + print('Attempting to fetch surveys again will result in an empty list'); |
| 166 | + print(await analytics.fetchAvailableSurveys()); |
| 167 | +} |
0 commit comments