Unverified Commit 5d30c097 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools][web] Add support for web app manifests and arbitrary resource...

[flutter_tools][web] Add support for web app manifests and arbitrary resource files (from web/) (#48316)

parent 749589d8
......@@ -761,6 +761,13 @@ final Set<Hash256> _grandfatheredBinaries = <Hash256>{
// (also used by a few examples)
Hash256(0xD29D4E0AF9256DC9, 0x2D0A8F8810608A5E, 0x64A132AD8B397CA2, 0xC4DDC0B1C26A68C3),
// packages/flutter_tools/templates/app/web/icons/Icon-192.png.copy.tmpl
// examples/flutter_gallery/web/icons/Icon-192.png
Hash256(0x3DCE99077602F704, 0x21C1C6B2A240BC9B, 0x83D64D86681D45F2, 0x154143310C980BE3),
// packages/flutter_tools/templates/app/web/icons/Icon-512.png.copy.tmpl
// examples/flutter_gallery/web/icons/Icon-512.png
Hash256(0xBACCB205AE45f0B4, 0x21BE1657259B4943, 0xAC40C95094AB877F, 0x3BCBE12CD544DCBE),
// GALLERY ICONS
......@@ -994,7 +1001,7 @@ Future<void> verifyNoBinaries(String workingDirectory, { Set<Hash256> grandfathe
assert(
_grandfatheredBinaries
.expand<int>((Hash256 hash) => <int>[hash.a, hash.b, hash.c, hash.d])
.reduce((int value, int element) => value ^ element) == 0x39A050CD69434936 // Please do not modify this line.
.reduce((int value, int element) => value ^ element) == 0xBFC18DE113B5AE8E // Please do not modify this line.
);
grandfatheredBinaries ??= _grandfatheredBinaries;
if (!Platform.isWindows) { // TODO(ianh): Port this to Windows
......
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
......@@ -3,10 +3,21 @@
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<html>
<head>
<title>Flutter Gallery</title>
</head>
<body>
<script src="main.dart.js"></script>
</body>
<head>
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="A demo app for Flutter's material design and cupertino widgets, as well as many other features of the Flutter SDK.">
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="Flutter Gallery">
<link rel="apple-touch-icon" href="/icons/Icon-192.png">
<title>Flutter Gallery</title>
<link rel="manifest" href="/manifest.json">
</head>
<body>
<script src="main.dart.js" type="application/javascript"></script>
</body>
</html>
{
"name": "flutter_gallery",
"short_name": "flutter_gallery",
"start_url": ".",
"display": "minimal-ui",
"background_color": "#0175C2",
"theme_color": "#0175C2",
"description": "A new Flutter project.",
"orientation": "portrait-primary",
"prefer_related_applications": false,
"icons": [
{
"src": "icons/Icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icons/Icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
......@@ -198,7 +198,7 @@ class Dart2JSTarget extends Target {
}
}
/// Unpacks the dart2js compilation to a given output directory
/// Unpacks the dart2js compilation and resources to a given output directory
class WebReleaseBundle extends Target {
const WebReleaseBundle();
......@@ -214,18 +214,18 @@ class WebReleaseBundle extends Target {
List<Source> get inputs => const <Source>[
Source.pattern('{BUILD_DIR}/main.dart.js'),
Source.pattern('{PROJECT_DIR}/pubspec.yaml'),
Source.pattern('{PROJECT_DIR}/web/index.html'),
];
@override
List<Source> get outputs => const <Source>[
Source.pattern('{OUTPUT_DIR}/main.dart.js'),
Source.pattern('{OUTPUT_DIR}/index.html'),
];
@override
List<String> get depfiles => const <String>[
'dart2js.d',
'flutter_assets.d',
'web_resources.d',
];
@override
......@@ -240,11 +240,30 @@ class WebReleaseBundle extends Target {
}
final Directory outputDirectory = environment.outputDir.childDirectory('assets');
outputDirectory.createSync(recursive: true);
environment.projectDir
.childDirectory('web')
.childFile('index.html')
.copySync(globals.fs.path.join(environment.outputDir.path, 'index.html'));
final Depfile depfile = await copyAssets(environment, environment.outputDir.childDirectory('assets'));
depfile.writeToFile(environment.buildDir.childFile('flutter_assets.d'));
final Directory webResources = environment.projectDir
.childDirectory('web');
final List<File> inputResourceFiles = webResources
.listSync(recursive: true)
.whereType<File>()
.toList();
// Copy other resource files out of web/ directory.
final List<File> outputResourcesFiles = <File>[];
for (final File inputFile in inputResourceFiles) {
final File outputFile = globals.fs.file(globals.fs.path.join(
environment.outputDir.path,
globals.fs.path.relative(inputFile.path, from: webResources.path)));
if (!outputFile.parent.existsSync()) {
outputFile.parent.createSync(recursive: true);
}
inputFile.copySync(outputFile.path);
outputResourcesFiles.add(outputFile);
}
final Depfile resourceFile = Depfile(inputResourceFiles, outputResourcesFiles);
resourceFile.writeToFile(environment.buildDir.childFile('web_resources.d'));
}
}
......@@ -2,7 +2,17 @@
<html>
<head>
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="{{description}}">
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="{{projectName}}">
<link rel="apple-touch-icon" href="/icons/Icon-192.png">
<title>{{projectName}}</title>
<link rel="manifest" href="/manifest.json">
</head>
<body>
<script src="main.dart.js" type="application/javascript"></script>
......
{
"name": "{{projectName}}",
"short_name": "{{projectName}}",
"start_url": ".",
"display": "minimal-ui",
"background_color": "#0175C2",
"theme_color": "#0175C2",
"description": "{{description}}",
"orientation": "portrait-primary",
"prefer_related_applications": false,
"icons": [
{
"src": "icons/Icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icons/Icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
......@@ -31,6 +31,7 @@ void main() {
when(mockPlatform.isWindows).thenReturn(false);
when(mockPlatform.isMacOS).thenReturn(true);
when(mockPlatform.isLinux).thenReturn(false);
when(mockPlatform.environment).thenReturn(const <String, String>{});
when(mockWindowsPlatform.isWindows).thenReturn(true);
when(mockWindowsPlatform.isMacOS).thenReturn(false);
......@@ -41,10 +42,11 @@ void main() {
..createSync(recursive: true)
..writeAsStringSync('foo:lib/\n');
PackageMap.globalPackagesPath = packagesFile.path;
globals.fs.currentDirectory.childDirectory('bar').createSync();
environment = Environment(
projectDir: globals.fs.currentDirectory.childDirectory('foo'),
outputDir: globals.fs.currentDirectory,
outputDir: globals.fs.currentDirectory.childDirectory('bar'),
buildDir: globals.fs.currentDirectory,
defines: <String, String>{
kTargetFile: globals.fs.path.join('foo', 'lib', 'main.dart'),
......@@ -77,6 +79,32 @@ void main() {
expect(generated, contains("import 'package:foo/main.dart' as entrypoint;"));
}));
test('WebReleaseBundle copies dart2js output and resource files to output directory', () => testbed.run(() async {
final Directory webResources = environment.projectDir.childDirectory('web');
webResources.childFile('index.html')
..createSync(recursive: true);
webResources.childFile('foo.txt')
..writeAsStringSync('A');
environment.buildDir.childFile('main.dart.js').createSync();
await const WebReleaseBundle().build(environment);
expect(environment.outputDir.childFile('foo.txt')
.readAsStringSync(), 'A');
expect(environment.outputDir.childFile('main.dart.js')
.existsSync(), true);
expect(environment.outputDir.childDirectory('assets')
.childFile('AssetManifest.json').existsSync(), true);
// Update to arbitary resource file triggers rebuild.
webResources.childFile('foo.txt').writeAsStringSync('B');
await const WebReleaseBundle().build(environment);
expect(environment.outputDir.childFile('foo.txt')
.readAsStringSync(), 'B');
}));
test('WebEntrypointTarget generates an entrypoint for a file outside of main', () => testbed.run(() async {
environment.defines[kTargetFile] = globals.fs.path.join('other', 'lib', 'main.dart');
await const WebEntrypointTarget().build(environment);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment