Merge in the flutter gallery (#176)
@ -0,0 +1,30 @@
|
|||||||
|
# Flutter Gallery
|
||||||
|
|
||||||
|
Flutter Gallery is a resource to help developers evaluate and use Flutter.
|
||||||
|
It is a collection of material design widgets, behaviors, and vignettes
|
||||||
|
implemented with Flutter. We often get asked how one can see Flutter in
|
||||||
|
action, and this gallery demonstrates what Flutter provides and how it
|
||||||
|
behaves in the wild.
|
||||||
|
|
||||||
|
## Supported Platforms
|
||||||
|
|
||||||
|
The Flutter Gallery application has been built to support multiple platforms. This includes:
|
||||||
|
|
||||||
|
* Android
|
||||||
|
* iOS
|
||||||
|
* web
|
||||||
|
* macOS
|
||||||
|
* Linux
|
||||||
|
* Windows
|
||||||
|
|
||||||
|
That being said, extra steps must be taken to [enable Desktop support](https://github.com/flutter/flutter/wiki/Desktop-shells#tooling).
|
||||||
|
|
||||||
|
Additionally, the UI adapts between mobile and desktop layouts regardless of the platform it runs on. This is determined based on window size as outlined in [adaptive.dart](https://github.com/material-components/material-components-flutter-gallery/blob/master/gallery/lib/layout/adaptive.dart).
|
||||||
|
|
||||||
|
## To include a new splash animation
|
||||||
|
|
||||||
|
1. Convert your animation to a `.gif` file. Ideally, use a background color of `0xFF030303` to ensure the animation blends into the background of the app.
|
||||||
|
|
||||||
|
2. Add your new `.gif` file to the assets directory under `assets/splash_effects`. Ensure the name follows the format `splash_effect_$num.gif`. The number should be the next number after the current largest number in the repository.
|
||||||
|
|
||||||
|
3. Update the map `_effectDurations` in [splash.dart](https://github.com/material-components/material-components-flutter-gallery/blob/master/gallery/lib/pages/splash.dart) to include the number of the new `.gif` as well as its estimated duration. The duration is used to determine how long to display the splash animation at launch.
|
@ -0,0 +1,11 @@
|
|||||||
|
# Files and directories created by pub
|
||||||
|
.dart_tool/
|
||||||
|
.packages
|
||||||
|
# Remove the following pattern if you wish to check in your lock file
|
||||||
|
pubspec.lock
|
||||||
|
|
||||||
|
# Conventional directory for build outputs
|
||||||
|
build/
|
||||||
|
|
||||||
|
# Directory created by dartdoc
|
||||||
|
doc/api/
|
@ -0,0 +1,3 @@
|
|||||||
|
## 1.0.0
|
||||||
|
|
||||||
|
- Initial version
|
@ -0,0 +1,55 @@
|
|||||||
|
A command-line application to highlight dart source code.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Code segments are highlighted before the app is compiled.
|
||||||
|
This is done because the highlighting process can take 300ms to finish, creating a noticeable delay when the demo switches to code page.
|
||||||
|
|
||||||
|
The highlighter takes all files in the `gallery/lib/demos/` folder and scans each.
|
||||||
|
Highlighted code widgets are stored in the `gallery/lib/codeviewer/code_segments.dart` file.
|
||||||
|
Under the root directory, run `make update-code-segments` to run the highlighter.
|
||||||
|
|
||||||
|
Wrap a block of code with lines `// BEGIN yourDemoName` and `// END` to mark it for highlighting. The block in between, as well as any copyright notice and imports at the beginning of the file, are automatically taken and highlighted, and stored as `static TextSpan yourDemoName(BuildContext context)` in `gallery/lib/codeviewer/code_segments.dart`.
|
||||||
|
To display the code, go to `gallery/lib/data/demos.dart`, and add `code: CodeSegments.yourDemoName,` to your `GalleryDemoConfiguration` object.
|
||||||
|
|
||||||
|
## Multiple blocks of code
|
||||||
|
|
||||||
|
Use the following method to join multiple blocks of code into a single segment:
|
||||||
|
```
|
||||||
|
// BEGIN yourDemo#2
|
||||||
|
a();
|
||||||
|
// END
|
||||||
|
b();
|
||||||
|
// BEGIN yourDemo#1
|
||||||
|
c();
|
||||||
|
// END
|
||||||
|
```
|
||||||
|
The generated code will be
|
||||||
|
```
|
||||||
|
c();
|
||||||
|
a();
|
||||||
|
```
|
||||||
|
|
||||||
|
Code blocks can nest or overlap. In these cases, specify which file(s) to `END`.
|
||||||
|
|
||||||
|
The following source file
|
||||||
|
```
|
||||||
|
// BEGIN demoOne
|
||||||
|
a();
|
||||||
|
// BEGIN demoTwo
|
||||||
|
b();
|
||||||
|
// END demoOne
|
||||||
|
c();
|
||||||
|
// END demoTwo
|
||||||
|
```
|
||||||
|
will create the following segments:
|
||||||
|
(demoOne)
|
||||||
|
```
|
||||||
|
a();
|
||||||
|
b();
|
||||||
|
```
|
||||||
|
(demoTwo)
|
||||||
|
```
|
||||||
|
b();
|
||||||
|
c();
|
||||||
|
```
|
@ -0,0 +1,39 @@
|
|||||||
|
# Defines a default set of lint rules enforced for
|
||||||
|
# projects at Google. For details and rationale,
|
||||||
|
# see https://github.com/dart-lang/pedantic#enabled-lints.
|
||||||
|
include: package:pedantic/analysis_options.yaml
|
||||||
|
|
||||||
|
# For lint rules and documentation, see http://dart-lang.github.io/linter/lints.
|
||||||
|
# Uncomment to specify additional rules.
|
||||||
|
# linter:
|
||||||
|
# rules:
|
||||||
|
# - camel_case_types
|
||||||
|
|
||||||
|
analyzer:
|
||||||
|
# exclude:
|
||||||
|
# - path/to/excluded/files/**
|
||||||
|
|
||||||
|
linter:
|
||||||
|
rules:
|
||||||
|
- avoid_types_on_closure_parameters
|
||||||
|
- avoid_void_async
|
||||||
|
- await_only_futures
|
||||||
|
- camel_case_types
|
||||||
|
- cancel_subscriptions
|
||||||
|
- close_sinks
|
||||||
|
- constant_identifier_names
|
||||||
|
- control_flow_in_finally
|
||||||
|
- empty_statements
|
||||||
|
- hash_and_equals
|
||||||
|
- implementation_imports
|
||||||
|
- non_constant_identifier_names
|
||||||
|
- package_api_docs
|
||||||
|
- package_names
|
||||||
|
- package_prefixed_library_names
|
||||||
|
- test_types_in_equals
|
||||||
|
- throw_in_finally
|
||||||
|
- unnecessary_brace_in_string_interps
|
||||||
|
- unnecessary_getters_setters
|
||||||
|
- unnecessary_new
|
||||||
|
- unnecessary_statements
|
||||||
|
- directives_ordering
|
@ -0,0 +1,12 @@
|
|||||||
|
// Copyright 2019 The Flutter team. 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:codeviewer_cli/segment_generator.dart';
|
||||||
|
|
||||||
|
main(List<String> arguments) {
|
||||||
|
writeSegments(
|
||||||
|
sourceDirectoryPath: '../gallery/lib/demos',
|
||||||
|
targetFilePath: '../gallery/lib/codeviewer/code_segments.dart',
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,412 @@
|
|||||||
|
// Copyright 2019 The Flutter team. 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:string_scanner/string_scanner.dart';
|
||||||
|
|
||||||
|
abstract class SyntaxPrehighlighter {
|
||||||
|
List<CodeSpan> format(String src);
|
||||||
|
}
|
||||||
|
|
||||||
|
class DartSyntaxPrehighlighter extends SyntaxPrehighlighter {
|
||||||
|
DartSyntaxPrehighlighter() {
|
||||||
|
_spans = <_HighlightSpan>[];
|
||||||
|
}
|
||||||
|
|
||||||
|
static const List<String> _keywords = <String>[
|
||||||
|
'abstract',
|
||||||
|
'as',
|
||||||
|
'assert',
|
||||||
|
'async',
|
||||||
|
'await',
|
||||||
|
'break',
|
||||||
|
'case',
|
||||||
|
'catch',
|
||||||
|
'class',
|
||||||
|
'const',
|
||||||
|
'continue',
|
||||||
|
'default',
|
||||||
|
'deferred',
|
||||||
|
'do',
|
||||||
|
'dynamic',
|
||||||
|
'else',
|
||||||
|
'enum',
|
||||||
|
'export',
|
||||||
|
'external',
|
||||||
|
'extends',
|
||||||
|
'factory',
|
||||||
|
'false',
|
||||||
|
'final',
|
||||||
|
'finally',
|
||||||
|
'for',
|
||||||
|
'get',
|
||||||
|
'if',
|
||||||
|
'implements',
|
||||||
|
'import',
|
||||||
|
'in',
|
||||||
|
'is',
|
||||||
|
'library',
|
||||||
|
'new',
|
||||||
|
'null',
|
||||||
|
'operator',
|
||||||
|
'part',
|
||||||
|
'rethrow',
|
||||||
|
'return',
|
||||||
|
'set',
|
||||||
|
'static',
|
||||||
|
'super',
|
||||||
|
'switch',
|
||||||
|
'sync',
|
||||||
|
'this',
|
||||||
|
'throw',
|
||||||
|
'true',
|
||||||
|
'try',
|
||||||
|
'typedef',
|
||||||
|
'var',
|
||||||
|
'void',
|
||||||
|
'while',
|
||||||
|
'with',
|
||||||
|
'yield',
|
||||||
|
];
|
||||||
|
|
||||||
|
static const List<String> _builtInTypes = <String>[
|
||||||
|
'int',
|
||||||
|
'double',
|
||||||
|
'num',
|
||||||
|
'bool',
|
||||||
|
];
|
||||||
|
|
||||||
|
String _src;
|
||||||
|
StringScanner _scanner;
|
||||||
|
|
||||||
|
List<_HighlightSpan> _spans;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<CodeSpan> format(String src) {
|
||||||
|
_src = src;
|
||||||
|
_scanner = StringScanner(_src);
|
||||||
|
|
||||||
|
if (_generateSpans()) {
|
||||||
|
// Successfully parsed the code
|
||||||
|
final List<CodeSpan> formattedText = <CodeSpan>[];
|
||||||
|
int currentPosition = 0;
|
||||||
|
|
||||||
|
for (_HighlightSpan span in _spans) {
|
||||||
|
if (currentPosition != span.start) {
|
||||||
|
formattedText
|
||||||
|
.add(CodeSpan(text: _src.substring(currentPosition, span.start)));
|
||||||
|
}
|
||||||
|
|
||||||
|
formattedText
|
||||||
|
.add(CodeSpan(type: span.type, text: span.textForSpan(_src)));
|
||||||
|
|
||||||
|
currentPosition = span.end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPosition != _src.length) {
|
||||||
|
formattedText
|
||||||
|
.add(CodeSpan(text: _src.substring(currentPosition, _src.length)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return formattedText;
|
||||||
|
} else {
|
||||||
|
// Parsing failed, return with only basic formatting
|
||||||
|
return [CodeSpan(type: _HighlightType.base, text: src)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _generateSpans() {
|
||||||
|
int lastLoopPosition = _scanner.position;
|
||||||
|
|
||||||
|
while (!_scanner.isDone) {
|
||||||
|
// Skip White space
|
||||||
|
_scanner.scan(RegExp(r'\s+'));
|
||||||
|
|
||||||
|
// Block comments
|
||||||
|
if (_scanner.scan(RegExp(r'/\*(.|\n)*\*/'))) {
|
||||||
|
_spans.add(_HighlightSpan(
|
||||||
|
_HighlightType.comment,
|
||||||
|
_scanner.lastMatch.start,
|
||||||
|
_scanner.lastMatch.end,
|
||||||
|
));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Line comments
|
||||||
|
if (_scanner.scan('//')) {
|
||||||
|
final int startComment = _scanner.lastMatch.start;
|
||||||
|
|
||||||
|
bool eof = false;
|
||||||
|
int endComment;
|
||||||
|
if (_scanner.scan(RegExp(r'.*\n'))) {
|
||||||
|
endComment = _scanner.lastMatch.end - 1;
|
||||||
|
} else {
|
||||||
|
eof = true;
|
||||||
|
endComment = _src.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
_spans.add(_HighlightSpan(
|
||||||
|
_HighlightType.comment,
|
||||||
|
startComment,
|
||||||
|
endComment,
|
||||||
|
));
|
||||||
|
|
||||||
|
if (eof) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Raw r"String"
|
||||||
|
if (_scanner.scan(RegExp(r'r".*"'))) {
|
||||||
|
_spans.add(_HighlightSpan(
|
||||||
|
_HighlightType.string,
|
||||||
|
_scanner.lastMatch.start,
|
||||||
|
_scanner.lastMatch.end,
|
||||||
|
));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Raw r'String'
|
||||||
|
if (_scanner.scan(RegExp(r"r'.*'"))) {
|
||||||
|
_spans.add(_HighlightSpan(
|
||||||
|
_HighlightType.string,
|
||||||
|
_scanner.lastMatch.start,
|
||||||
|
_scanner.lastMatch.end,
|
||||||
|
));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiline """String"""
|
||||||
|
if (_scanner.scan(RegExp(r'"""(?:[^"\\]|\\(.|\n))*"""'))) {
|
||||||
|
_spans.add(_HighlightSpan(
|
||||||
|
_HighlightType.string,
|
||||||
|
_scanner.lastMatch.start,
|
||||||
|
_scanner.lastMatch.end,
|
||||||
|
));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiline '''String'''
|
||||||
|
if (_scanner.scan(RegExp(r"'''(?:[^'\\]|\\(.|\n))*'''"))) {
|
||||||
|
_spans.add(_HighlightSpan(
|
||||||
|
_HighlightType.string,
|
||||||
|
_scanner.lastMatch.start,
|
||||||
|
_scanner.lastMatch.end,
|
||||||
|
));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "String"
|
||||||
|
if (_scanner.scan(RegExp(r'"(?:[^"\\]|\\.)*"'))) {
|
||||||
|
_spans.add(_HighlightSpan(
|
||||||
|
_HighlightType.string,
|
||||||
|
_scanner.lastMatch.start,
|
||||||
|
_scanner.lastMatch.end,
|
||||||
|
));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'String'
|
||||||
|
if (_scanner.scan(RegExp(r"'(?:[^'\\]|\\.)*'"))) {
|
||||||
|
_spans.add(_HighlightSpan(
|
||||||
|
_HighlightType.string,
|
||||||
|
_scanner.lastMatch.start,
|
||||||
|
_scanner.lastMatch.end,
|
||||||
|
));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Double
|
||||||
|
if (_scanner.scan(RegExp(r'\d+\.\d+'))) {
|
||||||
|
_spans.add(_HighlightSpan(
|
||||||
|
_HighlightType.number,
|
||||||
|
_scanner.lastMatch.start,
|
||||||
|
_scanner.lastMatch.end,
|
||||||
|
));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Integer
|
||||||
|
if (_scanner.scan(RegExp(r'\d+'))) {
|
||||||
|
_spans.add(_HighlightSpan(_HighlightType.number,
|
||||||
|
_scanner.lastMatch.start, _scanner.lastMatch.end));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Punctuation
|
||||||
|
if (_scanner.scan(RegExp(r'[\[\]{}().!=<>&\|\?\+\-\*/%\^~;:,]'))) {
|
||||||
|
_spans.add(_HighlightSpan(
|
||||||
|
_HighlightType.punctuation,
|
||||||
|
_scanner.lastMatch.start,
|
||||||
|
_scanner.lastMatch.end,
|
||||||
|
));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Meta data
|
||||||
|
if (_scanner.scan(RegExp(r'@\w+'))) {
|
||||||
|
_spans.add(_HighlightSpan(
|
||||||
|
_HighlightType.keyword,
|
||||||
|
_scanner.lastMatch.start,
|
||||||
|
_scanner.lastMatch.end,
|
||||||
|
));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Words
|
||||||
|
if (_scanner.scan(RegExp(r'\w+'))) {
|
||||||
|
_HighlightType type;
|
||||||
|
|
||||||
|
String word = _scanner.lastMatch[0];
|
||||||
|
if (word.startsWith('_')) {
|
||||||
|
word = word.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_keywords.contains(word)) {
|
||||||
|
type = _HighlightType.keyword;
|
||||||
|
} else if (_builtInTypes.contains(word)) {
|
||||||
|
type = _HighlightType.keyword;
|
||||||
|
} else if (_firstLetterIsUpperCase(word)) {
|
||||||
|
type = _HighlightType.klass;
|
||||||
|
} else if (word.length >= 2 &&
|
||||||
|
word.startsWith('k') &&
|
||||||
|
_firstLetterIsUpperCase(word.substring(1))) {
|
||||||
|
type = _HighlightType.constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type != null) {
|
||||||
|
_spans.add(_HighlightSpan(
|
||||||
|
type,
|
||||||
|
_scanner.lastMatch.start,
|
||||||
|
_scanner.lastMatch.end,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this loop did anything
|
||||||
|
if (lastLoopPosition == _scanner.position) {
|
||||||
|
// Failed to parse this file, abort gracefully
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
lastLoopPosition = _scanner.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
_simplify();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _simplify() {
|
||||||
|
for (int i = _spans.length - 2; i >= 0; i -= 1) {
|
||||||
|
if (_spans[i].type == _spans[i + 1].type &&
|
||||||
|
_spans[i].end == _spans[i + 1].start) {
|
||||||
|
_spans[i] = _HighlightSpan(
|
||||||
|
_spans[i].type,
|
||||||
|
_spans[i].start,
|
||||||
|
_spans[i + 1].end,
|
||||||
|
);
|
||||||
|
_spans.removeAt(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _firstLetterIsUpperCase(String str) {
|
||||||
|
if (str.isNotEmpty) {
|
||||||
|
final String first = str.substring(0, 1);
|
||||||
|
return first == first.toUpperCase();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum _HighlightType {
|
||||||
|
number,
|
||||||
|
comment,
|
||||||
|
keyword,
|
||||||
|
string,
|
||||||
|
punctuation,
|
||||||
|
klass,
|
||||||
|
constant,
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HighlightSpan {
|
||||||
|
_HighlightSpan(this.type, this.start, this.end);
|
||||||
|
final _HighlightType type;
|
||||||
|
final int start;
|
||||||
|
final int end;
|
||||||
|
|
||||||
|
String textForSpan(String src) {
|
||||||
|
return src.substring(start, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CodeSpan {
|
||||||
|
CodeSpan({this.type = _HighlightType.base, this.text});
|
||||||
|
|
||||||
|
final _HighlightType type;
|
||||||
|
final String text;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'TextSpan('
|
||||||
|
'style: codeStyle.${_styleNameOf(type)}, '
|
||||||
|
"text: '${_escape(text)}'"
|
||||||
|
')';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String _styleNameOf(_HighlightType type) {
|
||||||
|
switch (type) {
|
||||||
|
case _HighlightType.number:
|
||||||
|
return 'numberStyle';
|
||||||
|
case _HighlightType.comment:
|
||||||
|
return 'commentStyle';
|
||||||
|
case _HighlightType.keyword:
|
||||||
|
return 'keywordStyle';
|
||||||
|
case _HighlightType.string:
|
||||||
|
return 'stringStyle';
|
||||||
|
case _HighlightType.punctuation:
|
||||||
|
return 'punctuationStyle';
|
||||||
|
case _HighlightType.klass:
|
||||||
|
return 'classStyle';
|
||||||
|
case _HighlightType.constant:
|
||||||
|
return 'constantStyle';
|
||||||
|
case _HighlightType.base:
|
||||||
|
return 'baseStyle';
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
String _escape(String text) {
|
||||||
|
StringBuffer escapedText = StringBuffer();
|
||||||
|
|
||||||
|
for (final char in text.runes) {
|
||||||
|
if (char < 0x20 ||
|
||||||
|
char >= 0x7F ||
|
||||||
|
char == 0x22 ||
|
||||||
|
char == 0x24 ||
|
||||||
|
char == 0x27 ||
|
||||||
|
char == 0x5C) {
|
||||||
|
if (char <= 0xffff) {
|
||||||
|
escapedText.write("\\u${_encodeAndPad(char)}");
|
||||||
|
} else {
|
||||||
|
escapedText.write("\\u{${_encode(char)}}");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
escapedText.write(String.fromCharCode(char));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return escapedText.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
String _encode(int charCode) {
|
||||||
|
return charCode.toRadixString(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
String _encodeAndPad(int charCode) {
|
||||||
|
String encoded = _encode(charCode);
|
||||||
|
return '0' * (4 - encoded.length) + encoded;
|
||||||
|
}
|
@ -0,0 +1,266 @@
|
|||||||
|
// Copyright 2019 The Flutter team. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
import 'prehighlighter.dart';
|
||||||
|
|
||||||
|
const _globalPrologue =
|
||||||
|
'''// This file is automatically generated by codeviewer_cli.
|
||||||
|
// Do not edit this file.
|
||||||
|
|
||||||
|
// Copyright 2019 The Flutter team. 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/material.dart';
|
||||||
|
import 'package:gallery/codeviewer/code_style.dart';
|
||||||
|
|
||||||
|
class CodeSegments {
|
||||||
|
''';
|
||||||
|
|
||||||
|
const _globalEpilogue = '}\n';
|
||||||
|
|
||||||
|
final Pattern beginSubsegment = RegExp(r'//\s+BEGIN');
|
||||||
|
final Pattern endSubsegment = RegExp(r'//\s+END');
|
||||||
|
|
||||||
|
enum _FileReadStatus {
|
||||||
|
comments,
|
||||||
|
imports,
|
||||||
|
finished,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the new status of the scanner whose previous status was
|
||||||
|
/// [oldStatus], after scanning the line [line].
|
||||||
|
_FileReadStatus _updatedStatus(_FileReadStatus oldStatus, String line) {
|
||||||
|
_FileReadStatus lineStatus;
|
||||||
|
if (line.trim().startsWith('//')) {
|
||||||
|
lineStatus = _FileReadStatus.comments;
|
||||||
|
} else if (line.trim().startsWith('import')) {
|
||||||
|
lineStatus = _FileReadStatus.imports;
|
||||||
|
} else {
|
||||||
|
lineStatus = _FileReadStatus.finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FileReadStatus newStatus;
|
||||||
|
switch (oldStatus) {
|
||||||
|
case _FileReadStatus.comments:
|
||||||
|
newStatus =
|
||||||
|
(line.trim().isEmpty || lineStatus == _FileReadStatus.comments)
|
||||||
|
? _FileReadStatus.comments
|
||||||
|
: lineStatus;
|
||||||
|
break;
|
||||||
|
case _FileReadStatus.imports:
|
||||||
|
newStatus = (line.trim().isEmpty || lineStatus == _FileReadStatus.imports)
|
||||||
|
? _FileReadStatus.imports
|
||||||
|
: _FileReadStatus.finished;
|
||||||
|
break;
|
||||||
|
case _FileReadStatus.finished:
|
||||||
|
newStatus = oldStatus;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return newStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> _createSegments(String sourceDirectoryPath) {
|
||||||
|
List<File> files = Directory(sourceDirectoryPath)
|
||||||
|
.listSync(recursive: true)
|
||||||
|
.whereType<File>()
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
Map<String, StringBuffer> subsegments = {};
|
||||||
|
Map<String, String> subsegmentPrologues = {};
|
||||||
|
|
||||||
|
Set<String> appearedSubsegments = Set();
|
||||||
|
|
||||||
|
for (final file in files) {
|
||||||
|
// Process file.
|
||||||
|
|
||||||
|
String content = file.readAsStringSync();
|
||||||
|
List<String> lines = LineSplitter().convert(content);
|
||||||
|
|
||||||
|
_FileReadStatus status = _FileReadStatus.comments;
|
||||||
|
|
||||||
|
StringBuffer prologue = StringBuffer();
|
||||||
|
|
||||||
|
Set<String> activeSubsegments = Set();
|
||||||
|
|
||||||
|
for (final line in lines) {
|
||||||
|
// Update status.
|
||||||
|
|
||||||
|
status = _updatedStatus(status, line);
|
||||||
|
|
||||||
|
if (status != _FileReadStatus.finished) {
|
||||||
|
prologue.writeln(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process run commands.
|
||||||
|
|
||||||
|
if (line.trim().startsWith(beginSubsegment)) {
|
||||||
|
String argumentString = line.replaceFirst(beginSubsegment, '').trim();
|
||||||
|
List<String> arguments =
|
||||||
|
argumentString.isEmpty ? [] : argumentString.split(RegExp(r'\s+'));
|
||||||
|
|
||||||
|
for (final argument in arguments) {
|
||||||
|
if (activeSubsegments.contains(argument)) {
|
||||||
|
throw PreformatterException(
|
||||||
|
'BEGIN $argument is used twice in file ${file.path}');
|
||||||
|
} else if (appearedSubsegments.contains(argument)) {
|
||||||
|
throw PreformatterException('BEGIN $argument is used twice');
|
||||||
|
} else {
|
||||||
|
activeSubsegments.add(argument);
|
||||||
|
appearedSubsegments.add(argument);
|
||||||
|
subsegments[argument] = StringBuffer();
|
||||||
|
subsegmentPrologues[argument] = prologue.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (line.trim().startsWith(endSubsegment)) {
|
||||||
|
String argumentString = line.replaceFirst(endSubsegment, '').trim();
|
||||||
|
List<String> arguments =
|
||||||
|
argumentString.isEmpty ? [] : argumentString.split(RegExp(r'\s+'));
|
||||||
|
|
||||||
|
if (arguments.isEmpty && activeSubsegments.length == 1) {
|
||||||
|
arguments.add(activeSubsegments.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final argument in arguments) {
|
||||||
|
if (activeSubsegments.contains(argument)) {
|
||||||
|
activeSubsegments.remove(argument);
|
||||||
|
} else {
|
||||||
|
throw PreformatterException(
|
||||||
|
'END $argument is used without a paired BEGIN in ${file.path}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Simple line.
|
||||||
|
|
||||||
|
for (final name in activeSubsegments) {
|
||||||
|
subsegments[name].writeln(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeSubsegments.isNotEmpty) {
|
||||||
|
throw PreformatterException('File ${file.path} has unpaired BEGIN');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, List<TaggedString>> segments = {};
|
||||||
|
Map<String, String> segmentPrologues = {};
|
||||||
|
|
||||||
|
// Sometimes a code segment is made up of subsegments. They are marked by
|
||||||
|
// names with a "#" symbol in it, such as "bottomSheetDemoModal#1" and
|
||||||
|
// "bottomSheetDemoModal#2".
|
||||||
|
// The following code groups the subsegments by order into segments.
|
||||||
|
subsegments.forEach((key, value) {
|
||||||
|
String name;
|
||||||
|
double order;
|
||||||
|
|
||||||
|
if (key.contains('#')) {
|
||||||
|
List<String> parts = key.split('#');
|
||||||
|
name = parts[0];
|
||||||
|
order = double.parse(parts[1]);
|
||||||
|
} else {
|
||||||
|
name = key;
|
||||||
|
order = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!segments.containsKey(name)) {
|
||||||
|
segments[name] = [];
|
||||||
|
}
|
||||||
|
segments[name].add(
|
||||||
|
TaggedString(
|
||||||
|
text: value.toString(),
|
||||||
|
order: order,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
segmentPrologues[name] = subsegmentPrologues[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
segments.forEach((key, value) {
|
||||||
|
value.sort((ts1, ts2) => (ts1.order - ts2.order).sign.round());
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, String> answer = {};
|
||||||
|
|
||||||
|
for (final name in segments.keys) {
|
||||||
|
StringBuffer buffer = StringBuffer();
|
||||||
|
|
||||||
|
buffer.write(segmentPrologues[name].trim());
|
||||||
|
buffer.write('\n\n');
|
||||||
|
|
||||||
|
for (final ts in segments[name]) {
|
||||||
|
buffer.write(ts.text.trim());
|
||||||
|
buffer.write('\n\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
answer[name] = buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A string [text] together with a number [order], for sorting purposes.
|
||||||
|
/// Used to store different subsegments of a code segment.
|
||||||
|
/// The [order] of each subsegment is tagged with the code in order to be
|
||||||
|
/// sorted in the desired order.
|
||||||
|
class TaggedString {
|
||||||
|
TaggedString({this.text, this.order});
|
||||||
|
|
||||||
|
final String text;
|
||||||
|
final double order;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _formatSegments(Map<String, String> segments, String targetFilePath) {
|
||||||
|
File targetFile = File(targetFilePath);
|
||||||
|
IOSink output = targetFile.openWrite();
|
||||||
|
|
||||||
|
output.write(_globalPrologue);
|
||||||
|
|
||||||
|
for (final name in segments.keys) {
|
||||||
|
String code = segments[name];
|
||||||
|
|
||||||
|
output.writeln(' static TextSpan $name (BuildContext context) {');
|
||||||
|
output.writeln(' final CodeStyle codeStyle = CodeStyle.of(context);');
|
||||||
|
output.writeln(' return TextSpan(children: [');
|
||||||
|
|
||||||
|
List<CodeSpan> codeSpans = DartSyntaxPrehighlighter().format(code);
|
||||||
|
|
||||||
|
for (final span in codeSpans) {
|
||||||
|
output.write(' ');
|
||||||
|
output.write(span.toString());
|
||||||
|
output.write(',\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
output.write(' ]); }\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
output.write(_globalEpilogue);
|
||||||
|
|
||||||
|
output.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collect code segments, highlight, and write to file.
|
||||||
|
///
|
||||||
|
/// [writeSegments] walks through the directory specified by
|
||||||
|
/// [sourceDirectoryPath] and reads every file in it,
|
||||||
|
/// collects code segments marked by "// BEGIN <segment_name>" and "// END",
|
||||||
|
/// highlights them, and writes to the file specified by
|
||||||
|
/// [targetFilePath].
|
||||||
|
///
|
||||||
|
/// The output file is a dart source file with a class "CodeSegments" and
|
||||||
|
/// static methods of type TextSpan(BuildContext context).
|
||||||
|
/// Each method generates a widget that displays a segment of code.
|
||||||
|
///
|
||||||
|
/// The target file is overwritten.
|
||||||
|
void writeSegments({String sourceDirectoryPath, String targetFilePath}) {
|
||||||
|
Map<String, String> segments = _createSegments(sourceDirectoryPath);
|
||||||
|
_formatSegments(segments, targetFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PreformatterException implements Exception {
|
||||||
|
PreformatterException(this.cause);
|
||||||
|
String cause;
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
name: codeviewer_cli
|
||||||
|
description: A command-line application to highlight dart source code.
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: '>=2.4.0 <3.0.0'
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
string_scanner: 1.0.5
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
pedantic: 1.8.0
|
||||||
|
test: ^1.5.0
|
@ -0,0 +1,79 @@
|
|||||||
|
# Miscellaneous
|
||||||
|
*.class
|
||||||
|
*.log
|
||||||
|
*.pyc
|
||||||
|
*.swp
|
||||||
|
.DS_Store
|
||||||
|
.atom/
|
||||||
|
.buildlog/
|
||||||
|
.history
|
||||||
|
.svn/
|
||||||
|
.firebase/
|
||||||
|
.flutter-plugins-dependencies
|
||||||
|
|
||||||
|
# IntelliJ related
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# The .vscode folder contains launch configuration and tasks you configure in
|
||||||
|
# VS Code which you may wish to be included in version control, so this line
|
||||||
|
# is commented out by default.
|
||||||
|
#.vscode/
|
||||||
|
|
||||||
|
# Flutter/Dart/Pub related
|
||||||
|
**/doc/api/
|
||||||
|
.dart_tool/
|
||||||
|
.flutter-plugins
|
||||||
|
.flutter-plugins-dependencies
|
||||||
|
.packages
|
||||||
|
.pub-cache/
|
||||||
|
.pub/
|
||||||
|
/build/
|
||||||
|
|
||||||
|
# Android related
|
||||||
|
**/android/**/gradle-wrapper.jar
|
||||||
|
**/android/.gradle
|
||||||
|
**/android/captures/
|
||||||
|
**/android/gradlew
|
||||||
|
**/android/gradlew.bat
|
||||||
|
**/android/local.properties
|
||||||
|
**/android/**/GeneratedPluginRegistrant.java
|
||||||
|
|
||||||
|
# iOS/XCode related
|
||||||
|
**/ios/**/*.mode1v3
|
||||||
|
**/ios/**/*.mode2v3
|
||||||
|
**/ios/**/*.moved-aside
|
||||||
|
**/ios/**/*.pbxuser
|
||||||
|
**/ios/**/*.perspectivev3
|
||||||
|
**/ios/**/*sync/
|
||||||
|
**/ios/**/.sconsign.dblite
|
||||||
|
**/ios/**/.tags*
|
||||||
|
**/ios/**/.vagrant/
|
||||||
|
**/ios/**/DerivedData/
|
||||||
|
**/ios/**/Icon?
|
||||||
|
**/ios/**/Pods/
|
||||||
|
**/ios/**/.symlinks/
|
||||||
|
**/ios/**/profile
|
||||||
|
**/ios/**/xcuserdata
|
||||||
|
**/ios/.generated/
|
||||||
|
**/ios/Flutter/App.framework
|
||||||
|
**/ios/Flutter/Flutter.framework
|
||||||
|
**/ios/Flutter/Generated.xcconfig
|
||||||
|
**/ios/Flutter/app.flx
|
||||||
|
**/ios/Flutter/app.zip
|
||||||
|
**/ios/Flutter/flutter_assets/
|
||||||
|
**/ios/Flutter/flutter_export_environment.sh
|
||||||
|
**/ios/ServiceDefinitions.json
|
||||||
|
**/ios/Runner/GeneratedPluginRegistrant.*
|
||||||
|
|
||||||
|
# Web related
|
||||||
|
lib/generated_plugin_registrant.dart
|
||||||
|
|
||||||
|
# Exceptions to above rules.
|
||||||
|
!**/ios/**/default.mode1v3
|
||||||
|
!**/ios/**/default.mode2v3
|
||||||
|
!**/ios/**/default.pbxuser
|
||||||
|
!**/ios/**/default.perspectivev3
|
||||||
|
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
|
@ -0,0 +1,10 @@
|
|||||||
|
# This file tracks properties of this Flutter project.
|
||||||
|
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||||
|
#
|
||||||
|
# This file should be version controlled and should not be manually edited.
|
||||||
|
|
||||||
|
version:
|
||||||
|
revision: f5733f7a62ebc7c2ba324a2b410cd81215956b7d
|
||||||
|
channel: master
|
||||||
|
|
||||||
|
project_type: app
|
@ -0,0 +1,58 @@
|
|||||||
|
ROOT := $(shell git rev-parse --show-toplevel)
|
||||||
|
FLUTTER := $(shell which flutter)
|
||||||
|
FLUTTER_BIN_DIR := $(shell dirname $(FLUTTER))
|
||||||
|
FLUTTER_DIR := $(FLUTTER_BIN_DIR:/bin=)
|
||||||
|
DART := $(FLUTTER_BIN_DIR)/cache/dart-sdk/bin/dart
|
||||||
|
|
||||||
|
.PHONY: analyze
|
||||||
|
analyze:
|
||||||
|
$(FLUTTER) analyze
|
||||||
|
|
||||||
|
.PHONY: format
|
||||||
|
format:
|
||||||
|
$(FLUTTER) format .
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test:
|
||||||
|
$(FLUTTER) test
|
||||||
|
|
||||||
|
.PHONY: build-web
|
||||||
|
build-web:
|
||||||
|
$(FLUTTER) build web
|
||||||
|
|
||||||
|
.PHONY: fetch-master
|
||||||
|
fetch-master:
|
||||||
|
$(shell git fetch origin master)
|
||||||
|
|
||||||
|
.PHONY: master-branch-check
|
||||||
|
master-branch-check: fetch-master
|
||||||
|
ifneq ($(shell git rev-parse --abbrev-ref HEAD),master)
|
||||||
|
$(error Not on master branch, please checkout master)
|
||||||
|
endif
|
||||||
|
ifneq ($(shell git rev-parse HEAD),$(shell git rev-parse origin/master))
|
||||||
|
$(error Your master branch is not up to date with origin/master, please pull before deploying)
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: deploy
|
||||||
|
deploy: master-branch-check build-web
|
||||||
|
cp $(ROOT)/gallery/web/favicon.ico $(ROOT)/gallery/build/web/
|
||||||
|
firebase deploy
|
||||||
|
|
||||||
|
.PHONY: gen-l10n
|
||||||
|
gen-l10n:
|
||||||
|
$(DART) $(FLUTTER_DIR)/dev/tools/localization/bin/gen_l10n.dart \
|
||||||
|
--template-arb-file=intl_en_US.arb \
|
||||||
|
--output-localization-file=gallery_localizations.dart \
|
||||||
|
--output-class=GalleryLocalizations
|
||||||
|
|
||||||
|
.PHONY: l10n
|
||||||
|
l10n: gen-l10n format
|
||||||
|
cd $(ROOT)/l10n_cli/ && $(FLUTTER) pub get
|
||||||
|
$(DART) $(ROOT)/l10n_cli/bin/main.dart
|
||||||
|
|
||||||
|
.PHONY: update-code-segments
|
||||||
|
update-code-segments:
|
||||||
|
cd $(ROOT)/codeviewer_cli/ && pub get
|
||||||
|
$(DART) $(ROOT)/codeviewer_cli/bin/main.dart
|
||||||
|
$(FLUTTER) format $(ROOT)/gallery/lib/codeviewer/code_segments.dart
|
@ -0,0 +1,33 @@
|
|||||||
|
include: package:pedantic/analysis_options.1.8.0.yaml
|
||||||
|
|
||||||
|
analyzer:
|
||||||
|
exclude:
|
||||||
|
- lib/l10n/messages_*.dart
|
||||||
|
strong-mode:
|
||||||
|
implicit-casts: false
|
||||||
|
implicit-dynamic: false
|
||||||
|
|
||||||
|
linter:
|
||||||
|
rules:
|
||||||
|
- avoid_types_on_closure_parameters
|
||||||
|
- avoid_void_async
|
||||||
|
- await_only_futures
|
||||||
|
- camel_case_types
|
||||||
|
- cancel_subscriptions
|
||||||
|
- close_sinks
|
||||||
|
- constant_identifier_names
|
||||||
|
- control_flow_in_finally
|
||||||
|
- empty_statements
|
||||||
|
- hash_and_equals
|
||||||
|
- implementation_imports
|
||||||
|
- non_constant_identifier_names
|
||||||
|
- package_api_docs
|
||||||
|
- package_names
|
||||||
|
- package_prefixed_library_names
|
||||||
|
- test_types_in_equals
|
||||||
|
- throw_in_finally
|
||||||
|
- unnecessary_brace_in_string_interps
|
||||||
|
- unnecessary_getters_setters
|
||||||
|
- unnecessary_new
|
||||||
|
- unnecessary_statements
|
||||||
|
- directives_ordering
|
@ -0,0 +1,12 @@
|
|||||||
|
gradle-wrapper.jar
|
||||||
|
/.gradle
|
||||||
|
/captures/
|
||||||
|
/gradlew
|
||||||
|
/gradlew.bat
|
||||||
|
/local.properties
|
||||||
|
GeneratedPluginRegistrant.java
|
||||||
|
|
||||||
|
# Visual Studio Code related
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
.settings/
|
@ -0,0 +1,67 @@
|
|||||||
|
def localProperties = new Properties()
|
||||||
|
def localPropertiesFile = rootProject.file('local.properties')
|
||||||
|
if (localPropertiesFile.exists()) {
|
||||||
|
localPropertiesFile.withReader('UTF-8') { reader ->
|
||||||
|
localProperties.load(reader)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
||||||
|
if (flutterRoot == null) {
|
||||||
|
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||||
|
if (flutterVersionCode == null) {
|
||||||
|
flutterVersionCode = '1'
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutterVersionName = localProperties.getProperty('flutter.versionName')
|
||||||
|
if (flutterVersionName == null) {
|
||||||
|
flutterVersionName = '1.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
apply plugin: 'kotlin-android'
|
||||||
|
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 28
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main.java.srcDirs += 'src/main/kotlin'
|
||||||
|
}
|
||||||
|
|
||||||
|
lintOptions {
|
||||||
|
disable 'InvalidPackage'
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||||
|
applicationId "com.example.gallery"
|
||||||
|
minSdkVersion 16
|
||||||
|
targetSdkVersion 28
|
||||||
|
versionCode flutterVersionCode.toInteger()
|
||||||
|
versionName flutterVersionName
|
||||||
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
// TODO: Add your own signing config for the release build.
|
||||||
|
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||||
|
signingConfig signingConfigs.debug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flutter {
|
||||||
|
source '../..'
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
|
testImplementation 'junit:junit:4.12'
|
||||||
|
androidTestImplementation 'androidx.test:runner:1.1.0'
|
||||||
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.example.gallery">
|
||||||
|
<!-- Flutter needs it to communicate with the running application
|
||||||
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
|
-->
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
</manifest>
|
@ -0,0 +1,33 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.example.gallery">
|
||||||
|
|
||||||
|
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
||||||
|
calls FlutterMain.startInitialization(this); in its onCreate method.
|
||||||
|
In most cases you can leave this as-is, but you if you want to provide
|
||||||
|
additional functionality it is fine to subclass or reimplement
|
||||||
|
FlutterApplication and put your custom class here. -->
|
||||||
|
<application
|
||||||
|
android:name="io.flutter.app.FlutterApplication"
|
||||||
|
android:label="Flutter Gallery"
|
||||||
|
android:icon="@mipmap/ic_launcher">
|
||||||
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
|
android:launchMode="singleTop"
|
||||||
|
android:theme="@style/LaunchTheme"
|
||||||
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||||
|
android:hardwareAccelerated="true"
|
||||||
|
android:windowSoftInputMode="adjustResize">
|
||||||
|
<!-- This keeps the window background of the activity showing
|
||||||
|
until Flutter renders its first frame. It can be removed if
|
||||||
|
there is no splash screen (such as the default splash screen
|
||||||
|
defined in @style/LaunchTheme). -->
|
||||||
|
<meta-data
|
||||||
|
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
|
||||||
|
android:value="true" />
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
</manifest>
|
After Width: | Height: | Size: 23 KiB |
@ -0,0 +1,13 @@
|
|||||||
|
package com.example.gallery
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
|
||||||
|
import io.flutter.app.FlutterActivity
|
||||||
|
import io.flutter.plugins.GeneratedPluginRegistrant
|
||||||
|
|
||||||
|
class MainActivity: FlutterActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
GeneratedPluginRegistrant.registerWith(this)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Modify this file to customize your launch splash screen -->
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@color/backgroundColor" />
|
||||||
|
|
||||||
|
<!-- You can insert your own image assets here -->
|
||||||
|
<!-- <item>
|
||||||
|
<bitmap
|
||||||
|
android:gravity="center"
|
||||||
|
android:src="@mipmap/launch_image" />
|
||||||
|
</item> -->
|
||||||
|
</layer-list>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@mipmap/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@mipmap/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 375 B |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 240 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 517 B |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 12 KiB |
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||||
|
<!-- Show a splash screen on the activity. Automatically removed when
|
||||||
|
Flutter draws its first frame -->
|
||||||
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
|
</style>
|
||||||
|
<color name="backgroundColor">#030303</color>
|
||||||
|
</resources>
|
@ -0,0 +1,7 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.example.gallery">
|
||||||
|
<!-- Flutter needs it to communicate with the running application
|
||||||
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
|
-->
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
</manifest>
|
@ -0,0 +1,31 @@
|
|||||||
|
buildscript {
|
||||||
|
ext.kotlin_version = '1.2.71'
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||||
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.buildDir = '../build'
|
||||||
|
subprojects {
|
||||||
|
project.buildDir = "${rootProject.buildDir}/${project.name}"
|
||||||
|
}
|
||||||
|
subprojects {
|
||||||
|
project.evaluationDependsOn(':app')
|
||||||
|
}
|
||||||
|
|
||||||
|
task clean(type: Delete) {
|
||||||
|
delete rootProject.buildDir
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
org.gradle.jvmargs=-Xmx1536M
|
||||||
|
|
||||||
|
android.enableR8=true
|
||||||
|
android.useAndroidX=true
|
||||||
|
android.enableJetifier=true
|
@ -0,0 +1,6 @@
|
|||||||
|
#Fri Jun 23 08:50:38 CEST 2017
|
||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
|
@ -0,0 +1,15 @@
|
|||||||
|
include ':app'
|
||||||
|
|
||||||
|
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
|
||||||
|
|
||||||
|
def plugins = new Properties()
|
||||||
|
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
|
||||||
|
if (pluginsFile.exists()) {
|
||||||
|
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins.each { name, path ->
|
||||||
|
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
|
||||||
|
include ":$name"
|
||||||
|
project(":$name").projectDir = pluginDirectory
|
||||||
|
}
|
After Width: | Height: | Size: 120 KiB |
After Width: | Height: | Size: 200 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 158 KiB |
After Width: | Height: | Size: 107 KiB |
After Width: | Height: | Size: 74 KiB |
After Width: | Height: | Size: 217 KiB |
After Width: | Height: | Size: 157 KiB |
After Width: | Height: | Size: 146 KiB |
After Width: | Height: | Size: 173 KiB |
After Width: | Height: | Size: 169 KiB |
After Width: | Height: | Size: 154 KiB |
After Width: | Height: | Size: 158 KiB |
After Width: | Height: | Size: 69 KiB |
After Width: | Height: | Size: 253 KiB |
After Width: | Height: | Size: 201 KiB |
After Width: | Height: | Size: 310 KiB |
After Width: | Height: | Size: 192 KiB |
After Width: | Height: | Size: 218 KiB |
After Width: | Height: | Size: 194 KiB |
After Width: | Height: | Size: 284 KiB |
After Width: | Height: | Size: 237 KiB |
After Width: | Height: | Size: 160 KiB |
After Width: | Height: | Size: 232 KiB |
After Width: | Height: | Size: 147 KiB |
After Width: | Height: | Size: 194 KiB |
After Width: | Height: | Size: 154 KiB |
After Width: | Height: | Size: 69 KiB |
After Width: | Height: | Size: 209 KiB |
After Width: | Height: | Size: 218 KiB |
After Width: | Height: | Size: 147 KiB |
After Width: | Height: | Size: 284 KiB |
After Width: | Height: | Size: 158 KiB |
After Width: | Height: | Size: 201 KiB |
After Width: | Height: | Size: 140 KiB |
After Width: | Height: | Size: 209 KiB |
After Width: | Height: | Size: 253 KiB |
After Width: | Height: | Size: 227 KiB |
After Width: | Height: | Size: 421 KiB |
After Width: | Height: | Size: 165 KiB |
After Width: | Height: | Size: 381 KiB |
After Width: | Height: | Size: 211 KiB |
After Width: | Height: | Size: 151 KiB |
After Width: | Height: | Size: 442 KiB |
After Width: | Height: | Size: 335 KiB |
After Width: | Height: | Size: 299 KiB |
After Width: | Height: | Size: 365 KiB |
After Width: | Height: | Size: 348 KiB |
After Width: | Height: | Size: 343 KiB |
After Width: | Height: | Size: 447 KiB |
After Width: | Height: | Size: 126 KiB |
After Width: | Height: | Size: 557 KiB |