Skip to content

Commit

Permalink
Merge branch 'null-safty'
Browse files Browse the repository at this point in the history
  • Loading branch information
X-Wei committed Jul 30, 2021
2 parents a8551ff + 4f967b3 commit a314729
Show file tree
Hide file tree
Showing 112 changed files with 817 additions and 687 deletions.
6 changes: 5 additions & 1 deletion analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ include: package:lint/analysis_options.yaml
analyzer:
exclude:
- build/**
- "lib/**/*.g.dart"
- "lib/**/*.freezed.dart"
enable-experiment:
- non-nullable

Expand All @@ -20,4 +22,6 @@ linter:
use_string_buffers: false
avoid_redundant_argument_values: false
prefer_const_constructors: false
avoid_dynamic_calls: false
avoid_dynamic_calls: false
directives_ordering: false
sort_pub_dependencies: false
7 changes: 1 addition & 6 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ android {

defaultConfig {
applicationId "io.github.x_wei.flutter_catalog"
minSdkVersion 16
minSdkVersion 21
targetSdkVersion 29
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
Expand Down Expand Up @@ -99,11 +99,6 @@ dependencies {
implementation 'com.google.firebase:firebase-analytics:17.5.0'
implementation 'com.google.firebase:firebase-auth:19.4.0'
implementation 'com.google.firebase:firebase-firestore:21.6.0'
// Cf. https://firebase.google.com/docs/ml-kit/android/read-barcodes.
implementation 'com.google.firebase:firebase-ml-vision:24.0.3'
implementation 'com.google.firebase:firebase-ml-vision-barcode-model:16.0.1'
implementation 'com.google.firebase:firebase-ml-vision-image-label-model:20.0.1'
implementation 'com.google.firebase:firebase-ml-vision-face-model:20.0.1'
}

apply plugin: 'com.google.gms.google-services'
4 changes: 2 additions & 2 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
</intent-filter>
</activity>
<meta-data
android:name="com.google.firebase.ml.vision.DEPENDENCIES"
android:value="ocr,label,barcode,face" />
android:name="com.google.mlkit.vision.DEPENDENCIES"
android:value="ocr,ica,barcode,face" />
<meta-data
android:name="flutterEmbedding"
android:value="2" />
Expand Down
2 changes: 2 additions & 0 deletions lib/generated_plugin_registrant.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import 'package:firebase_core_web/firebase_core_web.dart';
import 'package:firebase_storage_web/firebase_storage_web.dart';
import 'package:fluttertoast/fluttertoast_web.dart';
import 'package:google_sign_in_web/google_sign_in_web.dart';
import 'package:image_picker_for_web/image_picker_for_web.dart';
import 'package:shared_preferences_web/shared_preferences_web.dart';
import 'package:url_launcher_web/url_launcher_web.dart';
import 'package:video_player_web/video_player_web.dart';
Expand All @@ -27,6 +28,7 @@ void registerPlugins(Registrar registrar) {
FirebaseStorageWeb.registerWith(registrar);
FluttertoastWebPlugin.registerWith(registrar);
GoogleSignInPlugin.registerWith(registrar);
ImagePickerPlugin.registerWith(registrar);
SharedPreferencesPlugin.registerWith(registrar);
UrlLauncherPlugin.registerWith(registrar);
VideoPlayerPlugin.registerWith(registrar);
Expand Down
10 changes: 5 additions & 5 deletions lib/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import './my_app_settings.dart';
import './my_route.dart';

class MyHomePage extends StatefulWidget {
const MyHomePage({Key key}) : super(key: key);
const MyHomePage({Key? key}) : super(key: key);

@override
_MyHomePageState createState() => _MyHomePageState();
Expand Down Expand Up @@ -73,11 +73,11 @@ class _MyHomePageState extends State<MyHomePage> {
}

Widget _myRouteToListTile(MyRoute myRoute,
{Widget leading, IconData trialing = Icons.keyboard_arrow_right}) {
{Widget? leading, IconData trialing = Icons.keyboard_arrow_right}) {
final mySettings = context.watch<MyAppSettings>();
final routeTitleTextStyle = Theme.of(context)
.textTheme
.bodyText2
.bodyText2!
.copyWith(fontWeight: FontWeight.bold);
final leadingWidget =
leading ?? mySettings.starStatusOfRoute(myRoute.routeName);
Expand All @@ -90,8 +90,8 @@ class _MyHomePageState extends State<MyHomePage> {
)
: leadingWidget,
title: Text(myRoute.title, style: routeTitleTextStyle),
trailing: trialing == null ? null : Icon(trialing),
subtitle: myRoute.description == null ? null : Text(myRoute.description),
trailing: Icon(trialing),
subtitle: myRoute.description.isEmpty ? null : Text(myRoute.description),
onTap: () {
if (isNew) {
mySettings.markRouteKnown(myRoute.routeName);
Expand Down
25 changes: 13 additions & 12 deletions lib/my_app_routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ import 'routes/layouts_fractionally_sizedbox_ex.dart';
import 'routes/layouts_row_col_ex.dart';
import 'routes/layouts_stack_ex.dart';
import 'routes/layouts_wrap_ex.dart';
import 'routes/lists_wheel_scroll_view_ex.dart';
import 'routes/lists_datatable_ex.dart';
import 'routes/lists_expansion_tile_ex.dart';
import 'routes/lists_grid_list_ex.dart';
Expand All @@ -54,6 +53,7 @@ import 'routes/lists_listview_builder_ex.dart';
import 'routes/lists_reorderable_ex.dart';
import 'routes/lists_slidable_tile_ex.dart';
import 'routes/lists_swipe_to_dismiss_ex.dart';
import 'routes/lists_wheel_scroll_view_ex.dart';
import 'routes/multimedia_edge_detection_ex.dart';
import 'routes/multimedia_extended_image_ex.dart';
import 'routes/multimedia_image_picker_ex.dart';
Expand Down Expand Up @@ -133,7 +133,7 @@ const kAboutRoute = MyRoute(
// ]
class MyRouteGroup {
const MyRouteGroup(
{@required this.groupName, @required this.icon, @required this.routes});
{required this.groupName, required this.icon, required this.routes});
final String groupName;
final Widget icon;
final List<MyRoute> routes;
Expand Down Expand Up @@ -363,14 +363,15 @@ const kMyAppRoutesBasic = <MyRouteGroup>[
),
MyRoute(
sourceFilePath: 'lib/routes/lists_wheel_scroll_view_ex.dart',
child: ListWheelViewExample(),
child: ListWheelViewExample(),
title: 'List Wheel Scroll View',
description: 'fancy list view',
links: {
'Doc': 'https://api.flutter.dev/flutter/widgets/ListWheelScrollView-class.html',
'Youtube':'https://youtu.be/dUhmWAz4C7Y'
'Doc':
'https://api.flutter.dev/flutter/widgets/ListWheelScrollView-class.html',
'Youtube': 'https://youtu.be/dUhmWAz4C7Y'
},
),
),
MyRoute(
child: SlidableTileExample(),
sourceFilePath: 'lib/routes/lists_slidable_tile_ex.dart',
Expand Down Expand Up @@ -672,9 +673,7 @@ const kMyAppRoutesAdvanced = <MyRouteGroup>[
sourceFilePath: 'lib/routes/animation_animated_radial_menu_ex.dart',
title: 'Animated Radial Menu',
description: 'Easy add radial menu with high-quality animation',
links: {
'Pub package': 'https://pub.dev/packages/animated_radial_menu'
},
links: {'Pub package': 'https://pub.dev/packages/animated_radial_menu'},
),
MyRoute(
child: LottieExample(),
Expand Down Expand Up @@ -1058,12 +1057,14 @@ const kMyAppRoutesAdvanced = <MyRouteGroup>[
},
),
MyRoute(
child: FirebaseMLKitExample(),
child: GoogleMLKitExample(),
sourceFilePath: 'lib/routes/firebase_mlkit_ex.dart',
title: 'Firebase ML Kit',
title: 'Google ML Kit',
description: 'Image labelling, text OCR, barcode scan, face detection.',
links: {
'Doc': 'https://pub.dartlang.org/packages/firebase_ml_vision',
'pub.dev': 'https://pub.dev/packages/google_ml_kit',
'MLKit doc':
'https://developers.google.com/ml-kit/vision/text-recognition',
},
),
],
Expand Down
23 changes: 11 additions & 12 deletions lib/my_app_settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ class MyAppSettings extends ChangeNotifier {
}
}

bool get isDarkMode => _pref?.getBool(_kDarkModePreferenceKey) ?? false;
bool get isDarkMode => _pref.getBool(_kDarkModePreferenceKey) ?? false;

// ignore:avoid_positional_boolean_parameters
void setDarkMode(bool val) {
_pref?.setBool(_kDarkModePreferenceKey, val);
_pref.setBool(_kDarkModePreferenceKey, val);
notifyListeners();
}

/// The list of route names in search history.
List<String> get searchHistory =>
_pref?.getStringList(_kSearchHistoryPreferenceKey) ?? [];
_pref.getStringList(_kSearchHistoryPreferenceKey) ?? [];

void addSearchHistory(String routeName) {
List<String> history = this.searchHistory;
Expand All @@ -43,16 +43,16 @@ class MyAppSettings extends ChangeNotifier {
if (history.length >= 10) {
history = history.take(10).toList();
}
_pref?.setStringList(_kSearchHistoryPreferenceKey, history);
_pref.setStringList(_kSearchHistoryPreferenceKey, history);
}

List<String> get starredRoutenames =>
_pref?.getStringList(_kBookmarkedRoutesPreferenceKey) ?? [];
_pref.getStringList(_kBookmarkedRoutesPreferenceKey) ?? [];

List<MyRoute> get starredRoutes => [
for (String routename in this.starredRoutenames)
if (_kRoutenameToRouteMap[routename] != null)
_kRoutenameToRouteMap[routename]
_kRoutenameToRouteMap[routename]!
];

// Returns a widget showing the star status of one demo route.
Expand All @@ -67,8 +67,7 @@ class MyAppSettings extends ChangeNotifier {
);
}

bool isStarred(String routeName) =>
starredRoutenames.contains(routeName) ?? false;
bool isStarred(String routeName) => starredRoutenames.contains(routeName);

void toggleStarred(String routeName) {
final staredRoutes = this.starredRoutenames;
Expand All @@ -78,20 +77,20 @@ class MyAppSettings extends ChangeNotifier {
staredRoutes.add(routeName);
}
final dedupedStaredRoutes = Set<String>.from(staredRoutes).toList();
_pref?.setStringList(_kBookmarkedRoutesPreferenceKey, dedupedStaredRoutes);
_pref.setStringList(_kBookmarkedRoutesPreferenceKey, dedupedStaredRoutes);
notifyListeners();
}

// Used to decide if an example route is newly added. We will show a red dot
// for newly added routes.
static const _kKnownRoutesKey = 'KNOWN_ROUTES';
bool isNewRoute(String routeName) =>
!_pref.getStringList(_kKnownRoutesKey).contains(routeName);
!(_pref.getStringList(_kKnownRoutesKey)?.contains(routeName) ?? false);

void markRouteKnown(String routeName) {
if (isNewRoute(routeName)) {
final knowRoutes = _pref.getStringList(_kKnownRoutesKey)..add(routeName);
_pref.setStringList(_kKnownRoutesKey, knowRoutes);
final knowRoutes = _pref.getStringList(_kKnownRoutesKey)?..add(routeName);
_pref.setStringList(_kKnownRoutesKey, knowRoutes ?? []);
notifyListeners();
}
}
Expand Down
4 changes: 2 additions & 2 deletions lib/my_main_app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import './themes.dart';

class MyMainApp extends StatelessWidget {
final SharedPreferences sharedPref;
const MyMainApp(this.sharedPref, {Key key}) : super(key: key);
const MyMainApp(this.sharedPref, {Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
Expand All @@ -20,7 +20,7 @@ class MyMainApp extends StatelessWidget {
}

class _MyMaterialApp extends StatelessWidget {
const _MyMaterialApp({Key key}) : super(key: key);
const _MyMaterialApp({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
Expand Down
22 changes: 11 additions & 11 deletions lib/my_route.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,25 @@ class MyRoute extends StatelessWidget {
// Actual content of the example.
final Widget child;
// Title shown in the route's appbar. By default just returns routeName.
final String _title;
final String? _title;
// A short description of the route. If not null, will be shown as subtitle in
// the home page list tile.
final String description;
// Returns a set of links {title:link} that are relative to the route. Can put
// documention links or reference video/article links here.
final Map<String, String> links;
// Route name of a page.
final String _routeName;
// Route name of a page, if missing, use ${child.runtimeType}.
final String? _routeName;
final Iterable<PlatformType> supportedPlatforms;

const MyRoute({
Key key,
@required this.sourceFilePath,
@required this.child,
String title,
this.description,
this.links,
String routeName,
Key? key,
required this.sourceFilePath,
required this.child,
String? title,
this.description = '',
this.links = const <String, String>{},
String? routeName,
this.supportedPlatforms = PlatformType.values,
}) : _title = title,
_routeName = routeName,
Expand Down Expand Up @@ -99,7 +99,7 @@ class MyRoute extends StatelessWidget {
),
if (this.routeName != Navigator.defaultRouteName)
settings.starStatusOfRoute(this.routeName),
if (this.links?.isNotEmpty ?? false)
if (this.links.isNotEmpty)
PopupMenuButton(
itemBuilder: (context) {
return <PopupMenuItem>[
Expand Down
16 changes: 7 additions & 9 deletions lib/my_route_search_delegate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class MyRouteSearchDelegate extends SearchDelegate<String> {
return IconButton(
tooltip: 'Back',
icon: const Icon(Icons.arrow_back),
onPressed: () => this.close(context, null),
onPressed: () => this.close(context, ''),
);
}

Expand All @@ -44,15 +44,13 @@ class MyRouteSearchDelegate extends SearchDelegate<String> {
// List<String> suggestions = _history;
Iterable<MyRoute> suggestions = [
for (final routeName in Provider.of<MyAppSettings>(context).searchHistory)
kRouteNameToRoute[routeName]
kRouteNameToRoute[routeName]!
];
if (this.query.isNotEmpty) {
suggestions = kAllRoutes
.where((route) =>
route.title.toLowerCase().contains(query.toLowerCase()) ||
(route.description ?? '')
.toLowerCase()
.contains(query.toLowerCase()))
route.description.toLowerCase().contains(query.toLowerCase()))
.toList();
}
return _buildSuggestionsList(suggestions);
Expand All @@ -63,23 +61,23 @@ class MyRouteSearchDelegate extends SearchDelegate<String> {
itemCount: suggestions.length,
itemBuilder: (BuildContext context, int i) {
final route = suggestions.elementAt(i);
final routeGroup = kRouteNameToRouteGroup[route.routeName];
final routeGroup = kRouteNameToRouteGroup[route.routeName]!;
return ListTile(
leading: query.isEmpty ? const Icon(Icons.history) : routeGroup.icon,
title: SubstringHighlight(
text: '${routeGroup.groupName}/${route.title}',
term: query,
textStyle: Theme.of(context)
.textTheme
.bodyText2
.bodyText2!
.copyWith(fontWeight: FontWeight.bold),
),
subtitle: route.description == null
subtitle: route.description.isEmpty
? null
: SubstringHighlight(
text: route.description,
term: query,
textStyle: Theme.of(context).textTheme.bodyText2,
textStyle: Theme.of(context).textTheme.bodyText2!,
),
onTap: () {
Provider.of<MyAppSettings>(context, listen: false)
Expand Down
2 changes: 1 addition & 1 deletion lib/routes/about.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import 'package:flutter_catalog/constants.dart';
// Inspired by the about page in Eajy's flutter demo:
// https://github.com/Eajy/flutter_demo/blob/master/lib/route/about.dart
class MyAboutRoute extends StatelessWidget {
const MyAboutRoute({Key key}) : super(key: key);
const MyAboutRoute({Key? key}) : super(key: key);

// These tiles are also used as drawer nav items in home route.
static final List<Widget> kAboutListTiles = <Widget>[
Expand Down
4 changes: 2 additions & 2 deletions lib/routes/animation_animated_builder_ex.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import 'dart:math';
import 'package:flutter/material.dart';

class AnimatedBuilderExample extends StatefulWidget {
const AnimatedBuilderExample({Key key}) : super(key: key);
const AnimatedBuilderExample({Key? key}) : super(key: key);

@override
_AnimatedBuilderExampleState createState() => _AnimatedBuilderExampleState();
}

class _AnimatedBuilderExampleState extends State<AnimatedBuilderExample>
with SingleTickerProviderStateMixin {
AnimationController _controller;
late AnimationController _controller;

@override
void initState() {
Expand Down
Loading

0 comments on commit a314729

Please sign in to comment.