1
0
mirror of https://github.com/flutter/samples.git synced 2025-11-10 06:48:26 +00:00

Fix sample index deployment action (#862)

* Update sample index dependencies

* Update to tuneup 0.3.8, update dependencies

* Upgrade to null safety, lock sass version

* fix analyzer warnings

* Fix unit tests

* Fix issues from upgrading to null safety
This commit is contained in:
John Ryan
2021-08-02 15:41:18 -07:00
committed by GitHub
parent 699cc3a8c5
commit 7de8fafcee
17 changed files with 153 additions and 102 deletions

View File

@@ -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: <String, dynamic>{});
@@ -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',
);
}

View File

@@ -15,8 +15,10 @@ Future<List<Sample>> 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<dynamic, dynamic>);
return index.samples..addAll(cookbookIndex.samples);

View File

@@ -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<Element> 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');
}
}

View File

@@ -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,
});

View File

@@ -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<dynamic>)
.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<dynamic>)
.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<dynamic>).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<dynamic>).map((e) => e as String).toList()),
tags: $checkedConvert(json, 'tags',
(v) => (v as List<dynamic>).map((e) => e as String).toList()),
platforms: $checkedConvert(json, 'platforms',
(v) => (v as List)?.map((e) => e as String)?.toList()),
(v) => (v as List<dynamic>).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<dynamic>)
.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;
});

View File

@@ -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

View File

@@ -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<String, String> 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();

View File

@@ -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(
'''<button class="mdc-button mdc-button--outlined" onclick="window.location.href = '${sample.web}';"><span class="mdc-button__ripple"></span> Launch App</button>''');
}

View File

@@ -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';