Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
7c618758
Unverified
Commit
7c618758
authored
Jan 06, 2021
by
Jonah Williams
Committed by
GitHub
Jan 06, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[flutter_tools] delegate first run message re-display to new class, only if changed (#73353)
parent
5f4cf659
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
174 additions
and
71 deletions
+174
-71
context_runner.dart
packages/flutter_tools/lib/src/context_runner.dart
+2
-0
persistent_tool_state.dart
packages/flutter_tools/lib/src/persistent_tool_state.dart
+13
-0
disabled_usage.dart
packages/flutter_tools/lib/src/reporting/disabled_usage.dart
+0
-3
first_run.dart
packages/flutter_tools/lib/src/reporting/first_run.dart
+79
-0
reporting.dart
packages/flutter_tools/lib/src/reporting/reporting.dart
+1
-0
usage.dart
packages/flutter_tools/lib/src/reporting/usage.dart
+13
-47
config_test.dart
...utter_tools/test/commands.shard/hermetic/config_test.dart
+0
-2
doctor_test.dart
...utter_tools/test/commands.shard/hermetic/doctor_test.dart
+0
-1
build_aar_test.dart
...r_tools/test/commands.shard/permeable/build_aar_test.dart
+0
-4
build_apk_test.dart
...r_tools/test/commands.shard/permeable/build_apk_test.dart
+0
-1
build_appbundle_test.dart
...s/test/commands.shard/permeable/build_appbundle_test.dart
+0
-2
analytics_test.dart
...ages/flutter_tools/test/general.shard/analytics_test.dart
+0
-1
first_run_test.dart
...er_tools/test/general.shard/reporting/first_run_test.dart
+66
-0
flutter_command_test.dart
...tools/test/general.shard/runner/flutter_command_test.dart
+0
-1
runner_test.dart
.../flutter_tools/test/general.shard/runner/runner_test.dart
+0
-3
context.dart
packages/flutter_tools/test/src/context.dart
+0
-3
testbed.dart
packages/flutter_tools/test/src/testbed.dart
+0
-3
No files found.
packages/flutter_tools/lib/src/context_runner.dart
View file @
7c618758
...
...
@@ -46,6 +46,7 @@ import 'macos/macos_workflow.dart';
import
'macos/xcode.dart'
;
import
'mdns_discovery.dart'
;
import
'persistent_tool_state.dart'
;
import
'reporting/first_run.dart'
;
import
'reporting/reporting.dart'
;
import
'resident_runner.dart'
;
import
'run_hot.dart'
;
...
...
@@ -278,6 +279,7 @@ Future<T> runInContext<T>(
SystemClock:
()
=>
const
SystemClock
(),
Usage:
()
=>
Usage
(
runningOnBot:
runningOnBot
,
firstRunMessenger:
FirstRunMessenger
(
persistentToolState:
globals
.
persistentToolState
),
),
UserMessages:
()
=>
UserMessages
(),
VisualStudioValidator:
()
=>
VisualStudioValidator
(
...
...
packages/flutter_tools/lib/src/persistent_tool_state.dart
View file @
7c618758
...
...
@@ -47,6 +47,9 @@ abstract class PersistentToolState {
/// Update the last active version for a given [channel].
void
updateLastActiveVersion
(
String
fullGitHash
,
Channel
channel
);
/// Return the hash of the last active license terms.
String
lastActiveLicenseTerms
;
/// Whether this client was already determined to be or not be a bot.
bool
isRunningOnBot
;
}
...
...
@@ -82,6 +85,7 @@ class _DefaultPersistentToolState implements PersistentToolState {
Channel
.
stable
:
'last-active-stable-version'
};
static
const
String
_kBotKey
=
'is-bot'
;
static
const
String
_kLicenseHash
=
'license-hash'
;
final
Config
_config
;
...
...
@@ -109,6 +113,15 @@ class _DefaultPersistentToolState implements PersistentToolState {
_config
.
setValue
(
versionKey
,
fullGitHash
);
}
@override
String
get
lastActiveLicenseTerms
=>
_config
.
getValue
(
_kLicenseHash
)
as
String
;
@override
set
lastActiveLicenseTerms
(
String
value
)
{
assert
(
value
!=
null
);
_config
.
setValue
(
_kLicenseHash
,
value
);
}
String
_versionKeyFor
(
Channel
channel
)
{
return
_lastActiveVersionKeys
[
channel
];
}
...
...
packages/flutter_tools/lib/src/reporting/disabled_usage.dart
View file @
7c618758
...
...
@@ -5,9 +5,6 @@
part of
reporting
;
class
DisabledUsage
implements
Usage
{
@override
bool
get
isFirstRun
=>
false
;
@override
bool
get
suppressAnalytics
=>
true
;
...
...
packages/flutter_tools/lib/src/reporting/first_run.dart
0 → 100644
View file @
7c618758
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:convert/convert.dart'
;
import
'package:crypto/crypto.dart'
;
import
'package:meta/meta.dart'
;
import
'../convert.dart'
;
import
'../persistent_tool_state.dart'
;
/// This message is displayed on the first run of the Flutter tool, or anytime
/// that the contents of this string change.
const
String
_kFlutterFirstRunMessage
=
'''
╔════════════════════════════════════════════════════════════════════════════╗
║ Welcome to Flutter! - https://flutter.dev ║
║ ║
║ The Flutter tool uses Google Analytics to anonymously report feature usage ║
║ statistics and basic crash reports. This data is used to help improve ║
║ Flutter tools over time. ║
║ ║
║ Flutter tool analytics are not sent on the very first run. To disable ║
║ reporting, type '
flutter
config
--
no
-
analytics
'. To display the current ║
║ setting, type '
flutter
config
'. If you opt out of analytics, an opt-out ║
║ event will be sent, and then no further information will be sent by the ║
║ Flutter tool. ║
║ ║
║ By downloading the Flutter SDK, you agree to the Google Terms of Service. ║
║ Note: The Google Privacy Policy describes how data is handled in this ║
║ service. ║
║ ║
║ Moreover, Flutter includes the Dart SDK, which may send usage metrics and ║
║ crash reports to Google. ║
║ ║
║ Read about data we send with crash reports: ║
║ https://flutter.dev/docs/reference/crash-reporting ║
║ ║
║ See Google'
s
privacy
policy:
║
║
https:
//policies.google.com/privacy ║
╚════════════════════════════════════════════════════════════════════════════╝
''';
/// The first run messenger determines whether the first run license terms
/// need to be displayed.
class FirstRunMessenger {
FirstRunMessenger({
@required PersistentToolState persistentToolState
}) : _persistentToolState = persistentToolState;
final PersistentToolState _persistentToolState;
/// Whether the license terms should be displayed.
///
/// This is implemented by caching a hash of the previous license terms. This
/// does not update the cache hash value.
///
/// The persistent tool state setting [PersistentToolState.redisplayWelcomeMessage]
/// can also be used to make this return false. This is primarily used to ensure
/// that the license terms are not printed during a `flutter upgrade`, until the
/// user manually runs the tool.
bool shouldDisplayLicenseTerms() {
if (_persistentToolState.redisplayWelcomeMessage == false) {
return false;
}
final String oldHash = _persistentToolState.lastActiveLicenseTerms;
return oldHash != _currentHash;
}
/// Update the cached license terms hash once the new terms have been displayed.
void confirmLicenseTermsDisplayed() {
_persistentToolState.lastActiveLicenseTerms = _currentHash;
}
/// The hash of the current license representation.
String get _currentHash => hex.encode(md5.convert(utf8.encode(licenseTerms)).bytes);
/// The current license terms.
String get licenseTerms => _kFlutterFirstRunMessage;
}
packages/flutter_tools/lib/src/reporting/reporting.dart
View file @
7c618758
...
...
@@ -35,6 +35,7 @@ import '../globals.dart' as globals;
import
'../project.dart'
;
import
'../runner/flutter_command.dart'
;
import
'../version.dart'
;
import
'first_run.dart'
;
part
'crash_reporting.dart'
;
part
'disabled_usage.dart'
;
...
...
packages/flutter_tools/lib/src/reporting/usage.dart
View file @
7c618758
...
...
@@ -79,13 +79,15 @@ abstract class Usage {
String
configDirOverride
,
String
logFile
,
AnalyticsFactory
analyticsIOFactory
,
FirstRunMessenger
firstRunMessenger
,
@required
bool
runningOnBot
,
})
=>
_DefaultUsage
(
settingsName:
settingsName
,
versionOverride:
versionOverride
,
configDirOverride:
configDirOverride
,
logFile:
logFile
,
analyticsIOFactory:
analyticsIOFactory
,
runningOnBot:
runningOnBot
);
runningOnBot:
runningOnBot
,
firstRunMessenger:
firstRunMessenger
);
factory
Usage
.
test
()
=>
_DefaultUsage
.
test
();
...
...
@@ -94,9 +96,6 @@ abstract class Usage {
Map
<
CustomDimensions
,
Object
>
parameters
,
})
=>
globals
.
flutterUsage
.
sendCommand
(
command
,
parameters:
_useCdKeys
(
parameters
));
/// Whether this is the first run of the tool.
bool
get
isFirstRun
;
/// Whether analytics reporting should be suppressed.
bool
get
suppressAnalytics
;
...
...
@@ -191,6 +190,7 @@ class _DefaultUsage implements Usage {
String
configDirOverride
,
String
logFile
,
AnalyticsFactory
analyticsIOFactory
,
@required
this
.
firstRunMessenger
,
@required
bool
runningOnBot
,
})
{
final
FlutterVersion
flutterVersion
=
globals
.
flutterVersion
;
...
...
@@ -202,7 +202,7 @@ class _DefaultUsage implements Usage {
analyticsIOFactory
??=
_defaultAnalyticsIOFactory
;
_clock
=
globals
.
systemClock
;
if
(
// To support testing, only allow other signals to supress analytics
if
(
// To support testing, only allow other signals to sup
p
ress analytics
// when analytics are not being shunted to a file.
!
usingLogFile
&&
(
// Ignore local user branches.
...
...
@@ -277,17 +277,16 @@ class _DefaultUsage implements Usage {
_DefaultUsage
.
test
()
:
_suppressAnalytics
=
false
,
_analytics
=
AnalyticsMock
(
true
),
firstRunMessenger
=
null
,
_clock
=
SystemClock
.
fixed
(
DateTime
(
2020
,
10
,
8
));
Analytics
_analytics
;
final
FirstRunMessenger
firstRunMessenger
;
bool
_printedWelcome
=
false
;
bool
_suppressAnalytics
=
false
;
SystemClock
_clock
;
@override
bool
get
isFirstRun
=>
_analytics
.
firstRun
;
@override
bool
get
suppressAnalytics
=>
_suppressAnalytics
||
_analytics
.
firstRun
;
...
...
@@ -383,52 +382,19 @@ class _DefaultUsage implements Usage {
await
_analytics
.
waitForLastPing
(
timeout:
const
Duration
(
milliseconds:
250
));
}
void
_printWelcome
()
{
globals
.
printStatus
(
''
);
globals
.
printStatus
(
'''
╔════════════════════════════════════════════════════════════════════════════╗
║ Welcome to Flutter! - https://flutter.dev ║
║ ║
║ The Flutter tool uses Google Analytics to anonymously report feature usage ║
║ statistics and basic crash reports. This data is used to help improve ║
║ Flutter tools over time. ║
║ ║
║ Flutter tool analytics are not sent on the very first run. To disable ║
║ reporting, type '
flutter
config
--
no
-
analytics
'. To display the current ║
║ setting, type '
flutter
config
'. If you opt out of analytics, an opt-out ║
║ event will be sent, and then no further information will be sent by the ║
║ Flutter tool. ║
║ ║
║ By downloading the Flutter SDK, you agree to the Google Terms of Service. ║
║ Note: The Google Privacy Policy describes how data is handled in this ║
║ service. ║
║ ║
║ Moreover, Flutter includes the Dart SDK, which may send usage metrics and ║
║ crash reports to Google. ║
║ ║
║ Read about data we send with crash reports: ║
║ https://flutter.dev/docs/reference/crash-reporting ║
║ ║
║ See Google'
s
privacy
policy:
║
║
https:
//policies.google.com/privacy ║
╚════════════════════════════════════════════════════════════════════════════╝
''', emphasis: true);
}
@override
void
printWelcome
()
{
// Only print once per run.
if
(
_printedWelcome
)
{
return
;
}
if (// Display the welcome message if this is the first run of the tool.
isFirstRun ||
// Display the welcome message if we are not on master, and if the
// persistent tool state instructs that we should.
(globals.persistentToolState.redisplayWelcomeMessage ?? true)) {
_printWelcome();
// Display the welcome message if this is the first run of the tool or if
// the license terms have changed since it was last displayed.
if
(
firstRunMessenger
!=
null
&&
firstRunMessenger
.
shouldDisplayLicenseTerms
()
??
true
)
{
globals
.
printStatus
(
''
);
globals
.
printStatus
(
firstRunMessenger
.
licenseTerms
,
emphasis:
true
);
_printedWelcome
=
true
;
globals.persistentToolState.redisplayWelcomeMessage = false
;
firstRunMessenger
.
confirmLicenseTermsDisplayed
()
;
}
}
}
...
...
packages/flutter_tools/test/commands.shard/hermetic/config_test.dart
View file @
7c618758
...
...
@@ -34,8 +34,6 @@ void main() {
mockAndroidSdk
=
MockAndroidSdk
();
mockFlutterVersion
=
MockFlutterVersion
();
mockUsage
=
MockUsage
();
when
(
mockUsage
.
isFirstRun
).
thenReturn
(
false
);
});
void
verifyNoAnalytics
()
{
...
...
packages/flutter_tools/test/commands.shard/hermetic/doctor_test.dart
View file @
7c618758
...
...
@@ -223,7 +223,6 @@ void main() {
setUp
(()
{
mockUsage
=
MockUsage
();
when
(
mockUsage
.
isFirstRun
).
thenReturn
(
true
);
});
testUsingContext
(
'contains installed'
,
()
async
{
...
...
packages/flutter_tools/test/commands.shard/permeable/build_aar_test.dart
View file @
7c618758
...
...
@@ -207,12 +207,8 @@ void main() {
ProcessManager
mockProcessManager
;
Directory
tempDir
;
AndroidSdk
mockAndroidSdk
;
Usage
mockUsage
;
setUp
(()
{
mockUsage
=
MockUsage
();
when
(
mockUsage
.
isFirstRun
).
thenReturn
(
true
);
tempDir
=
globals
.
fs
.
systemTempDirectory
.
createTempSync
(
'flutter_tools_packages_test.'
);
mockProcessManager
=
MockProcessManager
();
...
...
packages/flutter_tools/test/commands.shard/permeable/build_apk_test.dart
View file @
7c618758
...
...
@@ -124,7 +124,6 @@ void main() {
setUp
(()
{
mockUsage
=
MockUsage
();
when
(
mockUsage
.
isFirstRun
).
thenReturn
(
true
);
tempDir
=
globals
.
fs
.
systemTempDirectory
.
createTempSync
(
'flutter_tools_packages_test.'
);
gradlew
=
globals
.
fs
.
path
.
join
(
tempDir
.
path
,
'flutter_project'
,
'android'
,
...
...
packages/flutter_tools/test/commands.shard/permeable/build_appbundle_test.dart
View file @
7c618758
...
...
@@ -106,8 +106,6 @@ void main() {
setUp
(()
{
mockUsage
=
MockUsage
();
when
(
mockUsage
.
isFirstRun
).
thenReturn
(
true
);
tempDir
=
globals
.
fs
.
systemTempDirectory
.
createTempSync
(
'flutter_tools_packages_test.'
);
gradlew
=
globals
.
fs
.
path
.
join
(
tempDir
.
path
,
'flutter_project'
,
'android'
,
globals
.
platform
.
isWindows
?
'gradlew.bat'
:
'gradlew'
);
...
...
packages/flutter_tools/test/general.shard/analytics_test.dart
View file @
7c618758
...
...
@@ -160,7 +160,6 @@ void main() {
memoryFileSystem
=
MemoryFileSystem
.
test
();
mockStdio
=
MockStdio
();
mockUsage
=
MockUsage
();
when
(
mockUsage
.
isFirstRun
).
thenReturn
(
false
);
mockClock
=
MockClock
();
mockDoctor
=
MockDoctor
();
when
(
mockClock
.
now
()).
thenAnswer
(
...
...
packages/flutter_tools/test/general.shard/reporting/first_run_test.dart
0 → 100644
View file @
7c618758
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:file/memory.dart'
;
import
'package:flutter_tools/src/base/logger.dart'
;
import
'package:flutter_tools/src/persistent_tool_state.dart'
;
import
'package:flutter_tools/src/reporting/first_run.dart'
;
import
'../../src/common.dart'
;
void
main
(
)
{
testWithoutContext
(
'FirstRunMessenger delegates to the first run message'
,
()
{
final
FirstRunMessenger
messenger
=
setUpFirstRunMessenger
();
expect
(
messenger
.
licenseTerms
,
contains
(
'Welcome to Flutter'
));
});
testWithoutContext
(
'FirstRunMessenger requires redisplay if it has never been run before'
,
()
{
final
FirstRunMessenger
messenger
=
setUpFirstRunMessenger
();
expect
(
messenger
.
shouldDisplayLicenseTerms
(),
true
);
expect
(
messenger
.
shouldDisplayLicenseTerms
(),
true
);
// Once terms have been confirmed, then it will return false.
messenger
.
confirmLicenseTermsDisplayed
();
expect
(
messenger
.
shouldDisplayLicenseTerms
(),
false
);
});
testWithoutContext
(
'FirstRunMessenger requires redisplay if the license terms have changed'
,
()
{
final
TestFirstRunMessenger
messenger
=
setUpFirstRunMessenger
(
test:
true
)
as
TestFirstRunMessenger
;
messenger
.
confirmLicenseTermsDisplayed
();
expect
(
messenger
.
shouldDisplayLicenseTerms
(),
false
);
messenger
.
overrideLicenseTerms
=
'This is a new license'
;
expect
(
messenger
.
shouldDisplayLicenseTerms
(),
true
);
});
testWithoutContext
(
'FirstRunMessenger does not require re-display if the persistent tool state disables it'
,
()
{
final
FirstRunMessenger
messenger
=
setUpFirstRunMessenger
(
redisplayWelcomeMessage:
false
);
expect
(
messenger
.
shouldDisplayLicenseTerms
(),
false
);
});
}
FirstRunMessenger
setUpFirstRunMessenger
(
{
bool
redisplayWelcomeMessage
,
bool
test
=
false
})
{
final
MemoryFileSystem
fileSystem
=
MemoryFileSystem
.
test
();
final
PersistentToolState
state
=
PersistentToolState
.
test
(
directory:
fileSystem
.
currentDirectory
,
logger:
BufferLogger
.
test
())
..
redisplayWelcomeMessage
=
redisplayWelcomeMessage
;
if
(
test
)
{
return
TestFirstRunMessenger
(
state
);
}
return
FirstRunMessenger
(
persistentToolState:
state
);
}
class
TestFirstRunMessenger
extends
FirstRunMessenger
{
TestFirstRunMessenger
(
PersistentToolState
persistentToolState
)
:
super
(
persistentToolState:
persistentToolState
);
String
overrideLicenseTerms
;
@override
String
get
licenseTerms
=>
overrideLicenseTerms
??
super
.
licenseTerms
;
}
packages/flutter_tools/test/general.shard/runner/flutter_command_test.dart
View file @
7c618758
...
...
@@ -40,7 +40,6 @@ void main() {
clock
=
MockClock
();
mockProcessInfo
=
MockProcessInfo
();
when
(
usage
.
isFirstRun
).
thenReturn
(
false
);
when
(
clock
.
now
()).
thenAnswer
(
(
Invocation
_
)
=>
DateTime
.
fromMillisecondsSinceEpoch
(
mockTimes
.
removeAt
(
0
))
);
...
...
packages/flutter_tools/test/general.shard/runner/runner_test.dart
View file @
7c618758
...
...
@@ -259,9 +259,6 @@ class CrashingUsage implements Usage {
_sentException
=
exception
;
}
@override
bool
get
isFirstRun
=>
_impl
.
isFirstRun
;
@override
bool
get
suppressAnalytics
=>
_impl
.
suppressAnalytics
;
...
...
packages/flutter_tools/test/src/context.dart
View file @
7c618758
...
...
@@ -331,9 +331,6 @@ class FakeOperatingSystemUtils implements OperatingSystemUtils {
class
MockIOSSimulatorUtils
extends
Mock
implements
IOSSimulatorUtils
{}
class
FakeUsage
implements
Usage
{
@override
bool
get
isFirstRun
=>
false
;
@override
bool
get
suppressAnalytics
=>
false
;
...
...
packages/flutter_tools/test/src/testbed.dart
View file @
7c618758
...
...
@@ -174,9 +174,6 @@ class NoOpUsage implements Usage {
return
null
;
}
@override
bool
get
isFirstRun
=>
false
;
@override
Stream
<
Map
<
String
,
Object
>>
get
onSend
=>
const
Stream
<
Map
<
String
,
Object
>>.
empty
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment