Commit e5fb2fb0 authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

An API for tracking software licenses. (#4711)

parent bbf31cd3
......@@ -13,5 +13,6 @@ export 'src/foundation/assertions.dart';
export 'src/foundation/basic_types.dart';
export 'src/foundation/binding.dart';
export 'src/foundation/change_notifier.dart';
export 'src/foundation/licenses.dart';
export 'src/foundation/print.dart';
export 'src/foundation/synchronous_future.dart';
......@@ -11,6 +11,7 @@ import 'package:meta/meta.dart';
import 'assertions.dart';
import 'basic_types.dart';
import 'licenses.dart';
/// Signature for service extensions.
///
......@@ -74,9 +75,14 @@ abstract class BindingBase {
/// `initInstances()`.
void initInstances() {
assert(!_debugInitialized);
LicenseRegistry.addLicense(_addLicenses);
assert(() { _debugInitialized = true; return true; });
}
Iterable<LicenseEntry> _addLicenses() sync* {
// TODO(ianh): Populate the license registry.
}
/// Called when the binding is initialized, to register service
/// extensions.
///
......
This diff is collapsed.
......@@ -301,7 +301,7 @@ class AboutDialog extends StatelessWidget {
///
/// To show a [LicensePage], use [showLicensePage].
// TODO(ianh): Mention the API for registering more licenses once it exists.
class LicensePage extends StatelessWidget {
class LicensePage extends StatefulWidget {
/// Creates a page that shows licenses for software used by the application.
///
/// The arguments are all optional. The application name, if omitted, will be
......@@ -337,27 +337,73 @@ class LicensePage extends StatelessWidget {
/// Defaults to the empty string.
final String applicationLegalese;
@override
_LicensePageState createState() => new _LicensePageState();
}
class _LicensePageState extends State<LicensePage> {
List<Widget> _licenses = _initLicenses();
static List<Widget> _initLicenses() {
List<Widget> result = <Widget>[];
for (LicenseEntry license in LicenseRegistry.licenses) {
bool haveMargin = true;
result.add(new Padding(
padding: new EdgeInsets.symmetric(vertical: 18.0),
child: new Text(
'🍀‬', // That's U+1F340. Could also use U+2766 (❦) if U+1F340 doesn't work everywhere.
textAlign: TextAlign.center
)
));
for (LicenseParagraph paragraph in license.paragraphs) {
if (paragraph.indent == LicenseParagraph.centeredIndent) {
result.add(new Padding(
padding: new EdgeInsets.only(top: haveMargin ? 0.0 : 16.0),
child: new Text(
paragraph.text,
style: new TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.center
)
));
} else {
assert(paragraph.indent >= 0);
result.add(new Padding(
padding: new EdgeInsets.only(top: haveMargin ? 0.0 : 8.0, left: 16.0 * paragraph.indent),
child: new Text(paragraph.text)
));
}
haveMargin = false;
}
}
return result;
}
@override
Widget build(BuildContext context) {
final String name = applicationName ?? _defaultApplicationName(context);
final String version = applicationVersion ?? _defaultApplicationVersion(context);
final String name = config.applicationName ?? _defaultApplicationName(context);
final String version = config.applicationVersion ?? _defaultApplicationVersion(context);
final List<Widget> contents = <Widget>[
new Text(name, style: Theme.of(context).textTheme.headline, textAlign: TextAlign.center),
new Text(version, style: Theme.of(context).textTheme.body1, textAlign: TextAlign.center),
new Container(height: 18.0),
new Text(config.applicationLegalese ?? '', style: Theme.of(context).textTheme.caption, textAlign: TextAlign.center),
new Container(height: 18.0),
new Text('Powered by Flutter', style: Theme.of(context).textTheme.body1, textAlign: TextAlign.center),
new Container(height: 24.0),
];
contents.addAll(_licenses);
return new Scaffold(
appBar: new AppBar(
title: new Text('Licenses')
),
body: new Block(
padding: new EdgeInsets.symmetric(horizontal: 8.0, vertical: 12.0),
children: <Widget>[
new Text(name, style: Theme.of(context).textTheme.headline, textAlign: TextAlign.center),
new Text(version, style: Theme.of(context).textTheme.body1, textAlign: TextAlign.center),
new Container(height: 18.0),
new Text(applicationLegalese ?? '', style: Theme.of(context).textTheme.caption, textAlign: TextAlign.center),
new Container(height: 18.0),
new Text('Powered by Flutter', style: Theme.of(context).textTheme.body1, textAlign: TextAlign.center),
new Container(height: 24.0),
// TODO(ianh): Fill in the licenses from the API for registering more licenses once it exists.
new Text('<licenses will be automatically included here>', style: Theme.of(context).textTheme.caption)
]
body: new DefaultTextStyle(
style: Theme.of(context).textTheme.caption,
child: new LazyBlock(
padding: new EdgeInsets.symmetric(horizontal: 8.0, vertical: 12.0),
delegate: new LazyBlockChildren(
children: contents
)
)
)
);
}
......
// Copyright 2016 The Chromium 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:flutter/foundation.dart';
import 'package:test/test.dart';
void main() {
test('LicenseEntryWithLineBreaks - most cases', () {
// There's some trailing spaces in this string.
// To avoid IDEs stripping them, I've escaped them as \u0020.
List<LicenseParagraph> paragraphs = new LicenseEntryWithLineBreaks('''
A
A
A
B
B
B
C
C
C
D
D
D
E
E
F
G
G
G
[H
H
H]
\u0020\u0020
I J
K
K
L
L L
L L
L L
L L
L L
M
M\u0020\u0020\u0020
M\u0020\u0020\u0020\u0020
N
O
O
P
QQQ
RR RRR RRRR RRRRR
R
S
T
U
V
W
X
\u0020\u0020\u0020\u0020\u0020\u0020
Y''').paragraphs.toList();
int index = 0;
expect(paragraphs[index].text, 'A A A');
expect(paragraphs[index].indent, 0);
index += 1;
expect(paragraphs[index].text, 'B B B');
expect(paragraphs[index].indent, 0);
index += 1;
expect(paragraphs[index].text, 'C C C');
expect(paragraphs[index].indent, 1);
index += 1;
expect(paragraphs[index].text, 'D D D');
expect(paragraphs[index].indent, LicenseParagraph.centeredIndent);
index += 1;
expect(paragraphs[index].text, 'E E');
expect(paragraphs[index].indent, 0);
index += 1;
expect(paragraphs[index].text, 'F');
expect(paragraphs[index].indent, 0);
index += 1;
expect(paragraphs[index].text, 'G G G');
expect(paragraphs[index].indent, 0);
index += 1;
expect(paragraphs[index].text, '[H H H]');
expect(paragraphs[index].indent, 0);
index += 1;
expect(paragraphs[index].text, 'I');
expect(paragraphs[index].indent, 0);
index += 1;
expect(paragraphs[index].text, 'J');
expect(paragraphs[index].indent, 0);
index += 1;
expect(paragraphs[index].text, 'K K');
expect(paragraphs[index].indent, 0);
index += 1;
expect(paragraphs[index].text, 'L L L L L L L L L L L');
expect(paragraphs[index].indent, 0);
index += 1;
expect(paragraphs[index].text, 'M M M ');
expect(paragraphs[index].indent, 1);
index += 1;
expect(paragraphs[index].text, 'N');
expect(paragraphs[index].indent, 0);
index += 1;
expect(paragraphs[index].text, 'O O');
expect(paragraphs[index].indent, 0);
index += 1;
expect(paragraphs[index].text, 'P');
expect(paragraphs[index].indent, 0);
index += 1;
expect(paragraphs[index].text, 'QQQ');
expect(paragraphs[index].indent, 0);
index += 1;
expect(paragraphs[index].text, 'RR RRR RRRR RRRRR R');
expect(paragraphs[index].indent, 0);
index += 1;
expect(paragraphs[index].text, 'S');
expect(paragraphs[index].indent, 0);
index += 1;
expect(paragraphs[index].text, 'T');
expect(paragraphs[index].indent, 1);
index += 1;
expect(paragraphs[index].text, 'U');
expect(paragraphs[index].indent, 2);
index += 1;
expect(paragraphs[index].text, 'V');
expect(paragraphs[index].indent, 3);
index += 1;
expect(paragraphs[index].text, 'W');
expect(paragraphs[index].indent, 2);
index += 1;
expect(paragraphs[index].text, 'X');
expect(paragraphs[index].indent, 2);
index += 1;
expect(paragraphs[index].text, 'Y');
expect(paragraphs[index].indent, 2);
index += 1;
expect(paragraphs, hasLength(index));
});
test('LicenseEntryWithLineBreaks - leading and trailing whitespace', () {
expect(new LicenseEntryWithLineBreaks(' \n\n ').paragraphs.toList(), isEmpty);
List<LicenseParagraph> paragraphs;
paragraphs = new LicenseEntryWithLineBreaks(' \nA\n ').paragraphs.toList();
expect(paragraphs[0].text, 'A');
expect(paragraphs[0].indent, 0);
expect(paragraphs, hasLength(1));
paragraphs = new LicenseEntryWithLineBreaks('\n\n\nA\n\n\n').paragraphs.toList();
expect(paragraphs[0].text, 'A');
expect(paragraphs[0].indent, 0);
expect(paragraphs, hasLength(1));
});
test('LicenseRegistry', () {
expect(LicenseRegistry.licenses, isEmpty);
LicenseRegistry.addLicense(() {
return <LicenseEntry>[
new LicenseEntryWithLineBreaks('A'),
new LicenseEntryWithLineBreaks('B'),
];
});
LicenseRegistry.addLicense(() {
return <LicenseEntry>[
new LicenseEntryWithLineBreaks('C'),
new LicenseEntryWithLineBreaks('D'),
];
});
expect(LicenseRegistry.licenses, hasLength(4));
List<LicenseEntry> licenses = LicenseRegistry.licenses.toList();
expect(licenses, hasLength(4));
expect(licenses[0].paragraphs.single.text, 'A');
expect(licenses[1].paragraphs.single.text, 'B');
expect(licenses[2].paragraphs.single.text, 'C');
expect(licenses[3].paragraphs.single.text, 'D');
});
}
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