diff --git a/navigation_and_routing/pubspec.lock b/navigation_and_routing/pubspec.lock index 7296d7a5a..e4c6e6c34 100644 --- a/navigation_and_routing/pubspec.lock +++ b/navigation_and_routing/pubspec.lock @@ -28,7 +28,7 @@ packages: name: analyzer url: "https://pub.dartlang.org" source: hosted - version: "1.7.1" + version: "1.7.2" args: dependency: transitive description: @@ -42,7 +42,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.6.1" + version: "2.7.0" boolean_selector: dependency: transitive description: @@ -63,7 +63,7 @@ packages: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.1" cli_util: dependency: transitive description: @@ -149,6 +149,13 @@ packages: description: flutter source: sdk version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" glob: dependency: transitive description: @@ -211,7 +218,7 @@ packages: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.7.0" mime: dependency: transitive description: @@ -370,21 +377,21 @@ packages: name: test url: "https://pub.dartlang.org" source: hosted - version: "1.16.8" + version: "1.17.9" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.3.0" + version: "0.4.1" test_core: dependency: transitive description: name: test_core url: "https://pub.dartlang.org" source: hosted - version: "0.3.19" + version: "0.3.29" typed_data: dependency: transitive description: diff --git a/web/_tool/pubspec.lock b/web/_tool/pubspec.lock index 1789ea7a9..d11b0dce2 100644 --- a/web/_tool/pubspec.lock +++ b/web/_tool/pubspec.lock @@ -7,14 +7,14 @@ packages: name: args url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.2.0" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.1" lints: dependency: "direct dev" description: @@ -35,7 +35,7 @@ packages: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.4.0" + version: "1.7.0" path: dependency: "direct main" description: diff --git a/web/samples_index/lib/cookbook.dart b/web/samples_index/lib/cookbook.dart index c42c1dff1..94a6e12c3 100644 --- a/web/samples_index/lib/cookbook.dart +++ b/web/samples_index/lib/cookbook.dart @@ -12,7 +12,7 @@ import 'package:html/parser.dart' show parse; import 'package:path/path.dart' as path; class CookbookScraper { - WebDriver _driver; + late WebDriver _driver; Future init() async { _driver = await createDriver(desired: {}); @@ -36,7 +36,12 @@ class CookbookScraper { await _driver.get(Uri.parse(url)); var pageContent = await _driver.pageSource; var page = parse(pageContent); - var name = page.querySelector('main>.container>header>h1').text; + var search = 'main>.container>header>h1'; + var h1 = page.querySelector(search); + if (h1 == null) { + throw ('Could not find match for $search on page $url'); + } + var name = h1.text; var description = page.querySelectorAll('main>.container>p').first.text; var urlSegments = Uri.parse(url).pathSegments; @@ -50,6 +55,7 @@ class CookbookScraper { screenshots: [Screenshot(screenshotPath(url), 'Cookbook article')], tags: ['cookbook', category], source: url, + difficulty: 'advanced', ); } diff --git a/web/samples_index/lib/samples_index.dart b/web/samples_index/lib/samples_index.dart index 6fd6be892..765006e68 100644 --- a/web/samples_index/lib/samples_index.dart +++ b/web/samples_index/lib/samples_index.dart @@ -15,8 +15,10 @@ Future> getSamples() async { var cookbookFile = File('lib/src/cookbook.json'); var contents = await yamlFile.readAsString(); var cookbookContents = await cookbookFile.readAsString(); - var index = checkedYamlDecode(contents, (m) => Index.fromJson(m), + var index = checkedYamlDecode( + contents, (m) => m != null ? Index.fromJson(m) : null, sourceUrl: yamlFile.uri); + if (index == null) throw('unable to get load from ${yamlFile.uri}'); var cookbookIndex = Index.fromJson(json.decode(cookbookContents) as Map); return index.samples..addAll(cookbookIndex.samples); diff --git a/web/samples_index/lib/src/carousel.dart b/web/samples_index/lib/src/carousel.dart index cb94a4729..b617e983f 100644 --- a/web/samples_index/lib/src/carousel.dart +++ b/web/samples_index/lib/src/carousel.dart @@ -7,14 +7,15 @@ import 'dart:html'; class Carousel { final bool withArrowKeyControl; - final Element container = querySelector('.slider-container'); + final Element container = querySelector('.slider-container')!; final List slides = querySelectorAll('.slider-single'); - int currentSlideIndex, lastSlideIndex; + late int currentSlideIndex; + late int lastSlideIndex; - Element prevSlide, currentSlide, nextSlide; + late Element prevSlide, currentSlide, nextSlide; - num x0; + late num x0; bool touched = false; Carousel.init({this.withArrowKeyControl = false}) { @@ -90,13 +91,13 @@ class Carousel { } void _touchStartListener(TouchEvent e) { - x0 = e.changedTouches.first.client.x; + x0 = e.changedTouches!.first.client.x; touched = true; } void _touchEndListener(TouchEvent e) { if (touched) { - int dx = (e.changedTouches.first.client.x - x0) as int; + int dx = (e.changedTouches!.first.client.x - x0) as int; // dx==0 case is ignored if (dx > 0 && currentSlideIndex > 0) { @@ -115,7 +116,7 @@ class Carousel { void _updateBullets() { final bullets = - querySelector('.bullet-container').querySelectorAll('.bullet'); + querySelector('.bullet-container')!.querySelectorAll('.bullet'); for (var i = 0; i < bullets.length; i++) { bullets[i].classes.remove('active'); if (i == currentSlideIndex) { @@ -132,18 +133,18 @@ class Carousel { if (currentSlideIndex == slides.length - 1) { slides[0].classes.add('hidden'); slides[slides.length - 1].classes.remove('hidden'); - prevArrow.classes.remove('hidden'); - nextArrow.classes.add('hidden'); + prevArrow!.classes.remove('hidden'); + nextArrow!.classes.add('hidden'); } else if (currentSlideIndex == 0) { slides[slides.length - 1].classes.add('hidden'); slides[0].classes.remove('hidden'); - prevArrow.classes.add('hidden'); - nextArrow.classes.remove('hidden'); + prevArrow!.classes.add('hidden'); + nextArrow!.classes.remove('hidden'); } else { slides[slides.length - 1].classes.remove('hidden'); slides[0].classes.remove('hidden'); - prevArrow.classes.remove('hidden'); - nextArrow.classes.remove('hidden'); + prevArrow!.classes.remove('hidden'); + nextArrow!.classes.remove('hidden'); } } diff --git a/web/samples_index/lib/src/data.dart b/web/samples_index/lib/src/data.dart index ed843c590..b5e9008ff 100644 --- a/web/samples_index/lib/src/data.dart +++ b/web/samples_index/lib/src/data.dart @@ -34,7 +34,7 @@ class Sample { final String name; /// The author of the sample. Typically "Flutter" - final String author; + final String? author; /// Screenshots of the sample or cookbook article. At least 1 screenshot is /// required. @@ -44,14 +44,14 @@ class Sample { final String source; /// A link to this sample running in the browser. - final String web; + final String? web; /// 3-5 sentences describing the sample. final String description; /// The difficulty level. Values are either 'beginner', 'intermediate', or /// 'advanced'. - final String difficulty; + final String? difficulty; /// List of widgets or Flutter APIs used by the sample. e.g. "AnimatedBuilder" /// or "ChangeNotifier". @@ -76,26 +76,26 @@ class Sample { final String type; /// The date this sample was created. - final DateTime date; + final DateTime? date; /// The Flutter channel this sample runs on. Either 'stable', 'dev' or /// 'master'. - final String channel; + final String? channel; Sample({ - this.name, - this.author, - this.screenshots, - this.source, + required this.name, + this.author = 'Flutter', + required this.screenshots, + required this.source, this.web, - this.description, - this.difficulty, + required this.description, + this.difficulty = 'beginner', this.widgets = const [], this.packages = const [], this.tags = const [], this.platforms = const [], this.links = const [], - this.type, + required this.type, this.date, this.channel, }); diff --git a/web/samples_index/lib/src/data.g.dart b/web/samples_index/lib/src/data.g.dart index 465cbce68..96508749c 100644 --- a/web/samples_index/lib/src/data.g.dart +++ b/web/samples_index/lib/src/data.g.dart @@ -12,9 +12,9 @@ Index _$IndexFromJson(Map json) { $checkedConvert( json, 'samples', - (v) => (v as List) - ?.map((e) => e == null ? null : Sample.fromJson(e as Map)) - ?.toList()), + (v) => (v as List) + .map((e) => Sample.fromJson(e as Map)) + .toList()), ); return val; }); @@ -28,35 +28,35 @@ Sample _$SampleFromJson(Map json) { return $checkedNew('Sample', json, () { final val = Sample( name: $checkedConvert(json, 'name', (v) => v as String), - author: $checkedConvert(json, 'author', (v) => v as String), + author: $checkedConvert(json, 'author', (v) => v as String?), screenshots: $checkedConvert( json, 'screenshots', - (v) => (v as List) - ?.map((e) => e == null ? null : Screenshot.fromJson(e as Map)) - ?.toList()), + (v) => (v as List) + .map((e) => Screenshot.fromJson(e as Map)) + .toList()), source: $checkedConvert(json, 'source', (v) => v as String), - web: $checkedConvert(json, 'web', (v) => v as String), + web: $checkedConvert(json, 'web', (v) => v as String?), description: $checkedConvert(json, 'description', (v) => v as String), - difficulty: $checkedConvert(json, 'difficulty', (v) => v as String), + difficulty: $checkedConvert(json, 'difficulty', (v) => v as String?), widgets: $checkedConvert(json, 'widgets', - (v) => (v as List)?.map((e) => e as String)?.toList()), + (v) => (v as List).map((e) => e as String).toList()), packages: $checkedConvert(json, 'packages', - (v) => (v as List)?.map((e) => e as String)?.toList()), - tags: $checkedConvert( - json, 'tags', (v) => (v as List)?.map((e) => e as String)?.toList()), + (v) => (v as List).map((e) => e as String).toList()), + tags: $checkedConvert(json, 'tags', + (v) => (v as List).map((e) => e as String).toList()), platforms: $checkedConvert(json, 'platforms', - (v) => (v as List)?.map((e) => e as String)?.toList()), + (v) => (v as List).map((e) => e as String).toList()), links: $checkedConvert( json, 'links', - (v) => (v as List) - ?.map((e) => e == null ? null : Link.fromJson(e as Map)) - ?.toList()), + (v) => (v as List) + .map((e) => Link.fromJson(e as Map)) + .toList()), type: $checkedConvert(json, 'type', (v) => v as String), date: $checkedConvert( json, 'date', (v) => v == null ? null : DateTime.parse(v as String)), - channel: $checkedConvert(json, 'channel', (v) => v as String), + channel: $checkedConvert(json, 'channel', (v) => v as String?), ); return val; }); diff --git a/web/samples_index/lib/src/samples.yaml b/web/samples_index/lib/src/samples.yaml index 481077dcf..fc20e56b0 100644 --- a/web/samples_index/lib/src/samples.yaml +++ b/web/samples_index/lib/src/samples.yaml @@ -83,6 +83,7 @@ samples: - scoped_model tags: ['intermediate', 'sample', 'gallery', 'material', 'design', 'vignettes'] platforms: ['web', 'ios', 'android'] + links: [] type: demo - name: Add to App @@ -105,6 +106,7 @@ samples: - provider tags: ['advanced', 'sample', 'add-to-app', 'android', 'ios', 'native', 'embedding'] platforms: ['ios', 'android'] + links: [] type: sample - name: Animations @@ -133,6 +135,7 @@ samples: - flutter/material tags: ['intermediate', 'sample', 'animation'] platforms: ['ios', 'android', 'web'] + links: [] type: sample web: web/animations @@ -157,6 +160,7 @@ samples: - google_maps_webservice tags: ['intermediate', 'sample', 'firebase', 'maps'] platforms: ['ios', 'android'] + links: [] type: sample - name: Isolate Example @@ -181,6 +185,7 @@ samples: - dart:math tags: ['intermediate', 'sample', 'isolates', 'concurrency'] platforms: ['ios', 'android'] + links: [] type: sample - name: jsonexample @@ -209,6 +214,7 @@ samples: - built_value_generator tags: ['beginner', 'sample'] platforms: ['ios', 'android'] + links: [] type: sample - name: Place Tracker @@ -235,6 +241,7 @@ samples: - google_maps_flutter tags: ['intermediate', 'sample', 'json', 'serialization'] platforms: ['android'] + links: [] type: sample - name: Platform Design @@ -266,6 +273,7 @@ samples: - flutter/cupertino tags: ['advanced', 'sample', 'ios'] platforms: ['ios', 'android'] + links: [] type: sample - name: Platform View Swift @@ -287,6 +295,7 @@ samples: - flutter/services tags: ['advanced', 'sample', 'ios'] platforms: ['ios'] + links: [] type: sample - name: Infinite List @@ -311,6 +320,7 @@ samples: - meta tags: ['sample', 'material', 'design', 'android', 'ios'] platforms: ['ios', 'android'] + links: [] type: sample - name: IOS App Clip @@ -331,6 +341,7 @@ samples: - device_info tags: ['sample', 'Device Info', 'ios'] platforms: ['ios'] + links: [] type: sample - name: Testing App @@ -353,6 +364,7 @@ samples: - provider tags: ['sample', 'material', 'android', 'ios'] platforms: ['ios', 'android'] + links: [] type: sample - name: Provider Shopper @@ -376,6 +388,7 @@ samples: - provider tags: ['intermediate', 'sample', 'provider'] platforms: ['ios', 'android', 'web'] + links: [] type: sample web: web/provider_shopper @@ -402,6 +415,7 @@ samples: - firebase tags: ['intermediate', 'sample', 'firebase'] platforms: ['ios', 'android', 'web'] + links: [] type: sample web: web/web_dashboard @@ -423,6 +437,7 @@ samples: packages: [] tags: ['intermediate', 'sample', 'forms'] platforms: ['ios', 'android', 'web'] + links: [] type: sample web: web/form_app ################### @@ -433,6 +448,7 @@ samples: author: Flutter screenshots: - url: images/charts1.png + alt: Charts screenshot source: https://github.com/google/charts description: > A general-purpose charting library. @@ -440,6 +456,7 @@ samples: widgets: [] packages: [] platforms: ['ios', 'android', 'web'] + links: [] tags: ['demo', 'charts'] web: web/charts type: demo @@ -456,6 +473,7 @@ samples: widgets: [] packages: [] platforms: ['web'] + links: [] tags: ['demo', 'flutter create'] web: web/filipino_cuisine type: demo @@ -472,6 +490,7 @@ samples: widgets: [] packages: [] platforms: ['web'] + links: [] tags: ['demo', 'data', 'visualization'] web: web/github_dataviz type: demo @@ -488,6 +507,7 @@ samples: widgets: [] packages: [] platforms: ['web'] + links: [] tags: ['demo', 'animation'] web: web/particle_background type: demo @@ -504,6 +524,7 @@ samples: widgets: [] packages: [] platforms: ['web'] + links: [] tags: ['demo', 'game'] web: web/slide_puzzle type: demo @@ -520,6 +541,7 @@ samples: widgets: [] packages: [] platforms: ['web'] + links: [] tags: ['demo', 'animation'] web: https://z.flutter.gallery/#/dice type: demo diff --git a/web/samples_index/lib/src/search.dart b/web/samples_index/lib/src/search.dart index 3d2ad4fd7..24ebb55ac 100644 --- a/web/samples_index/lib/src/search.dart +++ b/web/samples_index/lib/src/search.dart @@ -3,7 +3,7 @@ // found in the LICENSE file bool matchesQuery(String query, String sampleAttributes) { - if (query == null || query.isEmpty) { + if (query.isEmpty) { return true; } var queryWords = query.split(' ')..removeWhere((s) => s.isEmpty); @@ -68,11 +68,13 @@ String searchQueryFromParams(Map params) { } if (params.containsKey('type')) { if (buf.isNotEmpty) buf.write(' '); - buf.write('type:' + params['type']); + var value = params['type']; + if (value != null) buf.write('type:' + value); } if (params.containsKey('platform')) { if (buf.isNotEmpty) buf.write(' '); - buf.write('platform:' + params['platform']); + var value = params['platform']; + if (value != null) buf.write('platform:' + value); } return buf.toString(); diff --git a/web/samples_index/lib/src/templates.dart b/web/samples_index/lib/src/templates.dart index b9ef3d257..15b139664 100644 --- a/web/samples_index/lib/src/templates.dart +++ b/web/samples_index/lib/src/templates.dart @@ -187,7 +187,7 @@ String _descriptionPage(Sample sample) => ''' String _descriptionButtons(Sample sample) { var buf = StringBuffer(); - if (sample?.web?.isNotEmpty == true) { + if (sample.web?.isNotEmpty == true) { buf.write( ''''''); } diff --git a/web/samples_index/lib/src/util.dart b/web/samples_index/lib/src/util.dart index a20d1e668..aaf0bfc20 100644 --- a/web/samples_index/lib/src/util.dart +++ b/web/samples_index/lib/src/util.dart @@ -23,7 +23,9 @@ String pascalCase(String input) { String _fixCase(String input, String separator) => input.replaceAllMapped(_upperCase, (match) { - var lower = match.group(0).toLowerCase(); + var group = match.group(0); + if (group == null) return input; + var lower = group.toLowerCase(); if (match.start > 0) { lower = '$separator$lower'; diff --git a/web/samples_index/pubspec.yaml b/web/samples_index/pubspec.yaml index 2185f65a2..fcb3e970e 100644 --- a/web/samples_index/pubspec.yaml +++ b/web/samples_index/pubspec.yaml @@ -4,23 +4,29 @@ homepage: https://github.com/flutter/samples_index author: Flutter Team version: 0.0.1 environment: - sdk: ">=2.5.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: - json_annotation: ^3.0.0 + json_annotation: ^4.0.1 path: ^1.6.0 - yaml: ^2.2.0 - mdc_web: ^0.5.0-pre + yaml: ^3.0.0 + mdc_web: ^0.6.0 sass_builder: ^2.1.0 - checked_yaml: ^1.0.0 - webdriver: ^2.1.0 - html: ^0.14.0 + checked_yaml: ^2.0.1 + webdriver: ^3.0.0 + html: ^0.15.0 dev_dependencies: - grinder: ^0.8.3 + grinder: ^0.9.0 flutter_lints: ^1.0.0 - test: ^1.6.0 - json_serializable: ^3.2.0 - build: ^1.2.0 - build_runner: ^1.7.0 - build_web_compilers: ^2.7.0 - tuneup: ^0.3.6 - image: ^2.1.0 + test: ^1.17.10 + json_serializable: ^4.0.2 + build: ^2.0.3 + build_runner: ^2.0.6 + build_web_compilers: ^3.0.0 + tuneup: ^0.3.8 + image: ^3.0.2 +# waiting for the next material-components-web release. +# Once released, it will need to be rolled into package:mdc_web. +# +# https://github.com/material-components/material-components-web/pull/7158 +dependency_overrides: + sass: 1.32.10 \ No newline at end of file diff --git a/web/samples_index/test/samples_index_test.dart b/web/samples_index/test/samples_index_test.dart index 2df5f26c2..55d2d5af2 100644 --- a/web/samples_index/test/samples_index_test.dart +++ b/web/samples_index/test/samples_index_test.dart @@ -16,15 +16,18 @@ void main() { var contents = await file.readAsString(); expect(contents, isNotEmpty); - var index = checkedYamlDecode(contents, (m) => Index.fromJson(m), + var index = checkedYamlDecode(contents, (m) => m != null ? Index.fromJson(m) : null, sourceUrl: file.uri); + if (index == null) { + throw('unable to load YAML from $file'); + } expect(index.samples, isNotEmpty); var sample = index.samples.first; expect(sample, isNotNull); expect(sample.name, 'Kittens'); expect(sample.screenshots, hasLength(2)); - expect(sample.source, 'http://github.com/johnpryan/kittens'); + expect(sample.source, 'https://github.com/johnpryan/kittens'); expect(sample.description, 'A sample kitten app'); expect(sample.difficulty, 'beginner'); expect(sample.widgets, hasLength(2)); @@ -36,7 +39,7 @@ void main() { expect(sample.platforms, hasLength(3)); expect(sample.links, hasLength(2)); expect(sample.links[1].text, 'author'); - expect(sample.links[1].href, 'http://jpryan.me'); + expect(sample.links[1].href, 'https://jpryan.me'); expect(sample.type, 'sample'); expect(sample.date, DateTime.parse('2019-12-15T02:59:43.1Z')); expect(sample.channel, 'stable'); @@ -49,8 +52,11 @@ void main() { var contents = await file.readAsString(); expect(contents, isNotEmpty); - var index = checkedYamlDecode(contents, (m) => Index.fromJson(m), + var index = checkedYamlDecode(contents, (m) => m != null ? Index.fromJson(m) : null, sourceUrl: file.uri); + if (index == null) { + throw('unable to load YAML from $file'); + } var sample = index.samples.first; expect( sample.searchAttributes.split(' '), diff --git a/web/samples_index/test/yaml/single.yaml b/web/samples_index/test/yaml/single.yaml index 3affccb27..f981a8ece 100644 --- a/web/samples_index/test/yaml/single.yaml +++ b/web/samples_index/test/yaml/single.yaml @@ -5,7 +5,7 @@ samples: alt: a kitten - url: https://placekitten.com/400/400 alt: another kitten - source: http://github.com/johnpryan/kittens + source: https://github.com/johnpryan/kittens description: A sample kitten app difficulty: beginner widgets: @@ -20,7 +20,7 @@ samples: - text: inspiration href: https://apps.apple.com/us/app/neko-atsume-kitty-collector/id923917775 - text: author - href: http://jpryan.me + href: https://jpryan.me type: sample # sample, app, or cookbook date: 2019-12-15T02:59:43.1Z channel: stable diff --git a/web/samples_index/tool/grind.dart b/web/samples_index/tool/grind.dart index 4456d0c5d..aa4e02cf5 100644 --- a/web/samples_index/tool/grind.dart +++ b/web/samples_index/tool/grind.dart @@ -104,12 +104,11 @@ Future _createThumbnails(Directory directory) async { continue; } - var file = entity as File; - var pathPrefix = path.dirname(file.path); + var pathPrefix = path.dirname(entity.path); var thumbnailFile = File(path.join(pathPrefix, filename + '_thumb.png')); - var img = image.decodeImage(await file.readAsBytes()); - var resized = image.copyResize(img, width: 640); + var img = image.decodeImage(await entity.readAsBytes()); + var resized = image.copyResize(img!, width: 640); filesToWrite.add(thumbnailFile.writeAsBytes(image.encodePng(resized))); } diff --git a/web/samples_index/web/description.dart b/web/samples_index/web/description.dart index cc623d816..f75861e8a 100644 --- a/web/samples_index/web/description.dart +++ b/web/samples_index/web/description.dart @@ -3,8 +3,6 @@ import 'dart:html'; import 'package:mdc_web/mdc_web.dart'; import 'package:samples_index/src/carousel.dart'; -InputElement searchInput; - void main() { querySelectorAll('.mdc-card__primary-action').forEach((el) => MDCRipple(el)); diff --git a/web/samples_index/web/main.dart b/web/samples_index/web/main.dart index 90ef493e1..05d4f7f45 100644 --- a/web/samples_index/web/main.dart +++ b/web/samples_index/web/main.dart @@ -4,8 +4,8 @@ import 'package:mdc_web/mdc_web.dart'; import 'package:samples_index/browser.dart'; /// The Material text input for searching -MDCTextField searchBar; -MDCChipSet chipSet; +late final MDCTextField searchBar; +late final MDCChipSet chipSet; /// The current set of query parameters that determine how the cards are /// filtered. e.g. {'search': 'kittens', 'platform': 'ios'} @@ -16,9 +16,9 @@ const platformKey = 'platform'; void main() { // Initialize Material components - MDCFloatingLabel(querySelector('.mdc-floating-label')); - searchBar = MDCTextField(querySelector('#search-bar')); - MDCRipple(querySelector('#clear-button')); + MDCFloatingLabel(querySelector('.mdc-floating-label')!); + searchBar = MDCTextField(querySelector('#search-bar')!); + MDCRipple(querySelector('#clear-button')!); // Listen for hash changes window.onHashChange.listen((_) { @@ -33,7 +33,7 @@ void main() { querySelectorAll('.mdc-card__primary-action').forEach((el) => MDCRipple(el) // Navigate to the description page when tapped ..listen('click', (e) { - window.location.href = el.attributes['href']; + window.location.href = el.attributes['href']!; })); // Filter cards on each keypress @@ -44,12 +44,12 @@ void main() { // Update the URL only when the user is done typing in the search bar searchBar.listen('change', (e) { - queryParams[searchKey] = searchBar.value; + queryParams[searchKey] = searchBar.value!; updateHash(); }); // Update the hash, cards, and text input when the clear button is pressed - querySelector('#clear-button').onClick.listen((e) { + querySelector('#clear-button')!.onClick.listen((e) { queryParams.remove('search'); updateHash(); setSearchBarText(); @@ -57,10 +57,10 @@ void main() { }); // Initialize chips - chipSet = MDCChipSet(querySelector('.mdc-chip-set')); + chipSet = MDCChipSet(querySelector('.mdc-chip-set')!); chipSet.listen('MDCChip:selection', (e) { // Get the query parameters for this chip - var selectedChipIndex = chipSet.chips.indexWhere((chip) => chip.selected); + var selectedChipIndex = chipSet.chips.indexWhere((chip) => chip.selected!); var chipParams = paramsForChip(selectedChipIndex); // Overwrite query parameters with new ones @@ -89,7 +89,7 @@ void setSearchBarText() { void setSelectedChips() { var type = queryParams.containsKey(typeKey) ? queryParams[typeKey] : ''; - if (type.isNotEmpty) { + if (type!.isNotEmpty) { if (type == 'sample') { chipSet.chips[1].selected = true; } @@ -101,7 +101,7 @@ void setSelectedChips() { // Apply the platform from the hash in the URL var platform = queryParams.containsKey(platformKey) ? queryParams[platformKey] : ''; - if (platform.isNotEmpty) { + if (platform!.isNotEmpty) { if (platform == 'web') { chipSet.chips[3].selected = true; } @@ -113,7 +113,7 @@ void setSelectedChips() { void handleSearch() { var search = searchBar.value; - queryParams[searchKey] = search; + queryParams[searchKey] = search!; filterCards(); } @@ -139,7 +139,7 @@ void filterCards() { var elements = querySelectorAll('[search-attrs]'); for (var element in elements) { var searchAttributes = element.attributes['search-attrs']; - if (matchesQuery(searchQuery, searchAttributes)) { + if (matchesQuery(searchQuery, searchAttributes!)) { element.hidden = false; } else { element.hidden = true;