diff --git a/dev/automated_tests/pubspec.yaml b/dev/automated_tests/pubspec.yaml index 049707ec0b8..98365004280 100644 --- a/dev/automated_tests/pubspec.yaml +++ b/dev/automated_tests/pubspec.yaml @@ -11,7 +11,7 @@ dependencies: sdk: flutter test: 1.5.1 - analyzer: 0.33.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + analyzer: 0.33.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -20,7 +20,7 @@ dependencies: convert: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - front_end: 0.1.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + front_end: 0.1.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -29,7 +29,7 @@ dependencies: io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - kernel: 0.3.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + kernel: 0.3.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -67,4 +67,4 @@ dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: 42f2 +# PUBSPEC CHECKSUM: 4a91 diff --git a/dev/benchmarks/complex_layout/pubspec.yaml b/dev/benchmarks/complex_layout/pubspec.yaml index fa5f63618b9..7d2792f03b1 100644 --- a/dev/benchmarks/complex_layout/pubspec.yaml +++ b/dev/benchmarks/complex_layout/pubspec.yaml @@ -41,11 +41,11 @@ dev_dependencies: sdk: flutter test: 1.5.1 - analyzer: 0.33.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + analyzer: 0.33.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - front_end: 0.1.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + front_end: 0.1.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -53,7 +53,7 @@ dev_dependencies: http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - kernel: 0.3.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + kernel: 0.3.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -84,4 +84,4 @@ flutter: - packages/flutter_gallery_assets/people/square/ali.png - packages/flutter_gallery_assets/places/india_chettinad_silk_maker.png -# PUBSPEC CHECKSUM: 6ac2 +# PUBSPEC CHECKSUM: 5461 diff --git a/dev/benchmarks/microbenchmarks/pubspec.yaml b/dev/benchmarks/microbenchmarks/pubspec.yaml index 41f73f54332..7754fbadad9 100644 --- a/dev/benchmarks/microbenchmarks/pubspec.yaml +++ b/dev/benchmarks/microbenchmarks/pubspec.yaml @@ -15,7 +15,7 @@ dependencies: path: ../../../examples/stocks test: 1.5.1 - analyzer: 0.33.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + analyzer: 0.33.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -25,7 +25,7 @@ dependencies: crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" dart_style: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - front_end: 0.1.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + front_end: 0.1.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -37,7 +37,7 @@ dependencies: isolate: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - kernel: 0.3.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + kernel: 0.3.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -75,4 +75,4 @@ dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: c249 +# PUBSPEC CHECKSUM: 71e7 diff --git a/dev/bots/pubspec.yaml b/dev/bots/pubspec.yaml index dad88497231..8af30b46a5c 100644 --- a/dev/bots/pubspec.yaml +++ b/dev/bots/pubspec.yaml @@ -15,7 +15,7 @@ dependencies: http_parser: 3.1.3 test: 1.5.1 - analyzer: 0.33.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + analyzer: 0.33.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" charcode: 1.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -24,7 +24,7 @@ dependencies: crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" file: 5.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - front_end: 0.1.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + front_end: 0.1.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" http_multi_server: 2.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -32,7 +32,7 @@ dependencies: io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - kernel: 0.3.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + kernel: 0.3.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -66,4 +66,4 @@ dev_dependencies: mockito: 4.0.0 test_api: 0.2.1 -# PUBSPEC CHECKSUM: ba96 +# PUBSPEC CHECKSUM: aa35 diff --git a/dev/devicelab/pubspec.yaml b/dev/devicelab/pubspec.yaml index b6546b9cd10..9dee6de4a12 100644 --- a/dev/devicelab/pubspec.yaml +++ b/dev/devicelab/pubspec.yaml @@ -38,10 +38,10 @@ dev_dependencies: # See packages/flutter_test/pubspec.yaml for why we're pinning this version. test: 1.5.1 - analyzer: 0.33.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + analyzer: 0.33.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - front_end: 0.1.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + front_end: 0.1.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -49,7 +49,7 @@ dev_dependencies: http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - kernel: 0.3.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + kernel: 0.3.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -73,4 +73,4 @@ dev_dependencies: watcher: 0.9.7+10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.1.15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: df7b +# PUBSPEC CHECKSUM: 021a diff --git a/dev/integration_tests/android_semantics_testing/pubspec.yaml b/dev/integration_tests/android_semantics_testing/pubspec.yaml index 5af69529fe7..ec30a600b32 100644 --- a/dev/integration_tests/android_semantics_testing/pubspec.yaml +++ b/dev/integration_tests/android_semantics_testing/pubspec.yaml @@ -8,7 +8,7 @@ dependencies: sdk: flutter test: 1.5.1 - analyzer: 0.33.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + analyzer: 0.33.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -18,7 +18,7 @@ dependencies: crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" file: 5.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - front_end: 0.1.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + front_end: 0.1.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -28,7 +28,7 @@ dependencies: io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - kernel: 0.3.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + kernel: 0.3.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -65,4 +65,4 @@ dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: cf3b +# PUBSPEC CHECKSUM: c4d9 diff --git a/dev/integration_tests/android_views/pubspec.yaml b/dev/integration_tests/android_views/pubspec.yaml index 7cb1517652c..30aeac1fb57 100644 --- a/dev/integration_tests/android_views/pubspec.yaml +++ b/dev/integration_tests/android_views/pubspec.yaml @@ -37,11 +37,11 @@ dev_dependencies: sdk: flutter test: 1.5.1 - analyzer: 0.33.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + analyzer: 0.33.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - front_end: 0.1.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + front_end: 0.1.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -49,7 +49,7 @@ dev_dependencies: http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - kernel: 0.3.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + kernel: 0.3.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -79,4 +79,4 @@ dev_dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: f2f5 +# PUBSPEC CHECKSUM: bc94 diff --git a/dev/integration_tests/channels/pubspec.yaml b/dev/integration_tests/channels/pubspec.yaml index 80614be109f..5d8b5b9d317 100644 --- a/dev/integration_tests/channels/pubspec.yaml +++ b/dev/integration_tests/channels/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: sdk: flutter test: 1.5.1 - analyzer: 0.33.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + analyzer: 0.33.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -22,7 +22,7 @@ dependencies: crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" file: 5.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - front_end: 0.1.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + front_end: 0.1.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -32,7 +32,7 @@ dependencies: io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - kernel: 0.3.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + kernel: 0.3.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -69,4 +69,4 @@ dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: cf3b +# PUBSPEC CHECKSUM: c4d9 diff --git a/dev/integration_tests/external_ui/pubspec.yaml b/dev/integration_tests/external_ui/pubspec.yaml index fbbae0afc7b..3a080096ac1 100644 --- a/dev/integration_tests/external_ui/pubspec.yaml +++ b/dev/integration_tests/external_ui/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: sdk: flutter test: 1.5.1 - analyzer: 0.33.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + analyzer: 0.33.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -22,7 +22,7 @@ dependencies: crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" file: 5.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - front_end: 0.1.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + front_end: 0.1.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -32,7 +32,7 @@ dependencies: io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - kernel: 0.3.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + kernel: 0.3.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -69,4 +69,4 @@ dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: cf3b +# PUBSPEC CHECKSUM: c4d9 diff --git a/dev/integration_tests/flavors/pubspec.yaml b/dev/integration_tests/flavors/pubspec.yaml index ac093aae7f9..d774e655769 100644 --- a/dev/integration_tests/flavors/pubspec.yaml +++ b/dev/integration_tests/flavors/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: sdk: flutter test: 1.5.1 - analyzer: 0.33.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + analyzer: 0.33.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -22,7 +22,7 @@ dependencies: crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" file: 5.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - front_end: 0.1.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + front_end: 0.1.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -32,7 +32,7 @@ dependencies: io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - kernel: 0.3.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + kernel: 0.3.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -69,4 +69,4 @@ dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: cf3b +# PUBSPEC CHECKSUM: c4d9 diff --git a/dev/integration_tests/platform_interaction/pubspec.yaml b/dev/integration_tests/platform_interaction/pubspec.yaml index 5631b82abd9..691ec166181 100644 --- a/dev/integration_tests/platform_interaction/pubspec.yaml +++ b/dev/integration_tests/platform_interaction/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: sdk: flutter test: 1.5.1 - analyzer: 0.33.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + analyzer: 0.33.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -22,7 +22,7 @@ dependencies: crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" file: 5.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - front_end: 0.1.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + front_end: 0.1.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -32,7 +32,7 @@ dependencies: io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - kernel: 0.3.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + kernel: 0.3.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -69,4 +69,4 @@ dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: cf3b +# PUBSPEC CHECKSUM: c4d9 diff --git a/dev/integration_tests/ui/pubspec.yaml b/dev/integration_tests/ui/pubspec.yaml index f610d066180..2062d11d6f2 100644 --- a/dev/integration_tests/ui/pubspec.yaml +++ b/dev/integration_tests/ui/pubspec.yaml @@ -13,7 +13,7 @@ dependencies: sdk: flutter test: 1.5.1 - analyzer: 0.33.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + analyzer: 0.33.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" archive: 2.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -24,7 +24,7 @@ dependencies: crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" file: 5.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - front_end: 0.1.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + front_end: 0.1.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -34,7 +34,7 @@ dependencies: io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - kernel: 0.3.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + kernel: 0.3.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -79,4 +79,4 @@ dev_dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: 9e4d +# PUBSPEC CHECKSUM: 3beb diff --git a/dev/snippets/pubspec.yaml b/dev/snippets/pubspec.yaml index b9de54a9daf..95b13379b16 100644 --- a/dev/snippets/pubspec.yaml +++ b/dev/snippets/pubspec.yaml @@ -18,17 +18,17 @@ dependencies: meta: 1.1.6 platform: 2.2.0 - analyzer: 0.33.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + analyzer: 0.33.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" charcode: 1.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" collection: 1.14.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" convert: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - front_end: 0.1.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + front_end: 0.1.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - kernel: 0.3.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + kernel: 0.3.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -100,4 +100,4 @@ executables: vm_service_client: 0.2.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 1.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: d555 +# PUBSPEC CHECKSUM: a3f3 diff --git a/examples/catalog/pubspec.yaml b/examples/catalog/pubspec.yaml index e0d0adb5d46..1aae495d348 100644 --- a/examples/catalog/pubspec.yaml +++ b/examples/catalog/pubspec.yaml @@ -22,7 +22,7 @@ dev_dependencies: sdk: flutter test: 1.5.1 - analyzer: 0.33.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + analyzer: 0.33.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -31,7 +31,7 @@ dev_dependencies: crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" file: 5.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - front_end: 0.1.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + front_end: 0.1.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -41,7 +41,7 @@ dev_dependencies: io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - kernel: 0.3.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + kernel: 0.3.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -75,4 +75,4 @@ dev_dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: c324 +# PUBSPEC CHECKSUM: d4c2 diff --git a/examples/flutter_gallery/lib/demo/shrine/app.dart b/examples/flutter_gallery/lib/demo/shrine/app.dart deleted file mode 100644 index e5eae3af50d..00000000000 --- a/examples/flutter_gallery/lib/demo/shrine/app.dart +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2018-present the Flutter authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; - -import 'package:flutter_gallery/demo/shrine/backdrop.dart'; -import 'package:flutter_gallery/demo/shrine/category_menu_page.dart'; -import 'package:flutter_gallery/demo/shrine/colors.dart'; -import 'package:flutter_gallery/demo/shrine/expanding_bottom_sheet.dart'; -import 'package:flutter_gallery/demo/shrine/home.dart'; -import 'package:flutter_gallery/demo/shrine/login.dart'; -import 'package:flutter_gallery/demo/shrine/supplemental/cut_corners_border.dart'; - -class ShrineApp extends StatefulWidget { - @override - _ShrineAppState createState() => _ShrineAppState(); -} - -class _ShrineAppState extends State with SingleTickerProviderStateMixin { - // Controller to coordinate both the opening/closing of backdrop and sliding - // of expanding bottom sheet - AnimationController _controller; - - @override - void initState() { - super.initState(); - _controller = AnimationController( - vsync: this, - duration: const Duration(milliseconds: 450), - value: 1.0, - ); - } - - @override - Widget build(BuildContext context) { - return MaterialApp( - title: 'Shrine', - home: HomePage( - backdrop: Backdrop( - frontLayer: const ProductPage(), - backLayer: CategoryMenuPage(onCategoryTap: () => _controller.forward()), - frontTitle: const Text('SHRINE'), - backTitle: const Text('MENU'), - controller: _controller, - ), - expandingBottomSheet: ExpandingBottomSheet(hideController: _controller), - ), - initialRoute: '/login', - onGenerateRoute: _getRoute, - theme: _kShrineTheme, - ); - } -} - -Route _getRoute(RouteSettings settings) { - if (settings.name != '/login') { - return null; - } - - return MaterialPageRoute( - settings: settings, - builder: (BuildContext context) => LoginPage(), - fullscreenDialog: true, - ); -} - -final ThemeData _kShrineTheme = _buildShrineTheme(); - -IconThemeData _customIconTheme(IconThemeData original) { - return original.copyWith(color: kShrineBrown900); -} - -ThemeData _buildShrineTheme() { - final ThemeData base = ThemeData.light(); - return base.copyWith( - colorScheme: kShrineColorScheme, - accentColor: kShrineBrown900, - primaryColor: kShrinePink100, - buttonColor: kShrinePink100, - scaffoldBackgroundColor: kShrineBackgroundWhite, - cardColor: kShrineBackgroundWhite, - textSelectionColor: kShrinePink100, - errorColor: kShrineErrorRed, - buttonTheme: const ButtonThemeData( - colorScheme: kShrineColorScheme, - textTheme: ButtonTextTheme.normal, - ), - primaryIconTheme: _customIconTheme(base.iconTheme), - inputDecorationTheme: const InputDecorationTheme(border: CutCornersBorder()), - textTheme: _buildShrineTextTheme(base.textTheme), - primaryTextTheme: _buildShrineTextTheme(base.primaryTextTheme), - accentTextTheme: _buildShrineTextTheme(base.accentTextTheme), - iconTheme: _customIconTheme(base.iconTheme), - ); -} - -TextTheme _buildShrineTextTheme(TextTheme base) { - return base.copyWith( - headline: base.headline.copyWith(fontWeight: FontWeight.w500), - title: base.title.copyWith(fontSize: 18.0), - caption: base.caption.copyWith(fontWeight: FontWeight.w400, fontSize: 14.0), - body2: base.body2.copyWith(fontWeight: FontWeight.w500, fontSize: 16.0), - button: base.button.copyWith(fontWeight: FontWeight.w500, fontSize: 14.0), - ).apply( - fontFamily: 'Raleway', - displayColor: kShrineBrown900, - bodyColor: kShrineBrown900, - ); -} - -const ColorScheme kShrineColorScheme = ColorScheme( - primary: kShrinePink100, - primaryVariant: kShrineBrown900, - secondary: kShrinePink50, - secondaryVariant: kShrineBrown900, - surface: kShrineSurfaceWhite, - background: kShrineBackgroundWhite, - error: kShrineErrorRed, - onPrimary: kShrineBrown900, - onSecondary: kShrineBrown900, - onSurface: kShrineBrown900, - onBackground: kShrineBrown900, - onError: kShrineSurfaceWhite, - brightness: Brightness.light, -); diff --git a/examples/flutter_gallery/lib/demo/shrine/backdrop.dart b/examples/flutter_gallery/lib/demo/shrine/backdrop.dart deleted file mode 100644 index 2e79fae755e..00000000000 --- a/examples/flutter_gallery/lib/demo/shrine/backdrop.dart +++ /dev/null @@ -1,330 +0,0 @@ -// Copyright 2018-present the Flutter authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; -import 'package:meta/meta.dart'; - -import 'package:flutter_gallery/demo/shrine/login.dart'; - -const Cubic _kAccelerateCurve = Cubic(0.548, 0.0, 0.757, 0.464); -const Cubic _kDecelerateCurve = Cubic(0.23, 0.94, 0.41, 1.0); -const double _kPeakVelocityTime = 0.248210; -const double _kPeakVelocityProgress = 0.379146; - -class _FrontLayer extends StatelessWidget { - const _FrontLayer({ - Key key, - this.onTap, - this.child, - }) : super(key: key); - - final VoidCallback onTap; - final Widget child; - - @override - Widget build(BuildContext context) { - return Material( - elevation: 16.0, - shape: const BeveledRectangleBorder( - borderRadius: BorderRadius.only(topLeft: Radius.circular(46.0)), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: onTap, - child: Container( - height: 40.0, - alignment: AlignmentDirectional.centerStart, - ), - ), - Expanded( - child: child, - ), - ], - ), - ); - } -} - -class _BackdropTitle extends AnimatedWidget { - const _BackdropTitle({ - Key key, - Listenable listenable, - this.onPress, - @required this.frontTitle, - @required this.backTitle, - }) : assert(frontTitle != null), - assert(backTitle != null), - super(key: key, listenable: listenable); - - final Function onPress; - final Widget frontTitle; - final Widget backTitle; - - @override - Widget build(BuildContext context) { - final Animation animation = CurvedAnimation( - parent: listenable, - curve: const Interval(0.0, 0.78), - ); - - return DefaultTextStyle( - style: Theme.of(context).primaryTextTheme.title, - softWrap: false, - overflow: TextOverflow.ellipsis, - child: Row(children: [ - // branded icon - SizedBox( - width: 72.0, - child: IconButton( - padding: const EdgeInsets.only(right: 8.0), - onPressed: onPress, - icon: Stack(children: [ - Opacity( - opacity: animation.value, - child: const ImageIcon(AssetImage('packages/shrine_images/slanted_menu.png')), - ), - FractionalTranslation( - translation: Tween( - begin: Offset.zero, - end: const Offset(1.0, 0.0), - ).evaluate(animation), - child: const ImageIcon(AssetImage('packages/shrine_images/diamond.png')), - ) - ]), - ), - ), - // Here, we do a custom cross fade between backTitle and frontTitle. - // This makes a smooth animation between the two texts. - Stack( - children: [ - Opacity( - opacity: CurvedAnimation( - parent: ReverseAnimation(animation), - curve: const Interval(0.5, 1.0), - ).value, - child: FractionalTranslation( - translation: Tween( - begin: Offset.zero, - end: const Offset(0.5, 0.0), - ).evaluate(animation), - child: backTitle, - ), - ), - Opacity( - opacity: CurvedAnimation( - parent: animation, - curve: const Interval(0.5, 1.0), - ).value, - child: FractionalTranslation( - translation: Tween( - begin: const Offset(-0.25, 0.0), - end: Offset.zero, - ).evaluate(animation), - child: frontTitle, - ), - ), - ], - ) - ]), - ); - } -} - -/// Builds a Backdrop. -/// -/// A Backdrop widget has two layers, front and back. The front layer is shown -/// by default, and slides down to show the back layer, from which a user -/// can make a selection. The user can also configure the titles for when the -/// front or back layer is showing. -class Backdrop extends StatefulWidget { - const Backdrop({ - @required this.frontLayer, - @required this.backLayer, - @required this.frontTitle, - @required this.backTitle, - @required this.controller, - }) : assert(frontLayer != null), - assert(backLayer != null), - assert(frontTitle != null), - assert(backTitle != null), - assert(controller != null); - - final Widget frontLayer; - final Widget backLayer; - final Widget frontTitle; - final Widget backTitle; - final AnimationController controller; - - @override - _BackdropState createState() => _BackdropState(); -} - -class _BackdropState extends State with SingleTickerProviderStateMixin { - final GlobalKey _backdropKey = GlobalKey(debugLabel: 'Backdrop'); - AnimationController _controller; - Animation _layerAnimation; - - @override - void initState() { - super.initState(); - _controller = widget.controller; - } - - @override - void dispose() { - _controller.dispose(); - super.dispose(); - } - - bool get _frontLayerVisible { - final AnimationStatus status = _controller.status; - return status == AnimationStatus.completed || status == AnimationStatus.forward; - } - - void _toggleBackdropLayerVisibility() { - // Call setState here to update layerAnimation if that's necessary - setState(() { - _frontLayerVisible ? _controller.reverse() : _controller.forward(); - }); - } - - // _layerAnimation animates the front layer between open and close. - // _getLayerAnimation adjusts the values in the TweenSequence so the - // curve and timing are correct in both directions. - Animation _getLayerAnimation(Size layerSize, double layerTop) { - Curve firstCurve; // Curve for first TweenSequenceItem - Curve secondCurve; // Curve for second TweenSequenceItem - double firstWeight; // Weight of first TweenSequenceItem - double secondWeight; // Weight of second TweenSequenceItem - Animation animation; // Animation on which TweenSequence runs - - if (_frontLayerVisible) { - firstCurve = _kAccelerateCurve; - secondCurve = _kDecelerateCurve; - firstWeight = _kPeakVelocityTime; - secondWeight = 1.0 - _kPeakVelocityTime; - animation = CurvedAnimation( - parent: _controller.view, - curve: const Interval(0.0, 0.78), - ); - } else { - // These values are only used when the controller runs from t=1.0 to t=0.0 - firstCurve = _kDecelerateCurve.flipped; - secondCurve = _kAccelerateCurve.flipped; - firstWeight = 1.0 - _kPeakVelocityTime; - secondWeight = _kPeakVelocityTime; - animation = _controller.view; - } - - return TweenSequence( - >[ - TweenSequenceItem( - tween: RelativeRectTween( - begin: RelativeRect.fromLTRB( - 0.0, - layerTop, - 0.0, - layerTop - layerSize.height, - ), - end: RelativeRect.fromLTRB( - 0.0, - layerTop * _kPeakVelocityProgress, - 0.0, - (layerTop - layerSize.height) * _kPeakVelocityProgress, - ), - ).chain(CurveTween(curve: firstCurve)), - weight: firstWeight, - ), - TweenSequenceItem( - tween: RelativeRectTween( - begin: RelativeRect.fromLTRB( - 0.0, - layerTop * _kPeakVelocityProgress, - 0.0, - (layerTop - layerSize.height) * _kPeakVelocityProgress, - ), - end: RelativeRect.fill, - ).chain(CurveTween(curve: secondCurve)), - weight: secondWeight, - ), - ], - ).animate(animation); - } - - Widget _buildStack(BuildContext context, BoxConstraints constraints) { - const double layerTitleHeight = 48.0; - final Size layerSize = constraints.biggest; - final double layerTop = layerSize.height - layerTitleHeight; - - _layerAnimation = _getLayerAnimation(layerSize, layerTop); - - return Stack( - key: _backdropKey, - children: [ - widget.backLayer, - PositionedTransition( - rect: _layerAnimation, - child: _FrontLayer( - onTap: _toggleBackdropLayerVisibility, - child: widget.frontLayer, - ), - ), - ], - ); - } - - @override - Widget build(BuildContext context) { - final AppBar appBar = AppBar( - brightness: Brightness.light, - elevation: 0.0, - titleSpacing: 0.0, - title: _BackdropTitle( - listenable: _controller.view, - onPress: _toggleBackdropLayerVisibility, - frontTitle: widget.frontTitle, - backTitle: widget.backTitle, - ), - actions: [ - IconButton( - icon: const Icon(Icons.search, semanticLabel: 'login'), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute(builder: (BuildContext context) => LoginPage()), - ); - }, - ), - IconButton( - icon: const Icon(Icons.tune, semanticLabel: 'login'), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute(builder: (BuildContext context) => LoginPage()), - ); - }, - ), - ], - ); - return Scaffold( - appBar: appBar, - body: LayoutBuilder( - builder: _buildStack, - ), - ); - } -} diff --git a/examples/flutter_gallery/lib/demo/shrine/category_menu_page.dart b/examples/flutter_gallery/lib/demo/shrine/category_menu_page.dart deleted file mode 100644 index 1ac62d57290..00000000000 --- a/examples/flutter_gallery/lib/demo/shrine/category_menu_page.dart +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2018-present the Flutter authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; -import 'package:scoped_model/scoped_model.dart'; - -import 'package:flutter_gallery/demo/shrine/colors.dart'; -import 'package:flutter_gallery/demo/shrine/model/app_state_model.dart'; -import 'package:flutter_gallery/demo/shrine/model/product.dart'; - -class CategoryMenuPage extends StatelessWidget { - const CategoryMenuPage({ - Key key, - this.onCategoryTap, - }) : super(key: key); - - final VoidCallback onCategoryTap; - - Widget _buildCategory(Category category, BuildContext context) { - final String categoryString = category.toString().replaceAll('Category.', '').toUpperCase(); - final ThemeData theme = Theme.of(context); - return ScopedModelDescendant( - builder: (BuildContext context, Widget child, AppStateModel model) => - GestureDetector( - onTap: () { - model.setCategory(category); - if (onCategoryTap != null) { - onCategoryTap(); - } - }, - child: model.selectedCategory == category - ? Column( - children: [ - const SizedBox(height: 16.0), - Text( - categoryString, - style: theme.textTheme.body2, - textAlign: TextAlign.center, - ), - const SizedBox(height: 14.0), - Container( - width: 70.0, - height: 2.0, - color: kShrinePink400, - ), - ], - ) - : Padding( - padding: const EdgeInsets.symmetric(vertical: 16.0), - child: Text( - categoryString, - style: theme.textTheme.body2.copyWith( - color: kShrineBrown900.withAlpha(153) - ), - textAlign: TextAlign.center, - ), - ), - ), - ); - } - - @override - Widget build(BuildContext context) { - return Center( - child: Container( - padding: const EdgeInsets.only(top: 40.0), - color: kShrinePink100, - child: ListView( - children: Category.values.map((Category c) => _buildCategory(c, context)).toList(), - ), - ), - ); - } -} diff --git a/examples/flutter_gallery/lib/demo/shrine/colors.dart b/examples/flutter_gallery/lib/demo/shrine/colors.dart deleted file mode 100644 index 66a47286172..00000000000 --- a/examples/flutter_gallery/lib/demo/shrine/colors.dart +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2018-present the Flutter authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; - -const Color kShrinePink50 = Color(0xFFFEEAE6); -const Color kShrinePink100 = Color(0xFFFEDBD0); -const Color kShrinePink300 = Color(0xFFFBB8AC); -const Color kShrinePink400 = Color(0xFFEAA4A4); - -const Color kShrineBrown900 = Color(0xFF442B2D); -const Color kShrineBrown600 = Color(0xFF7D4F52); - -const Color kShrineErrorRed = Color(0xFFC5032B); - -const Color kShrineSurfaceWhite = Color(0xFFFFFBFA); -const Color kShrineBackgroundWhite = Colors.white; diff --git a/examples/flutter_gallery/lib/demo/shrine/expanding_bottom_sheet.dart b/examples/flutter_gallery/lib/demo/shrine/expanding_bottom_sheet.dart deleted file mode 100644 index b74d632e081..00000000000 --- a/examples/flutter_gallery/lib/demo/shrine/expanding_bottom_sheet.dart +++ /dev/null @@ -1,655 +0,0 @@ -// Copyright 2018-present the Flutter authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'dart:async'; - -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:meta/meta.dart'; -import 'package:scoped_model/scoped_model.dart'; - -import 'package:flutter_gallery/demo/shrine/colors.dart'; -import 'package:flutter_gallery/demo/shrine/model/app_state_model.dart'; -import 'package:flutter_gallery/demo/shrine/model/product.dart'; -import 'package:flutter_gallery/demo/shrine/shopping_cart.dart'; - -// These curves define the emphasized easing curve. -const Cubic _kAccelerateCurve = Cubic(0.548, 0.0, 0.757, 0.464); -const Cubic _kDecelerateCurve = Cubic(0.23, 0.94, 0.41, 1.0); -// The time at which the accelerate and decelerate curves switch off -const double _kPeakVelocityTime = 0.248210; -// Percent (as a decimal) of animation that should be completed at _peakVelocityTime -const double _kPeakVelocityProgress = 0.379146; -const double _kCartHeight = 56.0; -// Radius of the shape on the top left of the sheet. -const double _kCornerRadius = 24.0; -// Width for just the cart icon and no thumbnails. -const double _kWidthForCartIcon = 64.0; - -class ExpandingBottomSheet extends StatefulWidget { - const ExpandingBottomSheet({Key key, @required this.hideController}) - : assert(hideController != null), - super(key: key); - - final AnimationController hideController; - - @override - _ExpandingBottomSheetState createState() => _ExpandingBottomSheetState(); - - static _ExpandingBottomSheetState of(BuildContext context, {bool isNullOk = false}) { - assert(isNullOk != null); - assert(context != null); - final _ExpandingBottomSheetState result = context.ancestorStateOfType( - const TypeMatcher<_ExpandingBottomSheetState>() - ); - if (isNullOk || result != null) { - return result; - } - throw FlutterError( - 'ExpandingBottomSheet.of() called with a context that does not contain a ExpandingBottomSheet.\n'); - } -} - -// Emphasized Easing is a motion curve that has an organic, exciting feeling. -// It's very fast to begin with and then very slow to finish. Unlike standard -// curves, like [Curves.fastOutSlowIn], it can't be expressed in a cubic bezier -// curve formula. It's quintic, not cubic. But it _can_ be expressed as one -// curve followed by another, which we do here. -Animation _getEmphasizedEasingAnimation({ - @required T begin, - @required T peak, - @required T end, - @required bool isForward, - @required Animation parent}) { - Curve firstCurve; - Curve secondCurve; - double firstWeight; - double secondWeight; - - if (isForward) { - firstCurve = _kAccelerateCurve; - secondCurve = _kDecelerateCurve; - firstWeight = _kPeakVelocityTime; - secondWeight = 1.0 - _kPeakVelocityTime; - } else { - firstCurve = _kDecelerateCurve.flipped; - secondCurve = _kAccelerateCurve.flipped; - firstWeight = 1.0 - _kPeakVelocityTime; - secondWeight = _kPeakVelocityTime; - } - - return TweenSequence( - >[ - TweenSequenceItem( - weight: firstWeight, - tween: Tween( - begin: begin, - end: peak, - ).chain(CurveTween(curve: firstCurve)), - ), - TweenSequenceItem( - weight: secondWeight, - tween: Tween( - begin: peak, - end: end, - ).chain(CurveTween(curve: secondCurve)), - ), - ], - ).animate(parent); -} - -// Calculates the value where two double Animations should be joined. Used by -// callers of _getEmphasisedEasing(). -double _getPeakPoint({double begin, double end}) { - return begin + (end - begin) * _kPeakVelocityProgress; -} - -class _ExpandingBottomSheetState extends State with TickerProviderStateMixin { - final GlobalKey _expandingBottomSheetKey = GlobalKey(debugLabel: 'Expanding bottom sheet'); - - // The width of the Material, calculated by _widthFor() & based on the number - // of products in the cart. 64.0 is the width when there are 0 products - // (_kWidthForZeroProducts) - double _width = _kWidthForCartIcon; - - // Controller for the opening and closing of the ExpandingBottomSheet - AnimationController _controller; - - // Animations for the opening and closing of the ExpandingBottomSheet - Animation _widthAnimation; - Animation _heightAnimation; - Animation _thumbnailOpacityAnimation; - Animation _cartOpacityAnimation; - Animation _shapeAnimation; - Animation _slideAnimation; - - @override - void initState() { - super.initState(); - _controller = AnimationController( - duration: const Duration(milliseconds: 500), - vsync: this, - ); - } - - @override - void dispose() { - _controller.dispose(); - super.dispose(); - } - - Animation _getWidthAnimation(double screenWidth) { - if (_controller.status == AnimationStatus.forward) { - // Opening animation - return Tween(begin: _width, end: screenWidth).animate( - CurvedAnimation( - parent: _controller.view, - curve: const Interval(0.0, 0.3, curve: Curves.fastOutSlowIn), - ), - ); - } else { - // Closing animation - return _getEmphasizedEasingAnimation( - begin: _width, - peak: _getPeakPoint(begin: _width, end: screenWidth), - end: screenWidth, - isForward: false, - parent: CurvedAnimation(parent: _controller.view, curve: const Interval(0.0, 0.87)), - ); - } - } - - Animation _getHeightAnimation(double screenHeight) { - if (_controller.status == AnimationStatus.forward) { - // Opening animation - - return _getEmphasizedEasingAnimation( - begin: _kCartHeight, - peak: _kCartHeight + (screenHeight - _kCartHeight) * _kPeakVelocityProgress, - end: screenHeight, - isForward: true, - parent: _controller.view, - ); - } else { - // Closing animation - return Tween( - begin: _kCartHeight, - end: screenHeight, - ).animate( - CurvedAnimation( - parent: _controller.view, - curve: const Interval(0.434, 1.0, curve: Curves.linear), // not used - // only the reverseCurve will be used - reverseCurve: Interval(0.434, 1.0, curve: Curves.fastOutSlowIn.flipped), - ), - ); - } - } - - // Animation of the cut corner. It's cut when closed and not cut when open. - Animation _getShapeAnimation() { - if (_controller.status == AnimationStatus.forward) { - return Tween(begin: _kCornerRadius, end: 0.0).animate( - CurvedAnimation( - parent: _controller.view, - curve: const Interval(0.0, 0.3, curve: Curves.fastOutSlowIn), - ), - ); - } else { - return _getEmphasizedEasingAnimation( - begin: _kCornerRadius, - peak: _getPeakPoint(begin: _kCornerRadius, end: 0.0), - end: 0.0, - isForward: false, - parent: _controller.view, - ); - } - } - - Animation _getThumbnailOpacityAnimation() { - return Tween(begin: 1.0, end: 0.0).animate( - CurvedAnimation( - parent: _controller.view, - curve: _controller.status == AnimationStatus.forward - ? const Interval(0.0, 0.3) - : const Interval(0.532, 0.766), - ), - ); - } - - Animation _getCartOpacityAnimation() { - return CurvedAnimation( - parent: _controller.view, - curve: _controller.status == AnimationStatus.forward - ? const Interval(0.3, 0.6) - : const Interval(0.766, 1.0), - ); - } - - // Returns the correct width of the ExpandingBottomSheet based on the number of - // products in the cart. - double _widthFor(int numProducts) { - switch (numProducts) { - case 0: - return _kWidthForCartIcon; - case 1: - return 136.0; - case 2: - return 192.0; - case 3: - return 248.0; - default: - return 278.0; - } - } - - // Returns true if the cart is open or opening and false otherwise. - bool get _isOpen { - final AnimationStatus status = _controller.status; - return status == AnimationStatus.completed || status == AnimationStatus.forward; - } - - // Opens the ExpandingBottomSheet if it's closed, otherwise does nothing. - void open() { - if (!_isOpen) { - _controller.forward(); - } - } - - // Closes the ExpandingBottomSheet if it's open or opening, otherwise does nothing. - void close() { - if (_isOpen) { - _controller.reverse(); - } - } - - // Changes the padding between the start edge of the Material and the cart icon - // based on the number of products in the cart (padding increases when > 0 - // products.) - EdgeInsetsDirectional _cartPaddingFor(int numProducts) { - return (numProducts == 0) - ? const EdgeInsetsDirectional.only(start: 20.0, end: 8.0) - : const EdgeInsetsDirectional.only(start: 32.0, end: 8.0); - } - - bool get _cartIsVisible => _thumbnailOpacityAnimation.value == 0.0; - - Widget _buildThumbnails(int numProducts) { - return ExcludeSemantics( - child: Opacity( - opacity: _thumbnailOpacityAnimation.value, - child: Column( - children: [ - Row( - children: [ - AnimatedPadding( - padding: _cartPaddingFor(numProducts), - child: const Icon(Icons.shopping_cart), - duration: const Duration(milliseconds: 225), - ), - Container( - // Accounts for the overflow number - width: numProducts > 3 ? _width - 94.0 : _width - 64.0, - height: _kCartHeight, - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: ProductThumbnailRow(), - ), - ExtraProductsNumber(), - ], - ), - ], - ), - ), - ); - } - - Widget _buildShoppingCartPage() { - return Opacity( - opacity: _cartOpacityAnimation.value, - child: ShoppingCartPage(), - ); - } - - Widget _buildCart(BuildContext context, Widget child) { - // numProducts is the number of different products in the cart (does not - // include multiples of the same product). - final AppStateModel model = ScopedModel.of(context); - final int numProducts = model.productsInCart.keys.length; - final int totalCartQuantity = model.totalCartQuantity; - final Size screenSize = MediaQuery.of(context).size; - final double screenWidth = screenSize.width; - final double screenHeight = screenSize.height; - - _width = _widthFor(numProducts); - _widthAnimation = _getWidthAnimation(screenWidth); - _heightAnimation = _getHeightAnimation(screenHeight); - _shapeAnimation = _getShapeAnimation(); - _thumbnailOpacityAnimation = _getThumbnailOpacityAnimation(); - _cartOpacityAnimation = _getCartOpacityAnimation(); - - return Semantics( - button: true, - value: 'Shopping cart, $totalCartQuantity items', - child: Container( - width: _widthAnimation.value, - height: _heightAnimation.value, - child: Material( - animationDuration: const Duration(milliseconds: 0), - shape: BeveledRectangleBorder( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(_shapeAnimation.value), - ), - ), - elevation: 4.0, - color: kShrinePink50, - child: _cartIsVisible - ? _buildShoppingCartPage() - : _buildThumbnails(numProducts), - ), - ), - ); - } - - // Builder for the hide and reveal animation when the backdrop opens and closes - Widget _buildSlideAnimation(BuildContext context, Widget child) { - _slideAnimation = _getEmphasizedEasingAnimation( - begin: const Offset(1.0, 0.0), - peak: const Offset(_kPeakVelocityProgress, 0.0), - end: const Offset(0.0, 0.0), - isForward: widget.hideController.status == AnimationStatus.forward, - parent: widget.hideController, - ); - - return SlideTransition( - position: _slideAnimation, - child: child, - ); - } - - // Closes the cart if the cart is open, otherwise exits the app (this should - // only be relevant for Android). - Future _onWillPop() async { - if (!_isOpen) { - await SystemNavigator.pop(); - return true; - } - - close(); - return true; - } - - @override - Widget build(BuildContext context) { - return AnimatedSize( - key: _expandingBottomSheetKey, - duration: const Duration(milliseconds: 225), - curve: Curves.easeInOut, - vsync: this, - alignment: FractionalOffset.topLeft, - child: WillPopScope( - onWillPop: _onWillPop, - child: AnimatedBuilder( - animation: widget.hideController, - builder: _buildSlideAnimation, - child: GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: open, - child: ScopedModelDescendant( - builder: (BuildContext context, Widget child, AppStateModel model) { - return AnimatedBuilder( - builder: _buildCart, - animation: _controller, - ); - }, - ), - ), - ), - ), - ); - } -} - -class ProductThumbnailRow extends StatefulWidget { - @override - _ProductThumbnailRowState createState() => _ProductThumbnailRowState(); -} - -class _ProductThumbnailRowState extends State { - final GlobalKey _listKey = GlobalKey(); - - // _list represents what's currently on screen. If _internalList updates, - // it will need to be updated to match it. - _ListModel _list; - - // _internalList represents the list as it is updated by the AppStateModel. - List _internalList; - - @override - void initState() { - super.initState(); - _list = _ListModel( - listKey: _listKey, - initialItems: ScopedModel.of(context).productsInCart.keys.toList(), - removedItemBuilder: _buildRemovedThumbnail, - ); - _internalList = List.from(_list.list); - } - - Product _productWithId(int productId) { - final AppStateModel model = ScopedModel.of(context); - final Product product = model.getProductById(productId); - assert(product != null); - return product; - } - - Widget _buildRemovedThumbnail(int item, BuildContext context, Animation animation) { - return ProductThumbnail(animation, animation, _productWithId(item)); - } - - Widget _buildThumbnail(BuildContext context, int index, Animation animation) { - final Animation thumbnailSize = Tween(begin: 0.8, end: 1.0).animate( - CurvedAnimation( - curve: const Interval(0.33, 1.0, curve: Curves.easeIn), - parent: animation, - ), - ); - - final Animation opacity = CurvedAnimation( - curve: const Interval(0.33, 1.0, curve: Curves.linear), - parent: animation, - ); - - return ProductThumbnail(thumbnailSize, opacity, _productWithId(_list[index])); - } - - // If the lists are the same length, assume nothing has changed. - // If the internalList is shorter than the ListModel, an item has been removed. - // If the internalList is longer, then an item has been added. - void _updateLists() { - // Update _internalList based on the model - _internalList = ScopedModel.of(context).productsInCart.keys.toList(); - final Set internalSet = Set.from(_internalList); - final Set listSet = Set.from(_list.list); - - final Set difference = internalSet.difference(listSet); - if (difference.isEmpty) { - return; - } - - for (int product in difference) { - if (_internalList.length < _list.length) { - _list.remove(product); - } else if (_internalList.length > _list.length) { - _list.add(product); - } - } - - while (_internalList.length != _list.length) { - int index = 0; - // Check bounds and that the list elements are the same - while (_internalList.isNotEmpty && - _list.length > 0 && - index < _internalList.length && - index < _list.length && - _internalList[index] == _list[index]) { - index++; - } - } - } - - Widget _buildAnimatedList() { - return AnimatedList( - key: _listKey, - shrinkWrap: true, - itemBuilder: _buildThumbnail, - initialItemCount: _list.length, - scrollDirection: Axis.horizontal, - physics: const NeverScrollableScrollPhysics(), // Cart shouldn't scroll - ); - } - - @override - Widget build(BuildContext context) { - _updateLists(); - return ScopedModelDescendant( - builder: (BuildContext context, Widget child, AppStateModel model) => _buildAnimatedList(), - ); - } -} - -class ExtraProductsNumber extends StatelessWidget { - // Calculates the number to be displayed at the end of the row if there are - // more than three products in the cart. This calculates overflow products, - // including their duplicates (but not duplicates of products shown as - // thumbnails). - int _calculateOverflow(AppStateModel model) { - final Map productMap = model.productsInCart; - // List created to be able to access products by index instead of ID. - // Order is guaranteed because productsInCart returns a LinkedHashMap. - final List products = productMap.keys.toList(); - int overflow = 0; - final int numProducts = products.length; - if (numProducts > 3) { - for (int i = 3; i < numProducts; i++) { - overflow += productMap[products[i]]; - } - } - return overflow; - } - - Widget _buildOverflow(AppStateModel model, BuildContext context) { - if (model.productsInCart.length <= 3) - return Container(); - - final int numOverflowProducts = _calculateOverflow(model); - // Maximum of 99 so padding doesn't get messy. - final int displayedOverflowProducts = numOverflowProducts <= 99 ? numOverflowProducts : 99; - return Container( - child: Text( - '+$displayedOverflowProducts', - style: Theme.of(context).primaryTextTheme.button, - ), - ); - } - - @override - Widget build(BuildContext context) { - return ScopedModelDescendant( - builder: (BuildContext builder, Widget child, AppStateModel model) => _buildOverflow(model, context), - ); - } -} - -class ProductThumbnail extends StatelessWidget { - const ProductThumbnail(this.animation, this.opacityAnimation, this.product); - - final Animation animation; - final Animation opacityAnimation; - final Product product; - - @override - Widget build(BuildContext context) { - return FadeTransition( - opacity: opacityAnimation, - child: ScaleTransition( - scale: animation, - child: Container( - width: 40.0, - height: 40.0, - decoration: BoxDecoration( - image: DecorationImage( - image: ExactAssetImage( - product.assetName, // asset name - package: product.assetPackage, // asset package - ), - fit: BoxFit.cover, - ), - borderRadius: const BorderRadius.all(Radius.circular(10.0)), - ), - margin: const EdgeInsets.only(left: 16.0), - ), - ), - ); - } -} - -// _ListModel manipulates an internal list and an AnimatedList -class _ListModel { - _ListModel({ - @required this.listKey, - @required this.removedItemBuilder, - Iterable initialItems - }) : assert(listKey != null), - assert(removedItemBuilder != null), - _items = List.from(initialItems ?? []); - - final GlobalKey listKey; - final dynamic removedItemBuilder; - final List _items; - - AnimatedListState get _animatedList => listKey.currentState; - - void add(int product) { - _insert(_items.length, product); - } - - void _insert(int index, int item) { - _items.insert(index, item); - _animatedList.insertItem(index, duration: const Duration(milliseconds: 225)); - } - - void remove(int product) { - final int index = _items.indexOf(product); - if (index >= 0) { - _removeAt(index); - } - } - - void _removeAt(int index) { - final int removedItem = _items.removeAt(index); - if (removedItem != null) { - _animatedList.removeItem(index, (BuildContext context, Animation animation) { - return removedItemBuilder(removedItem, context, animation); - }); - } - } - - int get length => _items.length; - - int operator [](int index) => _items[index]; - - int indexOf(int item) => _items.indexOf(item); - - List get list => _items; -} diff --git a/examples/flutter_gallery/lib/demo/shrine/home.dart b/examples/flutter_gallery/lib/demo/shrine/home.dart deleted file mode 100644 index 33131e237cc..00000000000 --- a/examples/flutter_gallery/lib/demo/shrine/home.dart +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2018-present the Flutter authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; -import 'package:scoped_model/scoped_model.dart'; - -import 'package:flutter_gallery/demo/shrine/backdrop.dart'; -import 'package:flutter_gallery/demo/shrine/expanding_bottom_sheet.dart'; -import 'package:flutter_gallery/demo/shrine/model/app_state_model.dart'; -import 'package:flutter_gallery/demo/shrine/model/product.dart'; -import 'package:flutter_gallery/demo/shrine/supplemental/asymmetric_view.dart'; - -class ProductPage extends StatelessWidget { - const ProductPage({this.category = Category.all}); - - final Category category; - - @override - Widget build(BuildContext context) { - return ScopedModelDescendant( - builder: (BuildContext context, Widget child, AppStateModel model) { - return AsymmetricView(products: model.getProducts()); - }); - } -} - -class HomePage extends StatelessWidget { - const HomePage({ - this.expandingBottomSheet, - this.backdrop, - Key key, - }) : super(key: key); - - final ExpandingBottomSheet expandingBottomSheet; - final Backdrop backdrop; - - @override - Widget build(BuildContext context) { - return Stack( - children: [ - backdrop, - Align(child: expandingBottomSheet, alignment: Alignment.bottomRight) - ], - ); - } -} diff --git a/examples/flutter_gallery/lib/demo/shrine/login.dart b/examples/flutter_gallery/lib/demo/shrine/login.dart deleted file mode 100644 index c400755d169..00000000000 --- a/examples/flutter_gallery/lib/demo/shrine/login.dart +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2018-present the Flutter authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; - -import 'package:flutter_gallery/demo/shrine/colors.dart'; - -class LoginPage extends StatefulWidget { - @override - _LoginPageState createState() => _LoginPageState(); -} - -class _LoginPageState extends State { - final TextEditingController _usernameController = TextEditingController(); - final TextEditingController _passwordController = TextEditingController(); - - @override - Widget build(BuildContext context) { - return Scaffold( - body: SafeArea( - child: ListView( - padding: const EdgeInsets.symmetric(horizontal: 24.0), - children: [ - const SizedBox(height: 80.0), - Column( - children: [ - Image.asset('packages/shrine_images/diamond.png'), - const SizedBox(height: 16.0), - Text( - 'SHRINE', - style: Theme.of(context).textTheme.headline, - ), - ], - ), - const SizedBox(height: 120.0), - PrimaryColorOverride( - color: kShrineBrown900, - child: TextField( - controller: _usernameController, - decoration: const InputDecoration( - labelText: 'Username', - ), - ), - ), - const SizedBox(height: 12.0), - PrimaryColorOverride( - color: kShrineBrown900, - child: TextField( - controller: _passwordController, - decoration: const InputDecoration( - labelText: 'Password', - ), - ), - ), - Wrap( - children: [ - ButtonBar( - children: [ - FlatButton( - child: const Text('CANCEL'), - shape: const BeveledRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(7.0)), - ), - onPressed: () { - _usernameController.clear(); - _passwordController.clear(); - }, - ), - RaisedButton( - child: const Text('NEXT'), - elevation: 8.0, - shape: const BeveledRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(7.0)), - ), - onPressed: () { - Navigator.pop(context); - }, - ), - ], - ), - Tooltip( - message: 'Back', - child: FlatButton( - child: const Text('EXIT'), - shape: const BeveledRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(7.0)), - ), - onPressed: () { - Navigator.of(context, rootNavigator: true).pop(); - }, - ), - ), - ], - ), - ], - ), - ), - ); - } -} - -class PrimaryColorOverride extends StatelessWidget { - const PrimaryColorOverride({Key key, this.color, this.child}) : super(key: key); - - final Color color; - final Widget child; - - @override - Widget build(BuildContext context) { - return Theme( - child: child, - data: Theme.of(context).copyWith(primaryColor: color), - ); - } -} diff --git a/examples/flutter_gallery/lib/demo/shrine/model/app_state_model.dart b/examples/flutter_gallery/lib/demo/shrine/model/app_state_model.dart deleted file mode 100644 index 9c984659351..00000000000 --- a/examples/flutter_gallery/lib/demo/shrine/model/app_state_model.dart +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2018-present the Flutter authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:scoped_model/scoped_model.dart'; - -import 'package:flutter_gallery/demo/shrine/model/product.dart'; -import 'package:flutter_gallery/demo/shrine/model/products_repository.dart'; - -double _salesTaxRate = 0.06; -double _shippingCostPerItem = 7.0; - -class AppStateModel extends Model { - // All the available products. - List _availableProducts; - - // The currently selected category of products. - Category _selectedCategory = Category.all; - - // The IDs and quantities of products currently in the cart. - final Map _productsInCart = {}; - - Map get productsInCart => Map.from(_productsInCart); - - // Total number of items in the cart. - int get totalCartQuantity => _productsInCart.values.fold(0, (int v, int e) => v + e); - - Category get selectedCategory => _selectedCategory; - - // Totaled prices of the items in the cart. - double get subtotalCost { - return _productsInCart.keys - .map((int id) => _availableProducts[id].price * _productsInCart[id]) - .fold(0.0, (double sum, int e) => sum + e); - } - - // Total shipping cost for the items in the cart. - double get shippingCost { - return _shippingCostPerItem * _productsInCart.values.fold(0.0, (num sum, int e) => sum + e); - } - - // Sales tax for the items in the cart - double get tax => subtotalCost * _salesTaxRate; - - // Total cost to order everything in the cart. - double get totalCost => subtotalCost + shippingCost + tax; - - // Returns a copy of the list of available products, filtered by category. - List getProducts() { - if (_availableProducts == null) { - return []; - } - - if (_selectedCategory == Category.all) { - return List.from(_availableProducts); - } else { - return _availableProducts - .where((Product p) => p.category == _selectedCategory) - .toList(); - } - } - - // Adds a product to the cart. - void addProductToCart(int productId) { - if (!_productsInCart.containsKey(productId)) { - _productsInCart[productId] = 1; - } else { - _productsInCart[productId]++; - } - - notifyListeners(); - } - - // Removes an item from the cart. - void removeItemFromCart(int productId) { - if (_productsInCart.containsKey(productId)) { - if (_productsInCart[productId] == 1) { - _productsInCart.remove(productId); - } else { - _productsInCart[productId]--; - } - } - - notifyListeners(); - } - - // Returns the Product instance matching the provided id. - Product getProductById(int id) { - return _availableProducts.firstWhere((Product p) => p.id == id); - } - - // Removes everything from the cart. - void clearCart() { - _productsInCart.clear(); - notifyListeners(); - } - - // Loads the list of available products from the repo. - void loadProducts() { - _availableProducts = ProductsRepository.loadProducts(Category.all); - notifyListeners(); - } - - void setCategory(Category newCategory) { - _selectedCategory = newCategory; - notifyListeners(); - } -} diff --git a/examples/flutter_gallery/lib/demo/shrine/model/product.dart b/examples/flutter_gallery/lib/demo/shrine/model/product.dart deleted file mode 100644 index ffedcc32174..00000000000 --- a/examples/flutter_gallery/lib/demo/shrine/model/product.dart +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2018-present the Flutter authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/foundation.dart'; - -enum Category { - all, - accessories, - clothing, - home, -} - -class Product { - const Product({ - @required this.category, - @required this.id, - @required this.isFeatured, - @required this.name, - @required this.price, - }) : assert(category != null), - assert(id != null), - assert(isFeatured != null), - assert(name != null), - assert(price != null); - - final Category category; - final int id; - final bool isFeatured; - final String name; - final int price; - - String get assetName => '$id-0.jpg'; - String get assetPackage => 'shrine_images'; - - @override - String toString() => '$name (id=$id)'; -} diff --git a/examples/flutter_gallery/lib/demo/shrine/model/products_repository.dart b/examples/flutter_gallery/lib/demo/shrine/model/products_repository.dart deleted file mode 100644 index 75bf4b3a36c..00000000000 --- a/examples/flutter_gallery/lib/demo/shrine/model/products_repository.dart +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright 2018-present the Flutter authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter_gallery/demo/shrine/model/product.dart'; - -class ProductsRepository { - static List loadProducts(Category category) { - const List allProducts = [ - Product( - category: Category.accessories, - id: 0, - isFeatured: true, - name: 'Vagabond sack', - price: 120, - ), - Product( - category: Category.accessories, - id: 1, - isFeatured: true, - name: 'Stella sunglasses', - price: 58, - ), - Product( - category: Category.accessories, - id: 2, - isFeatured: false, - name: 'Whitney belt', - price: 35, - ), - Product( - category: Category.accessories, - id: 3, - isFeatured: true, - name: 'Garden strand', - price: 98, - ), - Product( - category: Category.accessories, - id: 4, - isFeatured: false, - name: 'Strut earrings', - price: 34, - ), - Product( - category: Category.accessories, - id: 5, - isFeatured: false, - name: 'Varsity socks', - price: 12, - ), - Product( - category: Category.accessories, - id: 6, - isFeatured: false, - name: 'Weave keyring', - price: 16, - ), - Product( - category: Category.accessories, - id: 7, - isFeatured: true, - name: 'Gatsby hat', - price: 40, - ), - Product( - category: Category.accessories, - id: 8, - isFeatured: true, - name: 'Shrug bag', - price: 198, - ), - Product( - category: Category.home, - id: 9, - isFeatured: true, - name: 'Gilt desk trio', - price: 58, - ), - Product( - category: Category.home, - id: 10, - isFeatured: false, - name: 'Copper wire rack', - price: 18, - ), - Product( - category: Category.home, - id: 11, - isFeatured: false, - name: 'Soothe ceramic set', - price: 28, - ), - Product( - category: Category.home, - id: 12, - isFeatured: false, - name: 'Hurrahs tea set', - price: 34, - ), - Product( - category: Category.home, - id: 13, - isFeatured: true, - name: 'Blue stone mug', - price: 18, - ), - Product( - category: Category.home, - id: 14, - isFeatured: true, - name: 'Rainwater tray', - price: 27, - ), - Product( - category: Category.home, - id: 15, - isFeatured: true, - name: 'Chambray napkins', - price: 16, - ), - Product( - category: Category.home, - id: 16, - isFeatured: true, - name: 'Succulent planters', - price: 16, - ), - Product( - category: Category.home, - id: 17, - isFeatured: false, - name: 'Quartet table', - price: 175, - ), - Product( - category: Category.home, - id: 18, - isFeatured: true, - name: 'Kitchen quattro', - price: 129, - ), - Product( - category: Category.clothing, - id: 19, - isFeatured: false, - name: 'Clay sweater', - price: 48, - ), - Product( - category: Category.clothing, - id: 20, - isFeatured: false, - name: 'Sea tunic', - price: 45, - ), - Product( - category: Category.clothing, - id: 21, - isFeatured: false, - name: 'Plaster tunic', - price: 38, - ), - Product( - category: Category.clothing, - id: 22, - isFeatured: false, - name: 'White pinstripe shirt', - price: 70, - ), - Product( - category: Category.clothing, - id: 23, - isFeatured: false, - name: 'Chambray shirt', - price: 70, - ), - Product( - category: Category.clothing, - id: 24, - isFeatured: true, - name: 'Seabreeze sweater', - price: 60, - ), - Product( - category: Category.clothing, - id: 25, - isFeatured: false, - name: 'Gentry jacket', - price: 178, - ), - Product( - category: Category.clothing, - id: 26, - isFeatured: false, - name: 'Navy trousers', - price: 74, - ), - Product( - category: Category.clothing, - id: 27, - isFeatured: true, - name: 'Walter henley (white)', - price: 38, - ), - Product( - category: Category.clothing, - id: 28, - isFeatured: true, - name: 'Surf and perf shirt', - price: 48, - ), - Product( - category: Category.clothing, - id: 29, - isFeatured: true, - name: 'Ginger scarf', - price: 98, - ), - Product( - category: Category.clothing, - id: 30, - isFeatured: true, - name: 'Ramona crossover', - price: 68, - ), - Product( - category: Category.clothing, - id: 31, - isFeatured: false, - name: 'Chambray shirt', - price: 38, - ), - Product( - category: Category.clothing, - id: 32, - isFeatured: false, - name: 'Classic white collar', - price: 58, - ), - Product( - category: Category.clothing, - id: 33, - isFeatured: true, - name: 'Cerise scallop tee', - price: 42, - ), - Product( - category: Category.clothing, - id: 34, - isFeatured: false, - name: 'Shoulder rolls tee', - price: 27, - ), - Product( - category: Category.clothing, - id: 35, - isFeatured: false, - name: 'Grey slouch tank', - price: 24, - ), - Product( - category: Category.clothing, - id: 36, - isFeatured: false, - name: 'Sunshirt dress', - price: 58, - ), - Product( - category: Category.clothing, - id: 37, - isFeatured: true, - name: 'Fine lines tee', - price: 58, - ), - ]; - if (category == Category.all) { - return allProducts; - } else { - return allProducts.where((Product p) => p.category == category).toList(); - } - } -} diff --git a/examples/flutter_gallery/lib/demo/shrine/shopping_cart.dart b/examples/flutter_gallery/lib/demo/shrine/shopping_cart.dart deleted file mode 100644 index 076e6573afe..00000000000 --- a/examples/flutter_gallery/lib/demo/shrine/shopping_cart.dart +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright 2018-present the Flutter authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:scoped_model/scoped_model.dart'; - -import 'package:flutter_gallery/demo/shrine/colors.dart'; -import 'package:flutter_gallery/demo/shrine/expanding_bottom_sheet.dart'; -import 'package:flutter_gallery/demo/shrine/model/app_state_model.dart'; -import 'package:flutter_gallery/demo/shrine/model/product.dart'; - -const double _leftColumnWidth = 60.0; - -class ShoppingCartPage extends StatefulWidget { - @override - _ShoppingCartPageState createState() => _ShoppingCartPageState(); -} - -class _ShoppingCartPageState extends State { - List _createShoppingCartRows(AppStateModel model) { - return model.productsInCart.keys - .map((int id) => ShoppingCartRow( - product: model.getProductById(id), - quantity: model.productsInCart[id], - onPressed: () { - model.removeItemFromCart(id); - }, - ), - ) - .toList(); - } - - @override - Widget build(BuildContext context) { - final ThemeData localTheme = Theme.of(context); - - return Scaffold( - backgroundColor: kShrinePink50, - body: SafeArea( - child: Container( - child: ScopedModelDescendant( - builder: (BuildContext context, Widget child, AppStateModel model) { - return Stack( - children: [ - ListView( - children: [ - Row( - children: [ - SizedBox( - width: _leftColumnWidth, - child: IconButton( - icon: const Icon(Icons.keyboard_arrow_down), - onPressed: () => ExpandingBottomSheet.of(context).close(), - ), - ), - Text( - 'CART', - style: localTheme.textTheme.subhead.copyWith(fontWeight: FontWeight.w600), - ), - const SizedBox(width: 16.0), - Text('${model.totalCartQuantity} ITEMS'), - ], - ), - const SizedBox(height: 16.0), - Column( - children: _createShoppingCartRows(model), - ), - ShoppingCartSummary(model: model), - const SizedBox(height: 100.0), - ], - ), - Positioned( - bottom: 16.0, - left: 16.0, - right: 16.0, - child: RaisedButton( - shape: const BeveledRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(7.0)), - ), - color: kShrinePink100, - splashColor: kShrineBrown600, - child: const Padding( - padding: EdgeInsets.symmetric(vertical: 12.0), - child: Text('CLEAR CART'), - ), - onPressed: () { - model.clearCart(); - ExpandingBottomSheet.of(context).close(); - }, - ), - ), - ], - ); - }, - ), - ), - ), - ); - } -} - -class ShoppingCartSummary extends StatelessWidget { - const ShoppingCartSummary({this.model}); - - final AppStateModel model; - - @override - Widget build(BuildContext context) { - final TextStyle smallAmountStyle = Theme.of(context).textTheme.body1.copyWith(color: kShrineBrown600); - final TextStyle largeAmountStyle = Theme.of(context).textTheme.display1; - final NumberFormat formatter = NumberFormat.simpleCurrency( - decimalDigits: 2, - locale: Localizations.localeOf(context).toString(), - ); - - return Row( - children: [ - const SizedBox(width: _leftColumnWidth), - Expanded( - child: Padding( - padding: const EdgeInsets.only(right: 16.0), - child: Column( - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Expanded( - child: Text('TOTAL'), - ), - Text( - formatter.format(model.totalCost), - style: largeAmountStyle, - ), - ], - ), - const SizedBox(height: 16.0), - Row( - children: [ - const Expanded( - child: Text('Subtotal:'), - ), - Text( - formatter.format(model.subtotalCost), - style: smallAmountStyle, - ), - ], - ), - const SizedBox(height: 4.0), - Row( - children: [ - const Expanded( - child: Text('Shipping:'), - ), - Text( - formatter.format(model.shippingCost), - style: smallAmountStyle, - ), - ], - ), - const SizedBox(height: 4.0), - Row( - children: [ - const Expanded( - child: Text('Tax:'), - ), - Text( - formatter.format(model.tax), - style: smallAmountStyle, - ), - ], - ), - ], - ), - ), - ), - ], - ); - } -} - -class ShoppingCartRow extends StatelessWidget { - const ShoppingCartRow({ - @required this.product, - @required this.quantity, - this.onPressed, - }); - - final Product product; - final int quantity; - final VoidCallback onPressed; - - @override - Widget build(BuildContext context) { - final NumberFormat formatter = NumberFormat.simpleCurrency( - decimalDigits: 0, - locale: Localizations.localeOf(context).toString(), - ); - final ThemeData localTheme = Theme.of(context); - - return Padding( - padding: const EdgeInsets.only(bottom: 16.0), - child: Row( - key: ValueKey(product.id), - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: _leftColumnWidth, - child: IconButton( - icon: const Icon(Icons.remove_circle_outline), - onPressed: onPressed, - ), - ), - Expanded( - child: Padding( - padding: const EdgeInsets.only(right: 16.0), - child: Column( - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset( - product.assetName, - package: product.assetPackage, - fit: BoxFit.cover, - width: 75.0, - height: 75.0, - ), - const SizedBox(width: 16.0), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - child: Text('Quantity: $quantity'), - ), - Text('x ${formatter.format(product.price)}'), - ], - ), - Text( - product.name, - style: localTheme.textTheme.subhead.copyWith(fontWeight: FontWeight.w600), - ), - ], - ), - ), - ], - ), - const SizedBox(height: 16.0), - const Divider( - color: kShrineBrown900, - height: 10.0, - ), - ], - ), - ), - ), - ], - ), - ); - } -} diff --git a/examples/flutter_gallery/lib/demo/shrine/shrine_data.dart b/examples/flutter_gallery/lib/demo/shrine/shrine_data.dart new file mode 100644 index 00000000000..85dcce35bfc --- /dev/null +++ b/examples/flutter_gallery/lib/demo/shrine/shrine_data.dart @@ -0,0 +1,278 @@ +// 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 'shrine_types.dart'; + +const String _kGalleryAssetsPackage = 'flutter_gallery_assets'; + +const Vendor _ali = Vendor( + name: 'Ali’s shop', + avatarAsset: 'people/square/ali.png', + avatarAssetPackage: _kGalleryAssetsPackage, + description: + 'Ali Connor’s makes custom goods for folks of all shapes and sizes ' + 'made by hand and sometimes by machine, but always with love and care. ' + 'Custom orders are available upon request if you need something extra special.' +); + +const Vendor _peter = Vendor( + name: 'Peter’s shop', + avatarAsset: 'people/square/peter.png', + avatarAssetPackage: _kGalleryAssetsPackage, + description: + 'Peter makes great stuff for awesome people like you. Super cool and extra ' + 'awesome all of his shop’s goods are handmade with love. Custom orders are ' + 'available upon request if you need something extra special.' +); + +const Vendor _sandra = Vendor( + name: 'Sandra’s shop', + avatarAsset: 'people/square/sandra.png', + avatarAssetPackage: _kGalleryAssetsPackage, + description: + 'Sandra specializes in furniture, beauty and travel products with a classic vibe. ' + 'Custom orders are available if you’re looking for a certain color or material.' +); + +const Vendor _stella = Vendor( + name: 'Stella’s shop', + avatarAsset: 'people/square/stella.png', + avatarAssetPackage: _kGalleryAssetsPackage, + description: + 'Stella sells awesome stuff at lovely prices. made by hand and sometimes by ' + 'machine, but always with love and care. Custom orders are available upon request ' + 'if you need something extra special.' +); + +const Vendor _trevor = Vendor( + name: 'Trevor’s shop', + avatarAsset: 'people/square/trevor.png', + avatarAssetPackage: _kGalleryAssetsPackage, + description: + 'Trevor makes great stuff for awesome people like you. Super cool and extra ' + 'awesome all of his shop’s goods are handmade with love. Custom orders are ' + 'available upon request if you need something extra special.' +); + +const List _allProducts = [ + Product( + name: 'Vintage Brown Belt', + imageAsset: 'products/belt.png', + imageAssetPackage: _kGalleryAssetsPackage, + categories: ['fashion', 'latest'], + price: 300.00, + vendor: _sandra, + description: + 'Isn’t it cool when things look old, but they\'re not. Looks Old But Not makes ' + 'awesome vintage goods that are super smart. This ol’ belt just got an upgrade. ' + ), + Product( + name: 'Sunglasses', + imageAsset: 'products/sunnies.png', + imageAssetPackage: _kGalleryAssetsPackage, + categories: ['travel', 'fashion', 'beauty'], + price: 20.00, + vendor: _trevor, + description: + 'Be an optimist. Carry Sunglasses with you at all times. All Tints and ' + 'Shades products come with polarized lenses and super duper UV protection ' + 'so you can look at the sun for however long you want. Sunglasses make you ' + 'look cool, wear them.' + ), + Product( + name: 'Flatwear', + imageAsset: 'products/flatwear.png', + imageAssetPackage: _kGalleryAssetsPackage, + categories: ['furniture'], + price: 30.00, + vendor: _trevor, + description: + 'Leave the tunnel and the rain is fallin amazing things happen when you wait' + ), + Product( + name: 'Salmon Sweater', + imageAsset: 'products/sweater.png', + imageAssetPackage: _kGalleryAssetsPackage, + categories: ['fashion'], + price: 300.00, + vendor: _stella, + description: + 'Looks can be deceiving. This sweater comes in a wide variety of ' + 'flavors, including salmon, that pop as soon as they hit your eyes. ' + 'Sweaters heat quickly, so savor the warmth.' + ), + Product( + name: 'Pine Table', + imageAsset: 'products/table.png', + imageAssetPackage: _kGalleryAssetsPackage, + categories: ['furniture'], + price: 63.00, + vendor: _stella, + description: + 'Leave the tunnel and the rain is fallin amazing things happen when you wait' + ), + Product( + name: 'Green Comfort Jacket', + imageAsset: 'products/jacket.png', + imageAssetPackage: _kGalleryAssetsPackage, + categories: ['fashion'], + price: 36.00, + vendor: _ali, + description: + 'Leave the tunnel and the rain is fallin amazing things happen when you wait' + ), + Product( + name: 'Chambray Top', + imageAsset: 'products/top.png', + imageAssetPackage: _kGalleryAssetsPackage, + categories: ['fashion'], + price: 125.00, + vendor: _peter, + description: + 'Leave the tunnel and the rain is fallin amazing things happen when you wait' + ), + Product( + name: 'Blue Cup', + imageAsset: 'products/cup.png', + imageAssetPackage: _kGalleryAssetsPackage, + categories: ['travel', 'furniture'], + price: 75.00, + vendor: _sandra, + description: + 'Drinksy has been making extraordinary mugs for decades. With each ' + 'cup purchased Drinksy donates a cup to those in need. Buy yourself a mug, ' + 'buy someone else a mug.' + ), + Product( + name: 'Tea Set', + imageAsset: 'products/teaset.png', + imageAssetPackage: _kGalleryAssetsPackage, + categories: ['furniture', 'fashion'], + price: 70.00, + vendor: _trevor, + featureTitle: 'Beautiful glass teapot', + featureDescription: + 'Teapot holds extremely hot liquids and pours them from the spout.', + description: + 'Impress your guests with Tea Set by Kitchen Stuff. Teapot holds extremely ' + 'hot liquids and pours them from the spout. Use the handle, shown on the right, ' + 'so your fingers don’t get burnt while pouring.' + ), + Product( + name: 'Blue linen napkins', + imageAsset: 'products/napkins.png', + imageAssetPackage: _kGalleryAssetsPackage, + categories: ['furniture', 'fashion'], + price: 89.00, + vendor: _trevor, + description: + 'Blue linen napkins were meant to go with friends, so you may want to pick ' + 'up a bunch of these. These things are absorbant.' + ), + Product( + name: 'Dipped Earrings', + imageAsset: 'products/earrings.png', + imageAssetPackage: _kGalleryAssetsPackage, + categories: ['fashion', 'beauty'], + price: 25.00, + vendor: _stella, + description: + 'WeDipIt does it again. These hand-dipped 4 inch earrings are perfect for ' + 'the office or the beach. Just be sure you don’t drop it in a bucket of ' + 'red paint, then they won’t look dipped anymore.' + ), + Product( + name: 'Perfect Planters', + imageAsset: 'products/planters.png', + imageAssetPackage: _kGalleryAssetsPackage, + categories: ['latest', 'furniture'], + price: 30.00, + vendor: _ali, + description: + 'The Perfect Planter Co makes the best vessels for just about anything you ' + 'can pot. This set of Perfect Planters holds succulents and cuttings perfectly. ' + 'Looks great in any room. Keep out of reach from cats.' + ), + Product( + name: 'Cloud-White Dress', + imageAsset: 'products/dress.png', + imageAssetPackage: _kGalleryAssetsPackage, + categories: ['fashion'], + price: 54.00, + vendor: _sandra, + description: + 'Trying to find the perfect outift to match your mood? Try no longer. ' + 'This Cloud-White Dress has you covered for those nights when you need ' + 'to get out, or even if you’re just headed to work.' + ), + Product( + name: 'Backpack', + imageAsset: 'products/backpack.png', + imageAssetPackage: _kGalleryAssetsPackage, + categories: ['travel', 'fashion'], + price: 25.00, + vendor: _peter, + description: + 'This backpack by Bags ‘n’ stuff can hold just about anything: a laptop, ' + 'a pen, a protractor, notebooks, small animals, plugs for your devices, ' + 'sunglasses, gym clothes, shoes, gloves, two kittens, and even lunch!' + ), + Product( + name: 'Charcoal Straw Hat', + imageAsset: 'products/hat.png', + imageAssetPackage: _kGalleryAssetsPackage, + categories: ['travel', 'fashion', 'latest'], + price: 25.00, + vendor: _ali, + description: + 'This is the helmet for those warm summer days on the road. ' + 'Jetset approved, these hats have been rigorously tested. Keep that face ' + 'protected from the sun.' + ), + Product( + name: 'Ginger Scarf', + imageAsset: 'products/scarf.png', + imageAssetPackage: _kGalleryAssetsPackage, + categories: ['latest', 'fashion'], + price: 17.00, + vendor: _peter, + description: + 'Leave the tunnel and the rain is fallin amazing things happen when you wait' + ), + Product( + name: 'Blush Sweats', + imageAsset: 'products/sweats.png', + imageAssetPackage: _kGalleryAssetsPackage, + categories: ['travel', 'fashion', 'latest'], + price: 25.00, + vendor: _stella, + description: + 'Leave the tunnel and the rain is fallin amazing things happen when you wait' + ), + Product( + name: 'Mint Jumper', + imageAsset: 'products/jumper.png', + imageAssetPackage: _kGalleryAssetsPackage, + categories: ['travel', 'fashion', 'beauty'], + price: 25.00, + vendor: _peter, + description: + 'Leave the tunnel and the rain is fallin amazing things happen when you wait' + ), + Product( + name: 'Ochre Shirt', + imageAsset: 'products/shirt.png', + imageAssetPackage: _kGalleryAssetsPackage, + categories: [ 'fashion', 'latest'], + price: 120.00, + vendor: _stella, + description: + 'Leave the tunnel and the rain is fallin amazing things happen when you wait' + ) +]; + +List allProducts() { + assert(_allProducts.every((Product product) => product.isValid())); + return List.unmodifiable(_allProducts); +} diff --git a/examples/flutter_gallery/lib/demo/shrine/shrine_home.dart b/examples/flutter_gallery/lib/demo/shrine/shrine_home.dart new file mode 100644 index 00000000000..a7aa943befa --- /dev/null +++ b/examples/flutter_gallery/lib/demo/shrine/shrine_home.dart @@ -0,0 +1,411 @@ +// 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 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:meta/meta.dart'; + +import 'shrine_data.dart'; +import 'shrine_order.dart'; +import 'shrine_page.dart'; +import 'shrine_theme.dart'; +import 'shrine_types.dart'; + +const double unitSize = kToolbarHeight; + +final List _products = List.from(allProducts()); +final Map _shoppingCart = {}; + +const int _childrenPerBlock = 8; +const int _rowsPerBlock = 5; + +int _minIndexInRow(int rowIndex) { + final int blockIndex = rowIndex ~/ _rowsPerBlock; + return const [0, 2, 4, 6, 7][rowIndex % _rowsPerBlock] + blockIndex * _childrenPerBlock; +} + +int _maxIndexInRow(int rowIndex) { + final int blockIndex = rowIndex ~/ _rowsPerBlock; + return const [1, 3, 5, 6, 7][rowIndex % _rowsPerBlock] + blockIndex * _childrenPerBlock; +} + +int _rowAtIndex(int index) { + final int blockCount = index ~/ _childrenPerBlock; + return const [0, 0, 1, 1, 2, 2, 3, 4][index - blockCount * _childrenPerBlock] + blockCount * _rowsPerBlock; +} + +int _columnAtIndex(int index) { + return const [0, 1, 0, 1, 0, 1, 0, 0][index % _childrenPerBlock]; +} + +int _columnSpanAtIndex(int index) { + return const [1, 1, 1, 1, 1, 1, 2, 2][index % _childrenPerBlock]; +} + +// The Shrine home page arranges the product cards into two columns. The card +// on every 4th and 5th row spans two columns. +class _ShrineGridLayout extends SliverGridLayout { + const _ShrineGridLayout({ + @required this.rowStride, + @required this.columnStride, + @required this.tileHeight, + @required this.tileWidth, + }); + + final double rowStride; + final double columnStride; + final double tileHeight; + final double tileWidth; + + @override + int getMinChildIndexForScrollOffset(double scrollOffset) { + return _minIndexInRow(scrollOffset ~/ rowStride); + } + + @override + int getMaxChildIndexForScrollOffset(double scrollOffset) { + return _maxIndexInRow(scrollOffset ~/ rowStride); + } + + @override + SliverGridGeometry getGeometryForChildIndex(int index) { + final int row = _rowAtIndex(index); + final int column = _columnAtIndex(index); + final int columnSpan = _columnSpanAtIndex(index); + return SliverGridGeometry( + scrollOffset: row * rowStride, + crossAxisOffset: column * columnStride, + mainAxisExtent: tileHeight, + crossAxisExtent: tileWidth + (columnSpan - 1) * columnStride, + ); + } + + @override + double computeMaxScrollOffset(int childCount) { + if (childCount == 0) + return 0.0; + final int rowCount = _rowAtIndex(childCount - 1) + 1; + final double rowSpacing = rowStride - tileHeight; + return rowStride * rowCount - rowSpacing; + } +} + +class _ShrineGridDelegate extends SliverGridDelegate { + static const double _spacing = 8.0; + + @override + SliverGridLayout getLayout(SliverConstraints constraints) { + final double tileWidth = (constraints.crossAxisExtent - _spacing) / 2.0; + const double tileHeight = 40.0 + 144.0 + 40.0; + return _ShrineGridLayout( + tileWidth: tileWidth, + tileHeight: tileHeight, + rowStride: tileHeight + _spacing, + columnStride: tileWidth + _spacing, + ); + } + + @override + bool shouldRelayout(covariant SliverGridDelegate oldDelegate) => false; +} + +// Displays the Vendor's name and avatar. +class _VendorItem extends StatelessWidget { + const _VendorItem({ Key key, @required this.vendor }) + : assert(vendor != null), + super(key: key); + + final Vendor vendor; + + @override + Widget build(BuildContext context) { + return SizedBox( + height: 24.0, + child: Row( + children: [ + SizedBox( + width: 24.0, + child: ClipRRect( + borderRadius: BorderRadius.circular(12.0), + child: Image.asset( + vendor.avatarAsset, + package: vendor.avatarAssetPackage, + fit: BoxFit.cover, + ), + ), + ), + const SizedBox(width: 8.0), + Expanded( + child: Text(vendor.name, style: ShrineTheme.of(context).vendorItemStyle), + ), + ], + ), + ); + } +} + +// Displays the product's price. If the product is in the shopping cart then the +// background is highlighted. +abstract class _PriceItem extends StatelessWidget { + const _PriceItem({ Key key, @required this.product }) + : assert(product != null), + super(key: key); + + final Product product; + + Widget buildItem(BuildContext context, TextStyle style, EdgeInsets padding) { + BoxDecoration decoration; + if (_shoppingCart[product] != null) + decoration = BoxDecoration(color: ShrineTheme.of(context).priceHighlightColor); + + return Container( + padding: padding, + decoration: decoration, + child: Text(product.priceString, style: style), + ); + } +} + +class _ProductPriceItem extends _PriceItem { + const _ProductPriceItem({ Key key, Product product }) : super(key: key, product: product); + + @override + Widget build(BuildContext context) { + return buildItem( + context, + ShrineTheme.of(context).priceStyle, + const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), + ); + } +} + +class _FeaturePriceItem extends _PriceItem { + const _FeaturePriceItem({ Key key, Product product }) : super(key: key, product: product); + + @override + Widget build(BuildContext context) { + return buildItem( + context, + ShrineTheme.of(context).featurePriceStyle, + const EdgeInsets.symmetric(horizontal: 24.0, vertical: 16.0), + ); + } +} + +class _HeadingLayout extends MultiChildLayoutDelegate { + _HeadingLayout(); + + static const String price = 'price'; + static const String image = 'image'; + static const String title = 'title'; + static const String description = 'description'; + static const String vendor = 'vendor'; + + @override + void performLayout(Size size) { + final Size priceSize = layoutChild(price, BoxConstraints.loose(size)); + positionChild(price, Offset(size.width - priceSize.width, 0.0)); + + final double halfWidth = size.width / 2.0; + final double halfHeight = size.height / 2.0; + const double halfUnit = unitSize / 2.0; + const double margin = 16.0; + + final Size imageSize = layoutChild(image, BoxConstraints.loose(size)); + final double imageX = imageSize.width < halfWidth - halfUnit + ? halfWidth / 2.0 - imageSize.width / 2.0 - halfUnit + : halfWidth - imageSize.width; + positionChild(image, Offset(imageX, halfHeight - imageSize.height / 2.0)); + + final double maxTitleWidth = halfWidth + unitSize - margin; + final BoxConstraints titleBoxConstraints = BoxConstraints(maxWidth: maxTitleWidth); + final Size titleSize = layoutChild(title, titleBoxConstraints); + final double titleX = halfWidth - unitSize; + final double titleY = halfHeight - titleSize.height; + positionChild(title, Offset(titleX, titleY)); + + final Size descriptionSize = layoutChild(description, titleBoxConstraints); + final double descriptionY = titleY + titleSize.height + margin; + positionChild(description, Offset(titleX, descriptionY)); + + layoutChild(vendor, titleBoxConstraints); + final double vendorY = descriptionY + descriptionSize.height + margin; + positionChild(vendor, Offset(titleX, vendorY)); + } + + @override + bool shouldRelayout(_HeadingLayout oldDelegate) => false; +} + +// A card that highlights the "featured" catalog item. +class _Heading extends StatelessWidget { + _Heading({ Key key, @required this.product }) + : assert(product != null), + assert(product.featureTitle != null), + assert(product.featureDescription != null), + super(key: key); + + final Product product; + + @override + Widget build(BuildContext context) { + final Size screenSize = MediaQuery.of(context).size; + final ShrineTheme theme = ShrineTheme.of(context); + return MergeSemantics( + child: SizedBox( + height: screenSize.width > screenSize.height + ? (screenSize.height - kToolbarHeight) * 0.85 + : (screenSize.height - kToolbarHeight) * 0.70, + child: Container( + decoration: BoxDecoration( + color: theme.cardBackgroundColor, + border: Border(bottom: BorderSide(color: theme.dividerColor)), + ), + child: CustomMultiChildLayout( + delegate: _HeadingLayout(), + children: [ + LayoutId( + id: _HeadingLayout.price, + child: _FeaturePriceItem(product: product), + ), + LayoutId( + id: _HeadingLayout.image, + child: Image.asset( + product.imageAsset, + package: product.imageAssetPackage, + fit: BoxFit.cover, + ), + ), + LayoutId( + id: _HeadingLayout.title, + child: Text(product.featureTitle, style: theme.featureTitleStyle), + ), + LayoutId( + id: _HeadingLayout.description, + child: Text(product.featureDescription, style: theme.featureStyle), + ), + LayoutId( + id: _HeadingLayout.vendor, + child: _VendorItem(vendor: product.vendor), + ), + ], + ), + ), + ), + ); + } +} + +// A card that displays a product's image, price, and vendor. The _ProductItem +// cards appear in a grid below the heading. +class _ProductItem extends StatelessWidget { + const _ProductItem({ Key key, @required this.product, this.onPressed }) + : assert(product != null), + super(key: key); + + final Product product; + final VoidCallback onPressed; + + @override + Widget build(BuildContext context) { + return MergeSemantics( + child: Card( + child: Stack( + children: [ + Column( + children: [ + Align( + alignment: Alignment.centerRight, + child: _ProductPriceItem(product: product), + ), + Container( + width: 144.0, + height: 144.0, + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Hero( + tag: product.tag, + child: Image.asset( + product.imageAsset, + package: product.imageAssetPackage, + fit: BoxFit.contain, + ), + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: _VendorItem(vendor: product.vendor), + ), + ], + ), + Material( + type: MaterialType.transparency, + child: InkWell(onTap: onPressed), + ), + ], + ), + ), + ); + } +} + +// The Shrine app's home page. Displays the featured item above a grid +// of the product items. +class ShrineHome extends StatefulWidget { + @override + _ShrineHomeState createState() => _ShrineHomeState(); +} + +class _ShrineHomeState extends State { + static final GlobalKey _scaffoldKey = GlobalKey(debugLabel: 'Shrine Home'); + static final _ShrineGridDelegate gridDelegate = _ShrineGridDelegate(); + + Future _showOrderPage(Product product) async { + final Order order = _shoppingCart[product] ?? Order(product: product); + final Order completedOrder = await Navigator.push(context, ShrineOrderRoute( + order: order, + builder: (BuildContext context) { + return OrderPage( + order: order, + products: _products, + shoppingCart: _shoppingCart, + ); + } + )); + assert(completedOrder.product != null); + if (completedOrder.quantity == 0) + _shoppingCart.remove(completedOrder.product); + } + + @override + Widget build(BuildContext context) { + final Product featured = _products.firstWhere((Product product) => product.featureDescription != null); + return ShrinePage( + scaffoldKey: _scaffoldKey, + products: _products, + shoppingCart: _shoppingCart, + body: CustomScrollView( + slivers: [ + SliverToBoxAdapter(child: _Heading(product: featured)), + SliverSafeArea( + top: false, + minimum: const EdgeInsets.all(16.0), + sliver: SliverGrid( + gridDelegate: gridDelegate, + delegate: SliverChildListDelegate( + _products.map((Product product) { + return _ProductItem( + product: product, + onPressed: () { _showOrderPage(product); }, + ); + }).toList(), + ), + ), + ), + ], + ), + ); + } +} diff --git a/examples/flutter_gallery/lib/demo/shrine/shrine_order.dart b/examples/flutter_gallery/lib/demo/shrine/shrine_order.dart new file mode 100644 index 00000000000..135f1c9d775 --- /dev/null +++ b/examples/flutter_gallery/lib/demo/shrine/shrine_order.dart @@ -0,0 +1,340 @@ +// 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/material.dart'; + +import '../shrine_demo.dart' show ShrinePageRoute; +import 'shrine_page.dart'; +import 'shrine_theme.dart'; +import 'shrine_types.dart'; + +// Displays the product title's, description, and order quantity dropdown. +class _ProductItem extends StatelessWidget { + const _ProductItem({ + Key key, + @required this.product, + @required this.quantity, + @required this.onChanged, + }) : assert(product != null), + assert(quantity != null), + assert(onChanged != null), + super(key: key); + + final Product product; + final int quantity; + final ValueChanged onChanged; + + @override + Widget build(BuildContext context) { + final ShrineTheme theme = ShrineTheme.of(context); + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text(product.name, style: theme.featureTitleStyle), + const SizedBox(height: 24.0), + Text(product.description, style: theme.featureStyle), + const SizedBox(height: 16.0), + Padding( + padding: const EdgeInsets.only(top: 8.0, bottom: 8.0, right: 88.0), + child: DropdownButtonHideUnderline( + child: Container( + decoration: BoxDecoration( + border: Border.all( + color: const Color(0xFFD9D9D9), + ), + ), + child: DropdownButton( + items: [0, 1, 2, 3, 4, 5].map>((int value) { + return DropdownMenuItem( + value: value, + child: Padding( + padding: const EdgeInsets.only(left: 8.0), + child: Text('Quantity $value', style: theme.quantityMenuStyle), + ), + ); + }).toList(), + value: quantity, + onChanged: onChanged, + ), + ), + ), + ), + ], + ); + } +} + +// Vendor name and description +class _VendorItem extends StatelessWidget { + const _VendorItem({ Key key, @required this.vendor }) + : assert(vendor != null), + super(key: key); + + final Vendor vendor; + + @override + Widget build(BuildContext context) { + final ShrineTheme theme = ShrineTheme.of(context); + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + SizedBox( + height: 24.0, + child: Align( + alignment: Alignment.bottomLeft, + child: Text(vendor.name, style: theme.vendorTitleStyle), + ), + ), + const SizedBox(height: 16.0), + Text(vendor.description, style: theme.vendorStyle), + ], + ); + } +} + +// Layout the order page's heading: the product's image, the +// title/description/dropdown product item, and the vendor item. +class _HeadingLayout extends MultiChildLayoutDelegate { + _HeadingLayout(); + + static const String image = 'image'; + static const String icon = 'icon'; + static const String product = 'product'; + static const String vendor = 'vendor'; + + @override + void performLayout(Size size) { + const double margin = 56.0; + final bool landscape = size.width > size.height; + final double imageWidth = (landscape ? size.width / 2.0 : size.width) - margin * 2.0; + final BoxConstraints imageConstraints = BoxConstraints(maxHeight: 224.0, maxWidth: imageWidth); + final Size imageSize = layoutChild(image, imageConstraints); + const double imageY = 0.0; + positionChild(image, const Offset(margin, imageY)); + + final double productWidth = landscape ? size.width / 2.0 : size.width - margin; + final BoxConstraints productConstraints = BoxConstraints(maxWidth: productWidth); + final Size productSize = layoutChild(product, productConstraints); + final double productX = landscape ? size.width / 2.0 : margin; + final double productY = landscape ? 0.0 : imageY + imageSize.height + 16.0; + positionChild(product, Offset(productX, productY)); + + final Size iconSize = layoutChild(icon, BoxConstraints.loose(size)); + positionChild(icon, Offset(productX - iconSize.width - 16.0, productY + 8.0)); + + final double vendorWidth = landscape ? size.width - margin : productWidth; + layoutChild(vendor, BoxConstraints(maxWidth: vendorWidth)); + final double vendorX = landscape ? margin : productX; + final double vendorY = productY + productSize.height + 16.0; + positionChild(vendor, Offset(vendorX, vendorY)); + } + + @override + bool shouldRelayout(_HeadingLayout oldDelegate) => true; +} + +// Describes a product and vendor in detail, supports specifying +// a order quantity (0-5). Appears at the top of the OrderPage. +class _Heading extends StatelessWidget { + const _Heading({ + Key key, + @required this.product, + @required this.quantity, + this.quantityChanged, + }) : assert(product != null), + assert(quantity != null && quantity >= 0 && quantity <= 5), + super(key: key); + + final Product product; + final int quantity; + final ValueChanged quantityChanged; + + @override + Widget build(BuildContext context) { + final Size screenSize = MediaQuery.of(context).size; + return SizedBox( + height: (screenSize.height - kToolbarHeight) * 1.35, + child: Material( + type: MaterialType.card, + elevation: 0.0, + child: Padding( + padding: const EdgeInsets.only(left: 16.0, top: 18.0, right: 16.0, bottom: 24.0), + child: CustomMultiChildLayout( + delegate: _HeadingLayout(), + children: [ + LayoutId( + id: _HeadingLayout.image, + child: Hero( + tag: product.tag, + child: Image.asset( + product.imageAsset, + package: product.imageAssetPackage, + fit: BoxFit.contain, + alignment: Alignment.center, + ), + ), + ), + LayoutId( + id: _HeadingLayout.icon, + child: const Icon( + Icons.info_outline, + size: 24.0, + color: Color(0xFFFFE0E0), + ), + ), + LayoutId( + id: _HeadingLayout.product, + child: _ProductItem( + product: product, + quantity: quantity, + onChanged: quantityChanged, + ), + ), + LayoutId( + id: _HeadingLayout.vendor, + child: _VendorItem(vendor: product.vendor), + ), + ], + ), + ), + ), + ); + } +} + +class OrderPage extends StatefulWidget { + OrderPage({ + Key key, + @required this.order, + @required this.products, + @required this.shoppingCart, + }) : assert(order != null), + assert(products != null && products.isNotEmpty), + assert(shoppingCart != null), + super(key: key); + + final Order order; + final List products; + final Map shoppingCart; + + @override + _OrderPageState createState() => _OrderPageState(); +} + +// Displays a product's heading above photos of all of the other products +// arranged in two columns. Enables the user to specify a quantity and add an +// order to the shopping cart. +class _OrderPageState extends State { + GlobalKey scaffoldKey; + + @override + void initState() { + super.initState(); + scaffoldKey = GlobalKey(debugLabel: 'Shrine Order ${widget.order}'); + } + + Order get currentOrder => ShrineOrderRoute.of(context).order; + + set currentOrder(Order value) { + ShrineOrderRoute.of(context).order = value; + } + + void updateOrder({ int quantity, bool inCart }) { + final Order newOrder = currentOrder.copyWith(quantity: quantity, inCart: inCart); + if (currentOrder != newOrder) { + setState(() { + widget.shoppingCart[newOrder.product] = newOrder; + currentOrder = newOrder; + }); + } + } + + void showSnackBarMessage(String message) { + scaffoldKey.currentState.showSnackBar(SnackBar(content: Text(message))); + } + + @override + Widget build(BuildContext context) { + return ShrinePage( + scaffoldKey: scaffoldKey, + products: widget.products, + shoppingCart: widget.shoppingCart, + floatingActionButton: FloatingActionButton( + onPressed: () { + updateOrder(inCart: true); + final int n = currentOrder.quantity; + final String item = currentOrder.product.name; + showSnackBarMessage( + 'There ${ n == 1 ? "is one $item item" : "are $n $item items" } in the shopping cart.' + ); + }, + backgroundColor: const Color(0xFF16F0F0), + tooltip: 'Add to cart', + child: const Icon( + Icons.add_shopping_cart, + color: Colors.black, + ), + ), + body: CustomScrollView( + slivers: [ + SliverToBoxAdapter( + child: _Heading( + product: widget.order.product, + quantity: currentOrder.quantity, + quantityChanged: (int value) { updateOrder(quantity: value); }, + ), + ), + SliverSafeArea( + top: false, + minimum: const EdgeInsets.fromLTRB(8.0, 32.0, 8.0, 8.0), + sliver: SliverGrid( + gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent( + maxCrossAxisExtent: 248.0, + mainAxisSpacing: 8.0, + crossAxisSpacing: 8.0, + ), + delegate: SliverChildListDelegate( + widget.products + .where((Product product) => product != widget.order.product) + .map((Product product) { + return Card( + elevation: 1.0, + child: Image.asset( + product.imageAsset, + package: product.imageAssetPackage, + fit: BoxFit.contain, + ), + ); + }).toList(), + ), + ), + ), + ], + ), + ); + } +} + +// Displays a full-screen modal OrderPage. +// +// The order field will be replaced each time the user reconfigures the order. +// When the user backs out of this route the completer's value will be the +// final value of the order field. +class ShrineOrderRoute extends ShrinePageRoute { + ShrineOrderRoute({ + @required this.order, + WidgetBuilder builder, + RouteSettings settings, + }) : assert(order != null), + super(builder: builder, settings: settings); + + Order order; + + @override + Order get currentResult => order; + + static ShrineOrderRoute of(BuildContext context) => ModalRoute.of(context); +} diff --git a/examples/flutter_gallery/lib/demo/shrine/shrine_page.dart b/examples/flutter_gallery/lib/demo/shrine/shrine_page.dart new file mode 100644 index 00000000000..b31cb3ddcc4 --- /dev/null +++ b/examples/flutter_gallery/lib/demo/shrine/shrine_page.dart @@ -0,0 +1,149 @@ +// 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/material.dart'; + +import 'shrine_theme.dart'; +import 'shrine_types.dart'; + +enum ShrineAction { + sortByPrice, + sortByProduct, + emptyCart +} + +class ShrinePage extends StatefulWidget { + const ShrinePage({ + Key key, + @required this.scaffoldKey, + @required this.body, + this.floatingActionButton, + this.products, + this.shoppingCart + }) : assert(body != null), + assert(scaffoldKey != null), + super(key: key); + + final GlobalKey scaffoldKey; + final Widget body; + final Widget floatingActionButton; + final List products; + final Map shoppingCart; + + @override + ShrinePageState createState() => ShrinePageState(); +} + +/// Defines the Scaffold, AppBar, etc that the demo pages have in common. +class ShrinePageState extends State { + double _appBarElevation = 0.0; + + bool _handleScrollNotification(ScrollNotification notification) { + final double elevation = notification.metrics.extentBefore <= 0.0 ? 0.0 : 1.0; + if (elevation != _appBarElevation) { + setState(() { + _appBarElevation = elevation; + }); + } + return false; + } + + void _showShoppingCart() { + showModalBottomSheet(context: context, builder: (BuildContext context) { + if (widget.shoppingCart.isEmpty) { + return const Padding( + padding: EdgeInsets.all(24.0), + child: Text('The shopping cart is empty') + ); + } + return ListView( + padding: kMaterialListPadding, + children: widget.shoppingCart.values.map((Order order) { + return ListTile( + title: Text(order.product.name), + leading: Text('${order.quantity}'), + subtitle: Text(order.product.vendor.name) + ); + }).toList(), + ); + }); + } + + void _sortByPrice() { + widget.products.sort((Product a, Product b) => a.price.compareTo(b.price)); + } + + void _sortByProduct() { + widget.products.sort((Product a, Product b) => a.name.compareTo(b.name)); + } + + void _emptyCart() { + widget.shoppingCart.clear(); + widget.scaffoldKey.currentState.showSnackBar(const SnackBar(content: Text('Shopping cart is empty'))); + } + + @override + Widget build(BuildContext context) { + final ShrineTheme theme = ShrineTheme.of(context); + return Scaffold( + key: widget.scaffoldKey, + appBar: AppBar( + elevation: _appBarElevation, + backgroundColor: theme.appBarBackgroundColor, + iconTheme: Theme.of(context).iconTheme, + brightness: Brightness.light, + flexibleSpace: Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide(color: theme.dividerColor) + ) + ) + ), + title: Text('SHRINE', style: ShrineTheme.of(context).appBarTitleStyle), + centerTitle: true, + actions: [ + IconButton( + icon: const Icon(Icons.shopping_cart), + tooltip: 'Shopping cart', + onPressed: _showShoppingCart + ), + PopupMenuButton( + itemBuilder: (BuildContext context) => >[ + const PopupMenuItem( + value: ShrineAction.sortByPrice, + child: Text('Sort by price') + ), + const PopupMenuItem( + value: ShrineAction.sortByProduct, + child: Text('Sort by product') + ), + const PopupMenuItem( + value: ShrineAction.emptyCart, + child: Text('Empty shopping cart') + ) + ], + onSelected: (ShrineAction action) { + switch (action) { + case ShrineAction.sortByPrice: + setState(_sortByPrice); + break; + case ShrineAction.sortByProduct: + setState(_sortByProduct); + break; + case ShrineAction.emptyCart: + setState(_emptyCart); + break; + } + } + ) + ] + ), + floatingActionButton: widget.floatingActionButton, + body: NotificationListener( + onNotification: _handleScrollNotification, + child: widget.body + ) + ); + } +} diff --git a/examples/flutter_gallery/lib/demo/shrine/shrine_theme.dart b/examples/flutter_gallery/lib/demo/shrine/shrine_theme.dart new file mode 100644 index 00000000000..8e146348700 --- /dev/null +++ b/examples/flutter_gallery/lib/demo/shrine/shrine_theme.dart @@ -0,0 +1,54 @@ +// 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/material.dart'; + +class ShrineStyle extends TextStyle { + const ShrineStyle.roboto(double size, FontWeight weight, Color color) + : super(inherit: false, color: color, fontSize: size, fontWeight: weight, textBaseline: TextBaseline.alphabetic); + + const ShrineStyle.abrilFatface(double size, FontWeight weight, Color color) + : super(inherit: false, color: color, fontFamily: 'AbrilFatface', fontSize: size, fontWeight: weight, textBaseline: TextBaseline.alphabetic); +} + +TextStyle robotoRegular12(Color color) => ShrineStyle.roboto(12.0, FontWeight.w500, color); +TextStyle robotoLight12(Color color) => ShrineStyle.roboto(12.0, FontWeight.w300, color); +TextStyle robotoRegular14(Color color) => ShrineStyle.roboto(14.0, FontWeight.w500, color); +TextStyle robotoMedium14(Color color) => ShrineStyle.roboto(14.0, FontWeight.w600, color); +TextStyle robotoLight14(Color color) => ShrineStyle.roboto(14.0, FontWeight.w300, color); +TextStyle robotoRegular16(Color color) => ShrineStyle.roboto(16.0, FontWeight.w500, color); +TextStyle robotoRegular20(Color color) => ShrineStyle.roboto(20.0, FontWeight.w500, color); +TextStyle abrilFatfaceRegular24(Color color) => ShrineStyle.abrilFatface(24.0, FontWeight.w500, color); +TextStyle abrilFatfaceRegular34(Color color) => ShrineStyle.abrilFatface(34.0, FontWeight.w500, color); + +/// The TextStyles and Colors used for titles, labels, and descriptions. This +/// InheritedWidget is shared by all of the routes and widgets created for +/// the Shrine app. +class ShrineTheme extends InheritedWidget { + ShrineTheme({ Key key, @required Widget child }) + : assert(child != null), + super(key: key, child: child); + + final Color cardBackgroundColor = Colors.white; + final Color appBarBackgroundColor = Colors.white; + final Color dividerColor = const Color(0xFFD9D9D9); + final Color priceHighlightColor = const Color(0xFFFFE0E0); + + final TextStyle appBarTitleStyle = robotoRegular20(Colors.black87); + final TextStyle vendorItemStyle = robotoRegular12(const Color(0xFF81959D)); + final TextStyle priceStyle = robotoRegular14(Colors.black87); + final TextStyle featureTitleStyle = abrilFatfaceRegular34(const Color(0xFF0A3142)); + final TextStyle featurePriceStyle = robotoRegular16(Colors.black87); + final TextStyle featureStyle = robotoLight14(Colors.black54); + final TextStyle orderTitleStyle = abrilFatfaceRegular24(Colors.black87); + final TextStyle orderStyle = robotoLight14(Colors.black54); + final TextStyle vendorTitleStyle = robotoMedium14(Colors.black87); + final TextStyle vendorStyle = robotoLight14(Colors.black54); + final TextStyle quantityMenuStyle = robotoLight14(Colors.black54); + + static ShrineTheme of(BuildContext context) => context.inheritFromWidgetOfExactType(ShrineTheme); + + @override + bool updateShouldNotify(ShrineTheme oldWidget) => false; +} diff --git a/examples/flutter_gallery/lib/demo/shrine/shrine_types.dart b/examples/flutter_gallery/lib/demo/shrine/shrine_types.dart new file mode 100644 index 00000000000..884e64618e1 --- /dev/null +++ b/examples/flutter_gallery/lib/demo/shrine/shrine_types.dart @@ -0,0 +1,107 @@ +// 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 'dart:ui' show hashValues; + +import 'package:flutter/foundation.dart'; + +class Vendor { + const Vendor({ + this.name, + this.description, + this.avatarAsset, + this.avatarAssetPackage, + }); + + final String name; + final String description; + final String avatarAsset; + final String avatarAssetPackage; + + bool isValid() { + return name != null && + description != null && + avatarAsset != null; + } + + @override + String toString() => 'Vendor($name)'; +} + +class Product { + const Product({ + this.name, + this.description, + this.featureTitle, + this.featureDescription, + this.imageAsset, + this.imageAssetPackage, + this.categories, + this.price, + this.vendor + }); + + final String name; + final String description; + final String featureTitle; + final String featureDescription; + final String imageAsset; + final String imageAssetPackage; + final List categories; + final double price; + final Vendor vendor; + + String get tag => name; // Unique value for Heroes + String get priceString => '\$${price.floor()}'; + + bool isValid() { + return name != null && + description != null && + imageAsset != null && + categories != null && + categories.isNotEmpty && + price != null && + vendor.isValid(); + } + + @override + String toString() => 'Product($name)'; +} + +class Order { + Order({ @required this.product, this.quantity = 1, this.inCart = false }) + : assert(product != null), + assert(quantity != null && quantity >= 0), + assert(inCart != null); + + final Product product; + final int quantity; + final bool inCart; + + Order copyWith({ Product product, int quantity, bool inCart }) { + return Order( + product: product ?? this.product, + quantity: quantity ?? this.quantity, + inCart: inCart ?? this.inCart + ); + } + + @override + bool operator ==(dynamic other) { + if (identical(this, other)) + return true; + if (other.runtimeType != runtimeType) + return false; + final Order typedOther = other; + return product == typedOther.product && + quantity == typedOther.quantity && + inCart == typedOther.inCart; + } + + @override + int get hashCode => hashValues(product, quantity, inCart); + + @override + String toString() => 'Order($product, quantity=$quantity, inCart=$inCart)'; +} diff --git a/examples/flutter_gallery/lib/demo/shrine/supplemental/asymmetric_view.dart b/examples/flutter_gallery/lib/demo/shrine/supplemental/asymmetric_view.dart deleted file mode 100644 index 10922a1429f..00000000000 --- a/examples/flutter_gallery/lib/demo/shrine/supplemental/asymmetric_view.dart +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2018-present the Flutter authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; - -import 'package:flutter_gallery/demo/shrine/model/product.dart'; -import 'package:flutter_gallery/demo/shrine/supplemental/product_columns.dart'; - -class AsymmetricView extends StatelessWidget { - const AsymmetricView({Key key, this.products}) : super(key: key); - - final List products; - - List _buildColumns(BuildContext context) { - if (products == null || products.isEmpty) { - return const []; - } - - // This will return a list of columns. It will oscillate between the two - // kinds of columns. Even cases of the index (0, 2, 4, etc) will be - // TwoProductCardColumn and the odd cases will be OneProductCardColumn. - // - // Each pair of columns will advance us 3 products forward (2 + 1). That's - // some kinda awkward math so we use _evenCasesIndex and _oddCasesIndex as - // helpers for creating the index of the product list that will correspond - // to the index of the list of columns. - return List.generate(_listItemCount(products.length), (int index) { - double width = .59 * MediaQuery.of(context).size.width; - Widget column; - if (index % 2 == 0) { - /// Even cases - final int bottom = _evenCasesIndex(index); - column = TwoProductCardColumn( - bottom: products[bottom], - top: products.length - 1 >= bottom + 1 - ? products[bottom + 1] - : null, - ); - width += 32.0; - } else { - /// Odd cases - column = OneProductCardColumn( - product: products[_oddCasesIndex(index)], - ); - } - return Container( - width: width, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: column, - ), - ); - }).toList(); - } - - int _evenCasesIndex(int input) { - // The operator ~/ is a cool one. It's the truncating division operator. It - // divides the number and if there's a remainder / decimal, it cuts it off. - // This is like dividing and then casting the result to int. Also, it's - // functionally equivalent to floor() in this case. - return input ~/ 2 * 3; - } - - int _oddCasesIndex(int input) { - assert(input > 0); - return (input / 2).ceil() * 3 - 1; - } - - int _listItemCount(int totalItems) { - return (totalItems % 3 == 0) - ? totalItems ~/ 3 * 2 - : (totalItems / 3).ceil() * 2 - 1; - } - - @override - Widget build(BuildContext context) { - return ListView( - scrollDirection: Axis.horizontal, - padding: const EdgeInsets.fromLTRB(0.0, 34.0, 16.0, 44.0), - children: _buildColumns(context), - physics: const AlwaysScrollableScrollPhysics(), - ); - } -} diff --git a/examples/flutter_gallery/lib/demo/shrine/supplemental/cut_corners_border.dart b/examples/flutter_gallery/lib/demo/shrine/supplemental/cut_corners_border.dart deleted file mode 100644 index 687685bfd47..00000000000 --- a/examples/flutter_gallery/lib/demo/shrine/supplemental/cut_corners_border.dart +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2018-present the Flutter authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'dart:ui' show lerpDouble; - -import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; - -class CutCornersBorder extends OutlineInputBorder { - const CutCornersBorder({ - BorderSide borderSide = BorderSide.none, - BorderRadius borderRadius = const BorderRadius.all(Radius.circular(2.0)), - this.cut = 7.0, - double gapPadding = 2.0, - }) : super( - borderSide: borderSide, - borderRadius: borderRadius, - gapPadding: gapPadding, - ); - - @override - CutCornersBorder copyWith({ - BorderSide borderSide, - BorderRadius borderRadius, - double gapPadding, - double cut, - }) { - return CutCornersBorder( - borderSide: borderSide ?? this.borderSide, - borderRadius: borderRadius ?? this.borderRadius, - gapPadding: gapPadding ?? this.gapPadding, - cut: cut ?? this.cut, - ); - } - - final double cut; - - @override - ShapeBorder lerpFrom(ShapeBorder a, double t) { - if (a is CutCornersBorder) { - final CutCornersBorder outline = a; - return CutCornersBorder( - borderRadius: BorderRadius.lerp(outline.borderRadius, borderRadius, t), - borderSide: BorderSide.lerp(outline.borderSide, borderSide, t), - cut: cut, - gapPadding: outline.gapPadding, - ); - } - return super.lerpFrom(a, t); - } - - @override - ShapeBorder lerpTo(ShapeBorder b, double t) { - if (b is CutCornersBorder) { - final CutCornersBorder outline = b; - return CutCornersBorder( - borderRadius: BorderRadius.lerp(borderRadius, outline.borderRadius, t), - borderSide: BorderSide.lerp(borderSide, outline.borderSide, t), - cut: cut, - gapPadding: outline.gapPadding, - ); - } - return super.lerpTo(b, t); - } - - Path _notchedCornerPath(Rect center, [double start = 0.0, double extent = 0.0]) { - final Path path = Path(); - if (start > 0.0 || extent > 0.0) { - path.relativeMoveTo(extent + start, center.top); - _notchedSidesAndBottom(center, path); - path..lineTo(center.left + cut, center.top)..lineTo(start, center.top); - } else { - path.moveTo(center.left + cut, center.top); - _notchedSidesAndBottom(center, path); - path.lineTo(center.left + cut, center.top); - } - return path; - } - - Path _notchedSidesAndBottom(Rect center, Path path) { - return path - ..lineTo(center.right - cut, center.top) - ..lineTo(center.right, center.top + cut) - ..lineTo(center.right, center.top + center.height - cut) - ..lineTo(center.right - cut, center.top + center.height) - ..lineTo(center.left + cut, center.top + center.height) - ..lineTo(center.left, center.top + center.height - cut) - ..lineTo(center.left, center.top + cut); - } - - @override - void paint( - Canvas canvas, - Rect rect, { - double gapStart, - double gapExtent = 0.0, - double gapPercentage = 0.0, - TextDirection textDirection, - }) { - assert(gapExtent != null); - assert(gapPercentage >= 0.0 && gapPercentage <= 1.0); - - final Paint paint = borderSide.toPaint(); - final RRect outer = borderRadius.toRRect(rect); - if (gapStart == null || gapExtent <= 0.0 || gapPercentage == 0.0) { - canvas.drawPath(_notchedCornerPath(outer.middleRect), paint); - } else { - final double extent = lerpDouble(0.0, gapExtent + gapPadding * 2.0, gapPercentage); - switch (textDirection) { - case TextDirection.rtl: - { - final Path path = _notchedCornerPath(outer.middleRect, gapStart + gapPadding - extent, extent); - canvas.drawPath(path, paint); - break; - } - case TextDirection.ltr: - { - final Path path = _notchedCornerPath(outer.middleRect, gapStart - gapPadding, extent); - canvas.drawPath(path, paint); - break; - } - } - } - } -} diff --git a/examples/flutter_gallery/lib/demo/shrine/supplemental/product_card.dart b/examples/flutter_gallery/lib/demo/shrine/supplemental/product_card.dart deleted file mode 100644 index d0688118f51..00000000000 --- a/examples/flutter_gallery/lib/demo/shrine/supplemental/product_card.dart +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2018-present the Flutter authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:scoped_model/scoped_model.dart'; - -import 'package:flutter_gallery/demo/shrine/model/app_state_model.dart'; -import 'package:flutter_gallery/demo/shrine/model/product.dart'; - -class ProductCard extends StatelessWidget { - const ProductCard({ this.imageAspectRatio = 33 / 49, this.product }) - : assert(imageAspectRatio == null || imageAspectRatio > 0); - - final double imageAspectRatio; - final Product product; - - static const double kTextBoxHeight = 65.0; - - @override - Widget build(BuildContext context) { - final NumberFormat formatter = NumberFormat.simpleCurrency( - decimalDigits: 0, - locale: Localizations.localeOf(context).toString(), - ); - - final ThemeData theme = Theme.of(context); - - final Image imageWidget = Image.asset( - product.assetName, - package: product.assetPackage, - fit: BoxFit.cover, - ); - - return ScopedModelDescendant( - builder: (BuildContext context, Widget child, AppStateModel model) { - return GestureDetector( - onTap: () { - model.addProductToCart(product.id); - // TODO(redbrogdon): Add Snackbar - }, - child: child, - ); - }, - child: Stack( - children: [ - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - AspectRatio( - aspectRatio: imageAspectRatio, - child: imageWidget, - ), - SizedBox( - height: kTextBoxHeight * MediaQuery.of(context).textScaleFactor, - width: 121.0, - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - product == null ? '' : product.name, - style: theme.textTheme.button, - softWrap: false, - overflow: TextOverflow.ellipsis, - maxLines: 1, - ), - const SizedBox(height: 4.0), - Text( - product == null ? '' : formatter.format(product.price), - style: theme.textTheme.caption, - ), - ], - ), - ), - ], - ), - const Padding( - padding: EdgeInsets.all(16.0), - child: Icon(Icons.add_shopping_cart), - ), - ], - ), - ); - } -} diff --git a/examples/flutter_gallery/lib/demo/shrine/supplemental/product_columns.dart b/examples/flutter_gallery/lib/demo/shrine/supplemental/product_columns.dart deleted file mode 100644 index 6889716146c..00000000000 --- a/examples/flutter_gallery/lib/demo/shrine/supplemental/product_columns.dart +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2018-present the Flutter authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; - -import 'package:flutter_gallery/demo/shrine/model/product.dart'; -import 'package:flutter_gallery/demo/shrine/supplemental/product_card.dart'; - -class TwoProductCardColumn extends StatelessWidget { - const TwoProductCardColumn({ - @required this.bottom, - this.top, - }) : assert(bottom != null); - - final Product bottom, top; - - @override - Widget build(BuildContext context) { - return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) { - const double spacerHeight = 44.0; - - final double heightOfCards = (constraints.biggest.height - spacerHeight) / 2.0; - final double heightOfImages = heightOfCards - ProductCard.kTextBoxHeight; - final double imageAspectRatio = (heightOfImages >= 0.0 && constraints.biggest.width > heightOfImages) - ? constraints.biggest.width / heightOfImages - : 33 / 49; - - return ListView( - children: [ - Padding( - padding: const EdgeInsetsDirectional.only(start: 28.0), - child: top != null - ? ProductCard( - imageAspectRatio: imageAspectRatio, - product: top, - ) - : SizedBox( - height: heightOfCards > 0 ? heightOfCards : spacerHeight, - ), - ), - const SizedBox(height: spacerHeight), - Padding( - padding: const EdgeInsetsDirectional.only(end: 28.0), - child: ProductCard( - imageAspectRatio: imageAspectRatio, - product: bottom, - ), - ), - ], - ); - }); - } -} - -class OneProductCardColumn extends StatelessWidget { - const OneProductCardColumn({this.product}); - - final Product product; - - @override - Widget build(BuildContext context) { - return ListView( - reverse: true, - children: [ - const SizedBox( - height: 40.0, - ), - ProductCard( - product: product, - ), - ], - ); - } -} diff --git a/examples/flutter_gallery/lib/demo/shrine_demo.dart b/examples/flutter_gallery/lib/demo/shrine_demo.dart index 6c58ecdcd1a..24cd2d82066 100644 --- a/examples/flutter_gallery/lib/demo/shrine_demo.dart +++ b/examples/flutter_gallery/lib/demo/shrine_demo.dart @@ -3,13 +3,40 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; -import 'package:flutter_gallery/demo/shrine/app.dart'; + +import 'shrine/shrine_home.dart' show ShrineHome; +import 'shrine/shrine_theme.dart' show ShrineTheme; + +// This code would ordinarily be part of the MaterialApp's home. It's being +// used by the ShrineDemo and by each route pushed from there because this +// isn't a standalone app with its own main() and MaterialApp. +Widget buildShrine(BuildContext context, Widget child) { + return Theme( + data: ThemeData( + primarySwatch: Colors.grey, + iconTheme: const IconThemeData(color: Color(0xFF707070)), + platform: Theme.of(context).platform, + ), + child: ShrineTheme(child: child) + ); +} + +// In a standalone version of this app, MaterialPageRoute could be used directly. +class ShrinePageRoute extends MaterialPageRoute { + ShrinePageRoute({ + WidgetBuilder builder, + RouteSettings settings, + }) : super(builder: builder, settings: settings); + + @override + Widget buildPage(BuildContext context, Animation animation, Animation secondaryAnimation) { + return buildShrine(context, super.buildPage(context, animation, secondaryAnimation)); + } +} class ShrineDemo extends StatelessWidget { - const ShrineDemo({ Key key }) : super(key: key); - static const String routeName = '/shrine'; // Used by the Gallery app. @override - Widget build(BuildContext context) => ShrineApp(); + Widget build(BuildContext context) => buildShrine(context, ShrineHome()); } diff --git a/examples/flutter_gallery/lib/gallery/app.dart b/examples/flutter_gallery/lib/gallery/app.dart index e382823cfb5..ec88822d376 100644 --- a/examples/flutter_gallery/lib/gallery/app.dart +++ b/examples/flutter_gallery/lib/gallery/app.dart @@ -7,8 +7,6 @@ import 'dart:async'; import 'package:flutter/foundation.dart' show defaultTargetPlatform; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart' show timeDilation; -import 'package:flutter_gallery/demo/shrine/model/app_state_model.dart'; -import 'package:scoped_model/scoped_model.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -44,7 +42,6 @@ class GalleryApp extends StatefulWidget { class _GalleryAppState extends State { GalleryOptions _options; Timer _timeDilationTimer; - AppStateModel model; Map _buildRoutes() { // For a different example of how to set up an application routing table @@ -66,7 +63,6 @@ class _GalleryAppState extends State { timeDilation: timeDilation, platform: defaultTargetPlatform, ); - model = AppStateModel()..loadProducts(); } @override @@ -129,24 +125,22 @@ class _GalleryAppState extends State { child: home, ); } - return ScopedModel( - model: model, - child: MaterialApp( - theme: _options.theme.data.copyWith(platform: _options.platform), - title: 'Flutter Gallery', - color: Colors.grey, - showPerformanceOverlay: _options.showPerformanceOverlay, - checkerboardOffscreenLayers: _options.showOffscreenLayersCheckerboard, - checkerboardRasterCacheImages: _options.showRasterCacheImagesCheckerboard, - routes: _buildRoutes(), - builder: (BuildContext context, Widget child) { - return Directionality( - textDirection: _options.textDirection, - child: _applyTextScaleFactor(child), - ); - }, - home: home, - ), + + return MaterialApp( + theme: _options.theme.data.copyWith(platform: _options.platform), + title: 'Flutter Gallery', + color: Colors.grey, + showPerformanceOverlay: _options.showPerformanceOverlay, + checkerboardOffscreenLayers: _options.showOffscreenLayersCheckerboard, + checkerboardRasterCacheImages: _options.showRasterCacheImagesCheckerboard, + routes: _buildRoutes(), + builder: (BuildContext context, Widget child) { + return Directionality( + textDirection: _options.textDirection, + child: _applyTextScaleFactor(child), + ); + }, + home: home, ); } } diff --git a/examples/flutter_gallery/lib/gallery/demos.dart b/examples/flutter_gallery/lib/gallery/demos.dart index 3f7a8911967..0b18552e6b9 100644 --- a/examples/flutter_gallery/lib/gallery/demos.dart +++ b/examples/flutter_gallery/lib/gallery/demos.dart @@ -93,7 +93,7 @@ List _buildGalleryDemos() { icon: GalleryIcons.shrine, category: _kDemos, routeName: ShrineDemo.routeName, - buildRoute: (BuildContext context) => const ShrineDemo(), + buildRoute: (BuildContext context) => ShrineDemo(), ), GalleryDemo( title: 'Contact profile', diff --git a/examples/flutter_gallery/pubspec.yaml b/examples/flutter_gallery/pubspec.yaml index 2c28f5e7fa4..c92998af0a0 100644 --- a/examples/flutter_gallery/pubspec.yaml +++ b/examples/flutter_gallery/pubspec.yaml @@ -8,15 +8,13 @@ dependencies: flutter: sdk: flutter collection: 1.14.11 - device_info: 0.3.0 + device_info: 0.2.1 intl: 0.15.7 connectivity: 0.3.2 string_scanner: 1.0.4 url_launcher: 4.0.1 cupertino_icons: 0.1.2 video_player: 0.7.2 - scoped_model: 0.3.0 - shrine_images: 1.1.1 # Also update dev/benchmarks/complex_layout/pubspec.yaml flutter_gallery_assets: 0.1.6 @@ -37,7 +35,7 @@ dev_dependencies: sdk: flutter test: 1.5.1 - analyzer: 0.33.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + analyzer: 0.33.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -45,7 +43,7 @@ dev_dependencies: crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" file: 5.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - front_end: 0.1.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + front_end: 0.1.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -54,7 +52,7 @@ dev_dependencies: io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - kernel: 0.3.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + kernel: 0.3.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -151,47 +149,6 @@ flutter: - packages/flutter_gallery_assets/people/square/sandra.png - packages/flutter_gallery_assets/people/square/stella.png - packages/flutter_gallery_assets/people/square/trevor.png - - packages/shrine_images/diamond.png - - packages/shrine_images/slanted_menu.png - - packages/shrine_images/0-0.jpg - - packages/shrine_images/1-0.jpg - - packages/shrine_images/2-0.jpg - - packages/shrine_images/3-0.jpg - - packages/shrine_images/4-0.jpg - - packages/shrine_images/5-0.jpg - - packages/shrine_images/6-0.jpg - - packages/shrine_images/7-0.jpg - - packages/shrine_images/8-0.jpg - - packages/shrine_images/9-0.jpg - - packages/shrine_images/10-0.jpg - - packages/shrine_images/11-0.jpg - - packages/shrine_images/12-0.jpg - - packages/shrine_images/13-0.jpg - - packages/shrine_images/14-0.jpg - - packages/shrine_images/15-0.jpg - - packages/shrine_images/16-0.jpg - - packages/shrine_images/17-0.jpg - - packages/shrine_images/18-0.jpg - - packages/shrine_images/19-0.jpg - - packages/shrine_images/20-0.jpg - - packages/shrine_images/21-0.jpg - - packages/shrine_images/22-0.jpg - - packages/shrine_images/23-0.jpg - - packages/shrine_images/24-0.jpg - - packages/shrine_images/25-0.jpg - - packages/shrine_images/26-0.jpg - - packages/shrine_images/27-0.jpg - - packages/shrine_images/28-0.jpg - - packages/shrine_images/29-0.jpg - - packages/shrine_images/30-0.jpg - - packages/shrine_images/31-0.jpg - - packages/shrine_images/32-0.jpg - - packages/shrine_images/33-0.jpg - - packages/shrine_images/34-0.jpg - - packages/shrine_images/35-0.jpg - - packages/shrine_images/36-0.jpg - - packages/shrine_images/37-0.jpg - fonts: - family: Raleway fonts: @@ -241,4 +198,4 @@ flutter: - asset: packages/flutter_gallery_assets/fonts/private/googlesans/GoogleSansDisplay-Regular.ttf weight: 400 -# PUBSPEC CHECKSUM: bd43 +# PUBSPEC CHECKSUM: ccf6 diff --git a/examples/platform_channel/pubspec.yaml b/examples/platform_channel/pubspec.yaml index 3d1e7762d6f..7ff5adf96d5 100644 --- a/examples/platform_channel/pubspec.yaml +++ b/examples/platform_channel/pubspec.yaml @@ -20,7 +20,7 @@ dev_dependencies: sdk: flutter test: 1.5.1 - analyzer: 0.33.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + analyzer: 0.33.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -29,7 +29,7 @@ dev_dependencies: crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" file: 5.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - front_end: 0.1.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + front_end: 0.1.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -39,7 +39,7 @@ dev_dependencies: io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - kernel: 0.3.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + kernel: 0.3.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -74,4 +74,4 @@ dev_dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: c324 +# PUBSPEC CHECKSUM: d4c2 diff --git a/examples/stocks/pubspec.yaml b/examples/stocks/pubspec.yaml index 68bcd70c2db..34e32b58ec0 100644 --- a/examples/stocks/pubspec.yaml +++ b/examples/stocks/pubspec.yaml @@ -14,7 +14,7 @@ dependencies: http: 0.12.0 isolate: 2.0.2 - analyzer: 0.33.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + analyzer: 0.33.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" charcode: 1.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -23,11 +23,11 @@ dependencies: crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" dart_style: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - front_end: 0.1.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + front_end: 0.1.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - kernel: 0.3.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + kernel: 0.3.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -64,4 +64,4 @@ dev_dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: 5d4d +# PUBSPEC CHECKSUM: ceeb diff --git a/packages/flutter/lib/src/animation/tween_sequence.dart b/packages/flutter/lib/src/animation/tween_sequence.dart index 2d7b48fe6ea..490526fbd2e 100644 --- a/packages/flutter/lib/src/animation/tween_sequence.dart +++ b/packages/flutter/lib/src/animation/tween_sequence.dart @@ -82,9 +82,6 @@ class TweenSequence extends Animatable { assert(false, 'TweenSequence.evaluate() could not find a interval for $t'); return null; } - - @override - String toString() => 'TweenSequence(${_items.length} items)'; } /// A simple holder for one element of a [TweenSequence]. diff --git a/packages/flutter/lib/src/material/text_field.dart b/packages/flutter/lib/src/material/text_field.dart index 70fd567bb50..1a50ab05ebb 100644 --- a/packages/flutter/lib/src/material/text_field.dart +++ b/packages/flutter/lib/src/material/text_field.dart @@ -127,7 +127,6 @@ class TextField extends StatefulWidget { this.keyboardAppearance, this.scrollPadding = const EdgeInsets.all(20.0), this.enableInteractiveSelection = true, - this.onTap, }) : assert(textAlign != null), assert(autofocus != null), assert(obscureText != null), @@ -145,44 +144,9 @@ class TextField extends StatefulWidget { /// If null, this widget will create its own [TextEditingController]. final TextEditingController controller; - /// Defines the keyboard focus for this widget. - /// - /// The [focusNode] is a long-lived object that's typically managed by a - /// [StatefulWidget] parent. See [FocusNode] for more information. - /// - /// To give the keyboard focus to this widget provide a [focusNode] and then - /// use the current [FocusScope] to request the focus: - /// - /// ```dart - /// FocusScope.of(context).requestFocus(myFocusNode); - /// ``` - /// - /// This happens automatically when the widget is tapped. - /// - /// To be notified when the widget gains or loses the focus, add a listener - /// to the [focusNode]: - /// - /// ```dart - /// focusNode.addListener(() { print(myFocusNode.hasFocus); }); - /// ``` + /// Controls whether this widget has keyboard focus. /// /// If null, this widget will create its own [FocusNode]. - /// - /// ## Keyboard - /// - /// Requesting the focus will typically cause the the keyboard to be shown - /// if it's not showing already. - /// - /// On Android, the user can hide the keyboard - withouth changing the focus - - /// with the system back button. They can restore the keyboard's visibility - /// by tapping on a text field. The user might hide the keyboard and - /// switch to a physical keyboard, or they might just need to get it - /// out of the way for a moment, to expose something it's - /// obscuring. In this case requesting the focus again will not - /// cause the focus to change, and will not make the keyboard visible. - /// - /// This widget builds an [EditableText] and will ensure that the keyboard is - /// showing when it is tapped by calling [EditableTextState.requestKeyboard()]. final FocusNode focusNode; /// The decoration to show around the text field. @@ -334,26 +298,6 @@ class TextField extends StatefulWidget { /// {@macro flutter.widgets.editableText.enableInteractiveSelection} final bool enableInteractiveSelection; - /// Called when the user taps on this textfield. - /// - /// The textfield builds a [GestureDetector] to handle input events like tap, - /// to trigger focus requests, to move the caret, adjust the selection, etc. - /// Handling some of those events by wrapping the textfield with a competing - /// GestureDetector is problematic. - /// - /// To unconditionally handle taps, without interfering with the textfield's - /// internal gesture detector, provide this callback. - /// - /// If the textfield is created with [enabled] false, taps will not be - /// recognized. - /// - /// To be notified when the textfield gains or loses the focus, provide a - /// [focusNode] and add a listener to that. - /// - /// To listen to arbitrary pointer events without competing with the - /// textfield's internal gesture detector, use a [Listener]. - final GestureTapCallback onTap; - @override _TextFieldState createState() => _TextFieldState(); @@ -371,7 +315,6 @@ class TextField extends StatefulWidget { properties.add(IntProperty('maxLines', maxLines, defaultValue: 1)); properties.add(IntProperty('maxLength', maxLength, defaultValue: null)); properties.add(FlagProperty('maxLengthEnforced', value: maxLengthEnforced, ifTrue: 'max length enforced')); - properties.add(DiagnosticsProperty('onTap', onTap, defaultValue: false)); } } @@ -510,8 +453,6 @@ class _TextFieldState extends State with AutomaticKeepAliveClientMixi _renderEditable.handleTap(); _requestKeyboard(); _confirmCurrentSplash(); - if (widget.onTap != null) - widget.onTap(); } void _handleTapCancel() { diff --git a/packages/flutter_tools/pubspec.yaml b/packages/flutter_tools/pubspec.yaml index 6ddae11a931..5f89d0f18ea 100644 --- a/packages/flutter_tools/pubspec.yaml +++ b/packages/flutter_tools/pubspec.yaml @@ -9,7 +9,7 @@ environment: dependencies: # To update these, use "flutter update-packages --force-upgrade". - analyzer: 0.33.3+2 + analyzer: 0.33.3 archive: 2.0.4 args: 1.5.1 cli_util: 0.1.3+2 @@ -51,12 +51,12 @@ dependencies: convert: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" dart2_constant: 1.0.2+dart2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - front_end: 0.1.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + front_end: 0.1.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - kernel: 0.3.6+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + kernel: 0.3.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" package_resolver: 1.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -94,4 +94,4 @@ dartdoc: # Exclude this package from the hosted API docs. nodoc: true -# PUBSPEC CHECKSUM: 1cc9 +# PUBSPEC CHECKSUM: 1368