mirror of
https://github.com/flutter/samples.git
synced 2025-11-08 13:58:47 +00:00
Add flutter_lints (#808)
This commit is contained in:
19
add_to_app/books/flutter_module_books/analysis_options.yaml
Normal file
19
add_to_app/books/flutter_module_books/analysis_options.yaml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
|
analyzer:
|
||||||
|
strong-mode:
|
||||||
|
implicit-casts: false
|
||||||
|
implicit-dynamic: false
|
||||||
|
|
||||||
|
linter:
|
||||||
|
rules:
|
||||||
|
avoid_types_on_closure_parameters: true
|
||||||
|
avoid_void_async: true
|
||||||
|
cancel_subscriptions: true
|
||||||
|
close_sinks: true
|
||||||
|
directives_ordering: true
|
||||||
|
package_api_docs: true
|
||||||
|
package_prefixed_library_names: true
|
||||||
|
test_types_in_equals: true
|
||||||
|
throw_in_finally: true
|
||||||
|
unnecessary_statements: true
|
||||||
@@ -41,7 +41,7 @@ class Book {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract class FlutterBookApi {
|
abstract class FlutterBookApi {
|
||||||
void displayBookDetails(Book arg);
|
void displayBookDetails(Book book);
|
||||||
static void setup(FlutterBookApi api) {
|
static void setup(FlutterBookApi api) {
|
||||||
{
|
{
|
||||||
const BasicMessageChannel<Object> channel = BasicMessageChannel<Object>(
|
const BasicMessageChannel<Object> channel = BasicMessageChannel<Object>(
|
||||||
@@ -50,7 +50,7 @@ abstract class FlutterBookApi {
|
|||||||
if (api == null) {
|
if (api == null) {
|
||||||
channel.setMessageHandler(null);
|
channel.setMessageHandler(null);
|
||||||
} else {
|
} else {
|
||||||
channel.setMessageHandler((Object message) async {
|
channel.setMessageHandler((message) async {
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,16 +5,18 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_module_books/api.dart';
|
import 'package:flutter_module_books/api.dart';
|
||||||
|
|
||||||
void main() => runApp(MyApp());
|
void main() => runApp(const MyApp());
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatelessWidget {
|
||||||
|
const MyApp({Key key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
primaryColor: const Color(0xff6200ee),
|
primaryColor: const Color(0xff6200ee),
|
||||||
),
|
),
|
||||||
home: BookDetail(),
|
home: const BookDetail(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,7 +39,7 @@ class FlutterBookApiHandler extends FlutterBookApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class BookDetail extends StatefulWidget {
|
class BookDetail extends StatefulWidget {
|
||||||
const BookDetail({this.hostApi, this.flutterApi});
|
const BookDetail({this.hostApi, this.flutterApi, Key key}) : super(key: key);
|
||||||
|
|
||||||
// These are the outgoing and incoming APIs that are here for injection for
|
// These are the outgoing and incoming APIs that are here for injection for
|
||||||
// tests.
|
// tests.
|
||||||
@@ -73,7 +75,7 @@ class _BookDetailState extends State<BookDetail> {
|
|||||||
FlutterBookApi.setup(FlutterBookApiHandler(
|
FlutterBookApi.setup(FlutterBookApiHandler(
|
||||||
// The `FlutterBookApi` just has one method. Just give a closure for that
|
// The `FlutterBookApi` just has one method. Just give a closure for that
|
||||||
// method to the handler class.
|
// method to the handler class.
|
||||||
(Book book) {
|
(book) {
|
||||||
setState(() {
|
setState(() {
|
||||||
// This book model is what we're going to return to Kotlin eventually.
|
// This book model is what we're going to return to Kotlin eventually.
|
||||||
// Keep it bound to the UI.
|
// Keep it bound to the UI.
|
||||||
@@ -107,9 +109,9 @@ class _BookDetailState extends State<BookDetail> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text('Book Details'),
|
title: const Text('Book Details'),
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
icon: Icon(Icons.clear),
|
icon: const Icon(Icons.clear),
|
||||||
// Pressing clear cancels the edit and leaves the activity without
|
// Pressing clear cancels the edit and leaves the activity without
|
||||||
// modification.
|
// modification.
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@@ -119,7 +121,7 @@ class _BookDetailState extends State<BookDetail> {
|
|||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.check),
|
icon: const Icon(Icons.check),
|
||||||
// Pressing save sends the updated book to the platform.
|
// Pressing save sends the updated book to the platform.
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
hostApi.finishEditingBook(book);
|
hostApi.finishEditingBook(book);
|
||||||
@@ -131,44 +133,44 @@ class _BookDetailState extends State<BookDetail> {
|
|||||||
body: book == null
|
body: book == null
|
||||||
// Draw a spinner until the platform gives us the book to show details
|
// Draw a spinner until the platform gives us the book to show details
|
||||||
// for.
|
// for.
|
||||||
? Center(child: CircularProgressIndicator())
|
? const Center(child: CircularProgressIndicator())
|
||||||
: Focus(
|
: Focus(
|
||||||
focusNode: textFocusNode,
|
focusNode: textFocusNode,
|
||||||
child: ListView(
|
child: ListView(
|
||||||
padding: EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
children: [
|
children: [
|
||||||
TextField(
|
TextField(
|
||||||
controller: titleTextController,
|
controller: titleTextController,
|
||||||
decoration: InputDecoration(
|
decoration: const InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
filled: true,
|
filled: true,
|
||||||
hintText: "Title",
|
hintText: "Title",
|
||||||
labelText: "Title",
|
labelText: "Title",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
TextField(
|
TextField(
|
||||||
controller: subtitleTextController,
|
controller: subtitleTextController,
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
decoration: InputDecoration(
|
decoration: const InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
filled: true,
|
filled: true,
|
||||||
hintText: "Subtitle",
|
hintText: "Subtitle",
|
||||||
labelText: "Subtitle",
|
labelText: "Subtitle",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
TextField(
|
TextField(
|
||||||
controller: authorTextController,
|
controller: authorTextController,
|
||||||
decoration: InputDecoration(
|
decoration: const InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
filled: true,
|
filled: true,
|
||||||
hintText: "Author",
|
hintText: "Author",
|
||||||
labelText: "Author",
|
labelText: "Author",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 32),
|
const SizedBox(height: 32),
|
||||||
Divider(),
|
const Divider(),
|
||||||
Center(
|
Center(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
@@ -176,9 +178,9 @@ class _BookDetailState extends State<BookDetail> {
|
|||||||
'${book.pageCount} pages ~ published ${book.publishDate}'),
|
'${book.pageCount} pages ~ published ${book.publishDate}'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Divider(),
|
const Divider(),
|
||||||
SizedBox(height: 32),
|
const SizedBox(height: 32),
|
||||||
Center(
|
const Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'BOOK DESCRIPTION',
|
'BOOK DESCRIPTION',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@@ -188,7 +190,7 @@ class _BookDetailState extends State<BookDetail> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
Text(
|
Text(
|
||||||
book.summary,
|
book.summary,
|
||||||
style: TextStyle(color: Colors.grey.shade600, height: 1.24),
|
style: TextStyle(color: Colors.grey.shade600, height: 1.24),
|
||||||
|
|||||||
@@ -62,11 +62,25 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_lints:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: flutter_lints
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.3"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
lints:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: lints
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.1"
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ dev_dependencies:
|
|||||||
mockito: ^4.1.1
|
mockito: ^4.1.1
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
flutter_lints: ^1.0.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
@@ -30,4 +31,4 @@ flutter:
|
|||||||
module:
|
module:
|
||||||
androidX: true
|
androidX: true
|
||||||
androidPackage: dev.flutter.example.flutter_module_books
|
androidPackage: dev.flutter.example.flutter_module_books
|
||||||
iosBundleIdentifier: dev.flutter.example.flutterModuleBooks
|
iosBundleIdentifier: dev.flutter.example.flutterModuleBooks
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ import 'package:flutter_test/flutter_test.dart';
|
|||||||
import 'package:mockito/mockito.dart';
|
import 'package:mockito/mockito.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testWidgets('Pressing clear calls the cancel API',
|
testWidgets('Pressing clear calls the cancel API', (tester) async {
|
||||||
(WidgetTester tester) async {
|
|
||||||
MockHostBookApi mockHostApi = MockHostBookApi();
|
MockHostBookApi mockHostApi = MockHostBookApi();
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
@@ -24,8 +23,7 @@ void main() {
|
|||||||
verify(mockHostApi.cancel());
|
verify(mockHostApi.cancel());
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Pressing done calls the finish editing API',
|
testWidgets('Pressing done calls the finish editing API', (tester) async {
|
||||||
(WidgetTester tester) async {
|
|
||||||
MockHostBookApi mockHostApi = MockHostBookApi();
|
MockHostBookApi mockHostApi = MockHostBookApi();
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
|
|||||||
Reference in New Issue
Block a user