From c21ccbd54d87200c3f69322fb09c9ae74c34c006 Mon Sep 17 00:00:00 2001 From: peima Date: Sat, 25 Jul 2026 18:14:55 +0800 Subject: [PATCH] phase3: nullfix field-formal field-nullable handler. 907 -> 872 --- lib/pages/attribute_selection.dart | 6 +-- lib/pages/buy_service.dart | 2 +- lib/pages/contact_us.dart | 2 +- lib/pages/new_address.dart | 4 +- lib/pages/plain_page.dart | 2 +- lib/pages/product_detail_page.dart | 4 +- lib/pages/reset_password.dart | 2 +- lib/pages/set_password.dart | 2 +- lib/pages/shop.dart | 2 +- lib/utils/fake_iframe_web.dart | 6 +-- lib/widgets/desktop/desktop_blog.dart | 2 +- lib/widgets/desktop/desktop_my_addresses.dart | 4 +- lib/widgets/desktop/desktop_my_support.dart | 2 +- lib/widgets/desktop/desktop_new_address.dart | 22 +++++------ lib/widgets/desktop/desktop_order_detail.dart | 2 +- lib/widgets/desktop/desktop_product_item.dart | 32 ++++++++-------- .../desktop/desktop_reset_password.dart | 2 +- lib/widgets/desktop/desktop_set_password.dart | 2 +- .../desktop/desktop_shopping_cart_widget.dart | 2 +- lib/widgets/desktop/shop.dart | 2 +- lib/widgets/desktop/shopping_cart_widget.dart | 2 +- lib/widgets/general/add_remove_button.dart | 24 ++++++------ lib/widgets/general/download_item.dart | 4 +- lib/widgets/general/read_more_text.dart | 16 ++++---- lib/widgets/general/show_price.dart | 8 ++-- lib/widgets/general/sliding_up_panel.dart | 38 +++++++++---------- .../mobile/mobile_attribute_selection.dart | 2 +- lib/widgets/mobile/mobile_blog.dart | 2 +- lib/widgets/mobile/mobile_my_addresses.dart | 4 +- lib/widgets/mobile/mobile_my_support.dart | 2 +- lib/widgets/mobile/mobile_new_address.dart | 22 +++++------ lib/widgets/mobile/mobile_order_detail.dart | 2 +- lib/widgets/mobile/mobile_product_item.dart | 18 ++++----- lib/widgets/mobile/mobile_reset_password.dart | 2 +- lib/widgets/mobile/mobile_set_password.dart | 2 +- lib/widgets/mobile/shop.dart | 2 +- lib/widgets/mobile/shopping_cart_bar.dart | 6 +-- tools/nullfix.py | 22 ++++++++++- 38 files changed, 151 insertions(+), 131 deletions(-) diff --git a/lib/pages/attribute_selection.dart b/lib/pages/attribute_selection.dart index 8f9ad3a..e6c89c8 100644 --- a/lib/pages/attribute_selection.dart +++ b/lib/pages/attribute_selection.dart @@ -6,9 +6,9 @@ import '../models/business.dart'; import '../models/product.dart'; class AttributeSelection extends StatelessWidget { - final Product product; - final Business business; - final GlobalKey startKey; + final Product? product; + final Business? business; + final GlobalKey? startKey; const AttributeSelection({Key? key, this.product, this.business, this.startKey}) : super(key: key); diff --git a/lib/pages/buy_service.dart b/lib/pages/buy_service.dart index 733f1b6..e56d77f 100644 --- a/lib/pages/buy_service.dart +++ b/lib/pages/buy_service.dart @@ -19,7 +19,7 @@ import '../widgets/mobile/mobile_renew_license.dart'; class BuyService extends StatefulWidget { final int gid; final String serviceName; - final String domain; + final String? domain; final int sid; const BuyService(this.gid, this.serviceName, {Key? key, this.domain, this.sid = 0}) : diff --git a/lib/pages/contact_us.dart b/lib/pages/contact_us.dart index 3c4a61e..d486833 100644 --- a/lib/pages/contact_us.dart +++ b/lib/pages/contact_us.dart @@ -12,7 +12,7 @@ import '../widgets/desktop/desktop_contact_us.dart'; import '../widgets/mobile/mobile_contact_us.dart'; class ContactUs extends StatefulWidget { - final int businessId; + final int? businessId; const ContactUs({this.businessId, Key? key}) : super(key: key); diff --git a/lib/pages/new_address.dart b/lib/pages/new_address.dart index 8381329..afae2bd 100644 --- a/lib/pages/new_address.dart +++ b/lib/pages/new_address.dart @@ -8,8 +8,8 @@ import '../widgets/mobile/mobile_new_address.dart'; class NewAddress extends StatelessWidget { final Key? key; - final LocatedAddress locatedAddress; - final int businessId; + final LocatedAddress? locatedAddress; + final int? businessId; const NewAddress({this.key, this.locatedAddress, this.businessId}) : super(key: key); @override diff --git a/lib/pages/plain_page.dart b/lib/pages/plain_page.dart index ccfbc72..8784a31 100644 --- a/lib/pages/plain_page.dart +++ b/lib/pages/plain_page.dart @@ -12,7 +12,7 @@ import '../utils/http_util.dart'; import '../utils/utils.dart'; class PlainPage extends StatefulWidget { - final int businessId; + final int? businessId; final String slug; const PlainPage(this.slug, {this.businessId, Key? key}) : diff --git a/lib/pages/product_detail_page.dart b/lib/pages/product_detail_page.dart index dc330bc..e793f25 100644 --- a/lib/pages/product_detail_page.dart +++ b/lib/pages/product_detail_page.dart @@ -10,8 +10,8 @@ import '../widgets/desktop/desktop_product_detail_page.dart'; import '../widgets/mobile/mobile_product_detail_page.dart'; class ProductDetailPage extends StatelessWidget { - final Business business; - final Product product; + final Business? business; + final Product? product; const ProductDetailPage({this.business, this.product, Key? key}) : super(key: key); diff --git a/lib/pages/reset_password.dart b/lib/pages/reset_password.dart index 4220688..f719801 100644 --- a/lib/pages/reset_password.dart +++ b/lib/pages/reset_password.dart @@ -13,7 +13,7 @@ import '../widgets/mobile/mobile_reset_password.dart'; class ResetPassword extends StatelessWidget { final String mobile; - final String code; + final String? code; const ResetPassword(this.mobile, {Key? key, this.code}) : super(key: key); @override diff --git a/lib/pages/set_password.dart b/lib/pages/set_password.dart index 7828f9c..0ea4c7d 100644 --- a/lib/pages/set_password.dart +++ b/lib/pages/set_password.dart @@ -13,7 +13,7 @@ import '../widgets/mobile/mobile_set_password.dart'; class SetPassword extends StatelessWidget { final String mobile; - final String code; + final String? code; const SetPassword(this.mobile, {Key? key, this.code}) : super(key: key); @override diff --git a/lib/pages/shop.dart b/lib/pages/shop.dart index 1d2033f..4868cdd 100644 --- a/lib/pages/shop.dart +++ b/lib/pages/shop.dart @@ -8,7 +8,7 @@ import '../widgets/desktop/shop.dart' as desktop; import '../widgets/mobile/shop.dart' as mobile; class Shop extends StatefulWidget { - final int businessId; + final int? businessId; const Shop({this.businessId, Key? key}) : super(key: key); diff --git a/lib/utils/fake_iframe_web.dart b/lib/utils/fake_iframe_web.dart index a3a26b3..a8edf9a 100644 --- a/lib/utils/fake_iframe_web.dart +++ b/lib/utils/fake_iframe_web.dart @@ -2,9 +2,9 @@ import 'package:flutter/material.dart'; class IFrameWeb extends StatefulWidget { - final String width; - final String height; - final String src; + final String? width; + final String? height; + final String? src; const IFrameWeb({this.width, this.height, this.src}); diff --git a/lib/widgets/desktop/desktop_blog.dart b/lib/widgets/desktop/desktop_blog.dart index 8064303..37f7f97 100644 --- a/lib/widgets/desktop/desktop_blog.dart +++ b/lib/widgets/desktop/desktop_blog.dart @@ -23,7 +23,7 @@ import '../../widgets/general/navigationbar.dart'; import '../../utils/util_web.dart' if (dart.library.io) '../../utils/util_io.dart'; class DesktopBlog extends StatefulWidget { - final int businessId; + final int? businessId; const DesktopBlog({Key? key, this.businessId}) : super(key: key); @override diff --git a/lib/widgets/desktop/desktop_my_addresses.dart b/lib/widgets/desktop/desktop_my_addresses.dart index 6b2e481..cf527de 100644 --- a/lib/widgets/desktop/desktop_my_addresses.dart +++ b/lib/widgets/desktop/desktop_my_addresses.dart @@ -19,7 +19,7 @@ import '../../widgets/general/breadcrumbs.dart'; import '../../widgets/general/navigationbar.dart'; class DesktopMyAddresses extends StatefulWidget { - final int businessId; + final int? businessId; const DesktopMyAddresses({Key? key, this.businessId}) : super(key: key); @override @@ -208,7 +208,7 @@ class DesktopMyAddressesState extends State { ), ), Container( - child: widget.businessId > 0 ? IconButton( + child: widget.businessId! > 0 ? IconButton( icon: Icon( Icons.check, color: Colors.grey, diff --git a/lib/widgets/desktop/desktop_my_support.dart b/lib/widgets/desktop/desktop_my_support.dart index b82c9cb..d45170e 100644 --- a/lib/widgets/desktop/desktop_my_support.dart +++ b/lib/widgets/desktop/desktop_my_support.dart @@ -19,7 +19,7 @@ import '../../widgets/general/double_back_to_close_app_wrapper.dart'; import '../../widgets/general/navigationbar.dart'; class DesktopMySupport extends StatefulWidget { - final int businessId; + final int? businessId; const DesktopMySupport({Key? key, this.businessId}) : super(key: key); @override diff --git a/lib/widgets/desktop/desktop_new_address.dart b/lib/widgets/desktop/desktop_new_address.dart index f00e018..b8d3311 100644 --- a/lib/widgets/desktop/desktop_new_address.dart +++ b/lib/widgets/desktop/desktop_new_address.dart @@ -15,8 +15,8 @@ import '../../widgets/general/navigationbar.dart'; class DesktopNewAddress extends StatefulWidget { final Key? key; - final LocatedAddress locatedAddress; - final int businessId; + final LocatedAddress? locatedAddress; + final int? businessId; const DesktopNewAddress({this.key, this.locatedAddress, this.businessId}) : super(key: key); @override @@ -377,15 +377,15 @@ class DesktopNewAddressState extends State { super.initState(); setState(() { if (widget.locatedAddress != null) { - if (provinces.contains(widget.locatedAddress.province)) { - _selectedProvince = widget.locatedAddress.province; + if (provinces.contains(widget.locatedAddress!.province)) { + _selectedProvince = widget.locatedAddress!.province; } - cityController.text = widget.locatedAddress.city; - postalCodeController.text = widget.locatedAddress.postalCode; - streetLine1Controller.text = (widget.locatedAddress.streetNumber != null - && widget.locatedAddress.streetNumber!.isNotEmpty - ? widget.locatedAddress.streetNumber! + ' ' : '') - + widget.locatedAddress.streetName; + cityController.text = widget.locatedAddress!.city; + postalCodeController.text = widget.locatedAddress!.postalCode; + streetLine1Controller.text = (widget.locatedAddress!.streetNumber != null + && widget.locatedAddress!.streetNumber!.isNotEmpty + ? widget.locatedAddress!.streetNumber! + ' ' : '') + + widget.locatedAddress!.streetName; } else { _selectedProvince = 'Ontario'; } @@ -399,7 +399,7 @@ class DesktopNewAddressState extends State { if (form.validate()) { HttpUtil.httpPost('v1/addresses', (response) { - if (widget.businessId > 0) { + if (widget.businessId! > 0) { Routes.router.navigateTo(context, '/checkout/${widget.businessId}', replace: true); } else { Routes.router.navigateTo(context, '/my-addresses/${widget.businessId}', replace: true); diff --git a/lib/widgets/desktop/desktop_order_detail.dart b/lib/widgets/desktop/desktop_order_detail.dart index 1f62877..5b1f5a2 100644 --- a/lib/widgets/desktop/desktop_order_detail.dart +++ b/lib/widgets/desktop/desktop_order_detail.dart @@ -28,7 +28,7 @@ import '../../widgets/general/navigationbar.dart'; class DesktopOrderDetail extends StatefulWidget { final Key? key; final int orderId; - final bool fromOrders; + final bool? fromOrders; const DesktopOrderDetail(this.orderId, {this.key, this.fromOrders}); @override diff --git a/lib/widgets/desktop/desktop_product_item.dart b/lib/widgets/desktop/desktop_product_item.dart index b2e1c7f..561c986 100644 --- a/lib/widgets/desktop/desktop_product_item.dart +++ b/lib/widgets/desktop/desktop_product_item.dart @@ -13,8 +13,8 @@ import '../../widgets/general/style.dart'; import 'desktop_product_detail_page.dart'; class DesktopProductItem extends StatefulWidget { - final Product product; - final Business business; + final Product? product; + final Business? business; final bool horizontal; DesktopProductItem({this.product, this.business, Key? key, this.horizontal = false}) @@ -60,7 +60,7 @@ class DesktopProductItemState extends State { width: 110.0, height: 110.0, child: GestureDetector( - child: Util.showImage('${widget.product.imagePath}', + child: Util.showImage('${widget.product!.imagePath}', fit: BoxFit.fill, ), onTap: (){ @@ -76,7 +76,7 @@ class DesktopProductItemState extends State { Container( child: GestureDetector( child: Text( - '${widget.product.name}', + '${widget.product!.name}', // overflow: kIsWeb ? null : TextOverflow.ellipsis, overflow: TextOverflow.ellipsis, maxLines: 2, @@ -91,7 +91,7 @@ class DesktopProductItemState extends State { ), ), Text( - widget.product.description, + widget.product!.description, // overflow: kIsWeb ? null : TextOverflow.ellipsis, overflow: TextOverflow.ellipsis, maxLines: 2, @@ -107,17 +107,17 @@ class DesktopProductItemState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ new Container( - child: widget.business.showMonthlySold ? + child: widget.business!.showMonthlySold ? Text( - S.of(context).sold_per_month_token(widget.product.monthSales!.toStringAsFixed(0)), + S.of(context).sold_per_month_token(widget.product!.monthSales!.toStringAsFixed(0)), style: new TextStyle( fontSize: 9.0 ), ) : SizedBox.shrink(), ), ShowPrice( - widget.product.price, - regularPrice: widget.product.regularPrice, + widget.product!.price, + regularPrice: widget.product!.regularPrice, currencySign: '\$', fontWeight: FontWeight.bold, ), @@ -142,7 +142,7 @@ class DesktopProductItemState extends State { width: 110.0, height: 110.0, child: GestureDetector( - child: Util.showImage('${widget.product.imagePath}', + child: Util.showImage('${widget.product!.imagePath}', fit: BoxFit.fill, ), onTap: (){ @@ -158,7 +158,7 @@ class DesktopProductItemState extends State { Container( child: GestureDetector( child: Text( - '${widget.product.name}', + '${widget.product!.name}', // overflow: kIsWeb ? null : TextOverflow.ellipsis, overflow: TextOverflow.ellipsis, maxLines: 2, @@ -174,7 +174,7 @@ class DesktopProductItemState extends State { ), Container( child: Text( - widget.product.description, + widget.product!.description, // overflow: kIsWeb ? null : TextOverflow.ellipsis, overflow: TextOverflow.ellipsis, maxLines: 2, @@ -191,17 +191,17 @@ class DesktopProductItemState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ new Container( - child: widget.business.showMonthlySold ? + child: widget.business!.showMonthlySold ? Text( - S.of(context).sold_per_month_token(widget.product.monthSales!.toStringAsFixed(0)), + S.of(context).sold_per_month_token(widget.product!.monthSales!.toStringAsFixed(0)), style: new TextStyle( fontSize: 9.0 ), ) : SizedBox.shrink(), ), ShowPrice( - widget.product.price, - regularPrice: widget.product.regularPrice, + widget.product!.price, + regularPrice: widget.product!.regularPrice, currencySign: '\$', fontWeight: FontWeight.bold, ), diff --git a/lib/widgets/desktop/desktop_reset_password.dart b/lib/widgets/desktop/desktop_reset_password.dart index 71e211c..138ca1c 100644 --- a/lib/widgets/desktop/desktop_reset_password.dart +++ b/lib/widgets/desktop/desktop_reset_password.dart @@ -10,7 +10,7 @@ import '../../utils/utils.dart'; class DesktopResetPassword extends StatefulWidget { final String mobile; - final String code; + final String? code; const DesktopResetPassword(this.mobile, {this.code, Key? key}) : super(key: key); diff --git a/lib/widgets/desktop/desktop_set_password.dart b/lib/widgets/desktop/desktop_set_password.dart index 2910c98..d9cdb4b 100644 --- a/lib/widgets/desktop/desktop_set_password.dart +++ b/lib/widgets/desktop/desktop_set_password.dart @@ -10,7 +10,7 @@ import '../../utils/utils.dart'; class DesktopSetPassword extends StatefulWidget { final String mobile; - final String code; + final String? code; const DesktopSetPassword(this.mobile, {this.code, Key? key}) : super(key: key); diff --git a/lib/widgets/desktop/desktop_shopping_cart_widget.dart b/lib/widgets/desktop/desktop_shopping_cart_widget.dart index 64998c6..08f38b8 100644 --- a/lib/widgets/desktop/desktop_shopping_cart_widget.dart +++ b/lib/widgets/desktop/desktop_shopping_cart_widget.dart @@ -9,7 +9,7 @@ import '../../utils/utils.dart'; class DesktopShoppingCartWidget extends StatefulWidget { final Business business; - final Function onTap; + final Function? onTap; DesktopShoppingCartWidget({@required this.business, this.onTap}); diff --git a/lib/widgets/desktop/shop.dart b/lib/widgets/desktop/shop.dart index 21ea92d..91ea41d 100644 --- a/lib/widgets/desktop/shop.dart +++ b/lib/widgets/desktop/shop.dart @@ -22,7 +22,7 @@ import 'shop_promote.dart'; import 'shopping_cart_widget.dart'; class Shop extends StatefulWidget { - final int businessId; + final int? businessId; const Shop({Key? key, this.businessId}): super(key: key); diff --git a/lib/widgets/desktop/shopping_cart_widget.dart b/lib/widgets/desktop/shopping_cart_widget.dart index 0813f12..1e273f5 100644 --- a/lib/widgets/desktop/shopping_cart_widget.dart +++ b/lib/widgets/desktop/shopping_cart_widget.dart @@ -10,7 +10,7 @@ import '../../utils/utils.dart'; class ShoppingCartWidget extends StatefulWidget { final Business business; - final Function onTap; + final Function? onTap; ShoppingCartWidget({@required this.business, this.onTap}); diff --git a/lib/widgets/general/add_remove_button.dart b/lib/widgets/general/add_remove_button.dart index 2d7833a..0eacc8f 100644 --- a/lib/widgets/general/add_remove_button.dart +++ b/lib/widgets/general/add_remove_button.dart @@ -17,8 +17,8 @@ import '../../store/store.dart'; import '../../utils/utils.dart'; class AddRemoveButton extends StatefulWidget { - final Product product; - final Business business; + final Product? product; + final Business? business; final bool addOnly; final int cartLineItemIndex; final bool addToBasket; @@ -59,12 +59,12 @@ class AddRemoveButtonState extends State { @override Widget build(BuildContext context) { - if (widget.product.leftNum == null) { + if (widget.product!.leftNum == null) { _qty = 0; cartInfo = Utils.getCartInfoByBusiness(store.state.cartInfos, widget.business); if (cartInfo != null) { for (var i = 0; i < cartInfo.productList!.length; i++) { - if (cartInfo.productList![i].product!.id == widget.product.id + if (cartInfo.productList![i].product!.id == widget.product!.id && cartInfo.productList![i].unitPrice == 0.0) { _qty = cartInfo.productList![i].quantity!.round(); break; @@ -78,7 +78,7 @@ class AddRemoveButtonState extends State { ), ); } - if (widget.product.leftNum! <= 0) { + if (widget.product!.leftNum! <= 0) { return Container( padding: EdgeInsets.only(top: 0.0, bottom: 10.0, left: 8.0, right: 8.0), child: Text( @@ -105,7 +105,7 @@ class AddRemoveButtonState extends State { cartInfo = Utils.getCartInfoByBusiness(store.state.cartInfos, widget.business); if (cartInfo != null) { for (var i = 0; i < cartInfo.productList!.length; i++) { - if (cartInfo.productList![i].product!.id == widget.product.id) { + if (cartInfo.productList![i].product!.id == widget.product!.id) { _qty = cartInfo.productList![i].quantity!.round(); break; } @@ -198,14 +198,14 @@ class AddRemoveButtonState extends State { cartInfo = Utils.getCartInfoByBusiness(store.state.cartInfos, widget.business); if (cartInfo != null) { for (var i = 0; i < cartInfo.productList!.length; i++) { - if (cartInfo.productList![i].product!.id == widget.product.id) { + if (cartInfo.productList![i].product!.id == widget.product!.id) { _qty = cartInfo.productList![i].quantity!.round(); break; } } } - if (widget.product.productAttributes != null && - widget.product.productAttributes!.length > 0 && widget.cartLineItemIndex == -1) { + if (widget.product!.productAttributes != null && + widget.product!.productAttributes!.length > 0 && widget.cartLineItemIndex == -1) { return new Row( key: startKey, crossAxisAlignment: CrossAxisAlignment.end, @@ -312,7 +312,7 @@ class AddRemoveButtonState extends State { void _addToCart(BuildContext context) { if (widget.cartLineItemIndex != -1) { - if (cartInfo.productList![widget.cartLineItemIndex].quantity! + 1.0 > widget.product.leftNum) { + if (cartInfo.productList![widget.cartLineItemIndex].quantity! + 1.0 > widget.product!.leftNum) { Fluttertoast.showToast( msg: S.of(context).product_insufficient, toastLength: Toast.LENGTH_SHORT, @@ -328,7 +328,7 @@ class AddRemoveButtonState extends State { eventBus.fire(new OnCartInfoUpdated()); } } else { - if (widget.product.productAttributes!.length > 0) { + if (widget.product!.productAttributes!.length > 0) { Navigator.push( context, MaterialPageRoute(builder: (context) => @@ -337,7 +337,7 @@ class AddRemoveButtonState extends State { ); } else { eventBus.fire(new OnProductWillAddToCart(widget.product, {}, - widget.product.price, widget.product.description, + widget.product!.price, widget.product!.description, widget.business, buttonKey: startKey)); } } diff --git a/lib/widgets/general/download_item.dart b/lib/widgets/general/download_item.dart index 46afa5d..5d09b87 100644 --- a/lib/widgets/general/download_item.dart +++ b/lib/widgets/general/download_item.dart @@ -12,7 +12,7 @@ import '../../utils/utils.dart'; class DownloadItem extends StatefulWidget { final dynamic desc; - final double width; + final double? width; const DownloadItem(this.desc, {Key? key, this.width}) : super(key: key); @override @@ -52,7 +52,7 @@ class DownloadItemState extends State { margin: EdgeInsets.only(right: 16.0), ), Container( - width: widget.width != null ? widget.width - iconWidth - buttonWidth - 60 : MediaQuery.of(context).size.width - iconWidth - buttonWidth - 60, + width: widget.width != null ? widget.width! - iconWidth - buttonWidth - 60 : MediaQuery.of(context).size.width - iconWidth - buttonWidth - 60, child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/widgets/general/read_more_text.dart b/lib/widgets/general/read_more_text.dart index 0b8042f..8e61396 100644 --- a/lib/widgets/general/read_more_text.dart +++ b/lib/widgets/general/read_more_text.dart @@ -28,16 +28,16 @@ class ReadMoreText extends StatefulWidget { final String data; final String trimExpandedText; final String trimCollapsedText; - final Color colorClickableText; + final Color? colorClickableText; final int trimLength; final int trimLines; final TrimMode trimMode; - final TextStyle style; - final TextAlign textAlign; - final TextDirection textDirection; - final Locale locale; - final double textScaleFactor; - final String semanticsLabel; + final TextStyle? style; + final TextAlign? textAlign; + final TextDirection? textDirection; + final Locale? locale; + final double? textScaleFactor; + final String? semanticsLabel; @override ReadMoreTextState createState() => ReadMoreTextState(); @@ -58,7 +58,7 @@ class ReadMoreTextState extends State { Widget build(BuildContext context) { final DefaultTextStyle defaultTextStyle = DefaultTextStyle.of(context); TextStyle effectiveTextStyle = widget.style; - if (widget.style == null || widget.style.inherit) { + if (widget.style == null || widget.style!.inherit) { effectiveTextStyle = defaultTextStyle.style.merge(widget.style); } diff --git a/lib/widgets/general/show_price.dart b/lib/widgets/general/show_price.dart index 3183639..d73e35e 100644 --- a/lib/widgets/general/show_price.dart +++ b/lib/widgets/general/show_price.dart @@ -3,10 +3,10 @@ import 'package:flutter/material.dart'; class ShowPrice extends StatelessWidget { final double price; - final double regularPrice; + final double? regularPrice; final double largeFontSize; final double smallFontSize; - final String currencySign; + final String? currencySign; final Color color; final FontWeight fontWeight; @@ -65,12 +65,12 @@ class ShowPrice extends StatelessWidget { ), ), ), - regularPrice == null || price.round() >= regularPrice.round() ? + regularPrice == null || price.round() >= regularPrice!.round() ? SizedBox.shrink() : Container( padding: EdgeInsets.only(top: largeFontSize / 2), child: Text( - regularPrice.toStringAsFixed(0), + regularPrice!.toStringAsFixed(0), style: TextStyle( color: Colors.black38, fontSize: smallFontSize, diff --git a/lib/widgets/general/sliding_up_panel.dart b/lib/widgets/general/sliding_up_panel.dart index c7311dc..dad9e28 100644 --- a/lib/widgets/general/sliding_up_panel.dart +++ b/lib/widgets/general/sliding_up_panel.dart @@ -30,7 +30,7 @@ class SlidingUpPanel extends StatefulWidget { /// otherwise, [collapsed] will be displayed overtop /// of this Widget. If [panel] and [panelBuilder] are both non-null, /// [panel] will be used. - final Widget panel; + final Widget? panel; /// WARNING: This feature is still in beta and is subject to change without /// notice. Stability is not gauranteed. Provides a [ScrollController] and @@ -38,28 +38,28 @@ class SlidingUpPanel extends StatefulWidget { /// the panel position with the scroll position. Useful for implementing an /// infinite scroll behavior. If [panel] and [panelBuilder] are both non-null, /// [panel] will be used. - final Widget Function(ScrollController sc) panelBuilder; + final Widget Function(ScrollController sc)? panelBuilder; /// The Widget displayed overtop the [panel] when collapsed. /// This fades out as the panel is opened. - final Widget collapsed; + final Widget? collapsed; /// The Widget that lies underneath the sliding panel. /// This Widget automatically sizes itself /// to fill the screen. - final Widget body; + final Widget? body; /// Optional persistent widget that floats above the [panel] and attaches /// to the top of the [panel]. Content at the top of the panel will be covered /// by this widget. Add padding to the bottom of the `panel` to /// avoid coverage. - final Widget header; + final Widget? header; /// Optional persistent widget that floats above the [panel] and /// attaches to the bottom of the [panel]. Content at the bottom of the panel /// will be covered by this widget. Add padding to the bottom of the `panel` /// to avoid coverage. - final Widget footer; + final Widget? footer; /// The height of the sliding panel when fully collapsed. final double minHeight; @@ -72,13 +72,13 @@ class SlidingUpPanel extends StatefulWidget { /// and go directly to the open/close position. This value is represented as a /// percentage of the total animation distance ([maxHeight] - [minHeight]), /// so it must be between 0.0 and 1.0, exclusive. - final double snapPoint; + final double? snapPoint; /// A border to draw around the sliding panel sheet. - final Border border; + final Border? border; /// If non-null, the corners of the sliding panel sheet are rounded by this [BorderRadiusGeometry]. - final BorderRadiusGeometry borderRadius; + final BorderRadiusGeometry? borderRadius; /// A list of shadows cast behind the sliding panel sheet. final List boxShadow; @@ -87,10 +87,10 @@ class SlidingUpPanel extends StatefulWidget { final Color color; /// The amount to inset the children of the sliding panel sheet. - final EdgeInsetsGeometry padding; + final EdgeInsetsGeometry? padding; /// Empty space surrounding the sliding panel sheet. - final EdgeInsetsGeometry margin; + final EdgeInsetsGeometry? margin; /// Set to false to not to render the sheet the [panel] sits upon. /// This means that only the [body], [collapsed], and the [panel] @@ -104,7 +104,7 @@ class SlidingUpPanel extends StatefulWidget { final bool panelSnapping; /// If non-null, this can be used to control the state of the panel. - final PanelController controller; + final PanelController? controller; /// If non-null, shows a darkening shadow over the [body] as the panel slides open. final bool backdropEnabled; @@ -125,15 +125,15 @@ class SlidingUpPanel extends StatefulWidget { /// is called as the panel slides around with the /// current position of the panel. The position is a double /// between 0.0 and 1.0 where 0.0 is fully collapsed and 1.0 is fully open. - final void Function(double position) onPanelSlide; + final void Function(double position)? onPanelSlide; /// If non-null, this callback is called when the /// panel is fully opened - final VoidCallback onPanelOpened; + final VoidCallback? onPanelOpened; /// If non-null, this callback is called when the panel /// is fully collapsed. - final VoidCallback onPanelClosed; + final VoidCallback? onPanelClosed; /// If non-null and true, the SlidingUpPanel exhibits a /// parallax effect as the panel slides up. Essentially, @@ -320,8 +320,8 @@ class _SlidingUpPanelState extends State with SingleTickerProvid top: widget.slideDirection == SlideDirection.UP ? 0.0 : null, bottom: widget.slideDirection == SlideDirection.DOWN ? 0.0 : null, width: MediaQuery.of(context).size.width - - (widget.margin != null ? widget.margin.horizontal : 0) - - (widget.padding != null ? widget.padding.horizontal : 0), + (widget.margin != null ? widget.margin!.horizontal : 0) - + (widget.padding != null ? widget.padding!.horizontal : 0), child: Container( height: widget.maxHeight, child: widget.panel != null @@ -349,8 +349,8 @@ class _SlidingUpPanelState extends State with SingleTickerProvid top: widget.slideDirection == SlideDirection.UP ? 0.0 : null, bottom: widget.slideDirection == SlideDirection.DOWN ? 0.0 : null, width: MediaQuery.of(context).size.width - - (widget.margin != null ? widget.margin.horizontal : 0) - - (widget.padding != null ? widget.padding.horizontal : 0), + (widget.margin != null ? widget.margin!.horizontal : 0) - + (widget.padding != null ? widget.padding!.horizontal : 0), child: Container( height: widget.minHeight, child: widget.collapsed == null ? Container() : FadeTransition( diff --git a/lib/widgets/mobile/mobile_attribute_selection.dart b/lib/widgets/mobile/mobile_attribute_selection.dart index 608fe4a..a44a49f 100644 --- a/lib/widgets/mobile/mobile_attribute_selection.dart +++ b/lib/widgets/mobile/mobile_attribute_selection.dart @@ -20,7 +20,7 @@ class MobileAttributeSelection extends StatefulWidget { final Product product; final Business business; final Key? key; - final GlobalKey startKey; + final GlobalKey? startKey; const MobileAttributeSelection({@required this.product, @required this.business, this.key, this.startKey}) : super(key: key); diff --git a/lib/widgets/mobile/mobile_blog.dart b/lib/widgets/mobile/mobile_blog.dart index 6e36504..8f7d0ad 100644 --- a/lib/widgets/mobile/mobile_blog.dart +++ b/lib/widgets/mobile/mobile_blog.dart @@ -17,7 +17,7 @@ import '../../utils/utils.dart'; import '../../widgets/mobile/MobileBottomNav.dart'; class MobileBlog extends StatefulWidget { - final int businessId; + final int? businessId; const MobileBlog({Key? key, this.businessId}) : super(key: key); @override diff --git a/lib/widgets/mobile/mobile_my_addresses.dart b/lib/widgets/mobile/mobile_my_addresses.dart index 4e5b7c1..18545da 100644 --- a/lib/widgets/mobile/mobile_my_addresses.dart +++ b/lib/widgets/mobile/mobile_my_addresses.dart @@ -16,7 +16,7 @@ import 'package:flutter_wisetronic/widgets/mobile/MobileBottomNav.dart'; import '../../routes.dart'; class MobileMyAddresses extends StatefulWidget { - final int businessId; + final int? businessId; const MobileMyAddresses({Key? key, this.businessId}) : super(key: key); @override @@ -162,7 +162,7 @@ class MobileMyAddressesState extends State { ), ), Container( - child: widget.businessId > 0 ? IconButton( + child: widget.businessId! > 0 ? IconButton( icon: Icon( Icons.check, color: Colors.grey, diff --git a/lib/widgets/mobile/mobile_my_support.dart b/lib/widgets/mobile/mobile_my_support.dart index 3cf57b5..4439638 100644 --- a/lib/widgets/mobile/mobile_my_support.dart +++ b/lib/widgets/mobile/mobile_my_support.dart @@ -17,7 +17,7 @@ import '../../widgets/general/double_back_to_close_app_wrapper.dart'; import '../../widgets/mobile/MobileBottomNav.dart'; class MobileMySupport extends StatefulWidget { - final int businessId; + final int? businessId; const MobileMySupport({Key? key, this.businessId}) : super(key: key); @override diff --git a/lib/widgets/mobile/mobile_new_address.dart b/lib/widgets/mobile/mobile_new_address.dart index 887587e..dd19728 100644 --- a/lib/widgets/mobile/mobile_new_address.dart +++ b/lib/widgets/mobile/mobile_new_address.dart @@ -12,8 +12,8 @@ import '../../utils/http_util.dart'; class MobileNewAddress extends StatefulWidget { final Key? key; - final LocatedAddress locatedAddress; - final int businessId; + final LocatedAddress? locatedAddress; + final int? businessId; const MobileNewAddress({this.key, this.locatedAddress, this.businessId}) : super(key: key); @override @@ -348,15 +348,15 @@ class MobileNewAddressState extends State { super.initState(); setState(() { if (widget.locatedAddress != null) { - if (provinces.contains(widget.locatedAddress.province)) { - _selectedProvince = widget.locatedAddress.province; + if (provinces.contains(widget.locatedAddress!.province)) { + _selectedProvince = widget.locatedAddress!.province; } - cityController.text = widget.locatedAddress.city; - postalCodeController.text = widget.locatedAddress.postalCode; - streetLine1Controller.text = (widget.locatedAddress.streetNumber != null - && widget.locatedAddress.streetNumber!.isNotEmpty - ? widget.locatedAddress.streetNumber! + ' ' : '') - + widget.locatedAddress.streetName; + cityController.text = widget.locatedAddress!.city; + postalCodeController.text = widget.locatedAddress!.postalCode; + streetLine1Controller.text = (widget.locatedAddress!.streetNumber != null + && widget.locatedAddress!.streetNumber!.isNotEmpty + ? widget.locatedAddress!.streetNumber! + ' ' : '') + + widget.locatedAddress!.streetName; } else { _selectedProvince = 'Ontario'; } @@ -370,7 +370,7 @@ class MobileNewAddressState extends State { if (form.validate()) { HttpUtil.httpPost('v1/addresses', (response) { - if (widget.businessId > 0) { + if (widget.businessId! > 0) { Routes.router.navigateTo(context, '/checkout/${widget.businessId}', replace: true); } else { Routes.router.navigateTo(context, '/my-addresses/${widget.businessId}', replace: true); diff --git a/lib/widgets/mobile/mobile_order_detail.dart b/lib/widgets/mobile/mobile_order_detail.dart index d00c296..3fee39b 100644 --- a/lib/widgets/mobile/mobile_order_detail.dart +++ b/lib/widgets/mobile/mobile_order_detail.dart @@ -26,7 +26,7 @@ import '../../utils/util_web.dart' if (dart.library.io) '../../utils/util_io.dar class MobileOrderDetail extends StatefulWidget { final Key? key; final int orderId; - final bool fromOrders; + final bool? fromOrders; const MobileOrderDetail(this.orderId, {this.key, this.fromOrders}); @override diff --git a/lib/widgets/mobile/mobile_product_item.dart b/lib/widgets/mobile/mobile_product_item.dart index 015337b..0bf2479 100644 --- a/lib/widgets/mobile/mobile_product_item.dart +++ b/lib/widgets/mobile/mobile_product_item.dart @@ -12,8 +12,8 @@ import '../../widgets/general/show_price.dart'; import '../../widgets/general/style.dart'; class MobileProductItem extends StatefulWidget { - final Product product; - final Business business; + final Product? product; + final Business? business; MobileProductItem({this.product, this.business, Key? key}) : super(key: key); @@ -49,7 +49,7 @@ class MobileProductItemState extends State { width: 80.0, height: 80.0, child: GestureDetector( - child: Util.showImage('${widget.product.imagePath}', + child: Util.showImage('${widget.product!.imagePath}', fit: BoxFit.fill, ), onTap: (){ @@ -65,7 +65,7 @@ class MobileProductItemState extends State { Container( child: GestureDetector( child: Text( - '${widget.product.name}', + '${widget.product!.name}', // overflow: kIsWeb ? null : TextOverflow.ellipsis, overflow: TextOverflow.ellipsis, maxLines: 2, @@ -80,7 +80,7 @@ class MobileProductItemState extends State { ), ), new Text( - widget.product.description, + widget.product!.description, // overflow: kIsWeb ? null : TextOverflow.ellipsis, overflow: TextOverflow.ellipsis, maxLines: 2, @@ -96,9 +96,9 @@ class MobileProductItemState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ new Container( - child: widget.business.showMonthlySold ? + child: widget.business!.showMonthlySold ? Text( - S.of(context).sold_per_month_token(widget.product.monthSales!.toStringAsFixed(0)), + S.of(context).sold_per_month_token(widget.product!.monthSales!.toStringAsFixed(0)), style: new TextStyle( fontSize: 9.0 ), @@ -110,8 +110,8 @@ class MobileProductItemState extends State { textBaseline: TextBaseline.alphabetic, children: [ ShowPrice( - widget.product.price, - regularPrice: widget.product.regularPrice, + widget.product!.price, + regularPrice: widget.product!.regularPrice, currencySign: '\$', ), ], diff --git a/lib/widgets/mobile/mobile_reset_password.dart b/lib/widgets/mobile/mobile_reset_password.dart index 8a65f5a..8d53b32 100644 --- a/lib/widgets/mobile/mobile_reset_password.dart +++ b/lib/widgets/mobile/mobile_reset_password.dart @@ -10,7 +10,7 @@ import '../../utils/utils.dart'; class MobileResetPassword extends StatefulWidget { final String mobile; - final String code; + final String? code; const MobileResetPassword(this.mobile, {this.code, Key? key}) : super(key: key); diff --git a/lib/widgets/mobile/mobile_set_password.dart b/lib/widgets/mobile/mobile_set_password.dart index e488fe4..d2c4ab2 100644 --- a/lib/widgets/mobile/mobile_set_password.dart +++ b/lib/widgets/mobile/mobile_set_password.dart @@ -10,7 +10,7 @@ import '../../utils/utils.dart'; class MobileSetPassword extends StatefulWidget { final String mobile; - final String code; + final String? code; const MobileSetPassword(this.mobile, {Key? key, this.code}) : super(key: key); diff --git a/lib/widgets/mobile/shop.dart b/lib/widgets/mobile/shop.dart index be85c69..d06cce6 100644 --- a/lib/widgets/mobile/shop.dart +++ b/lib/widgets/mobile/shop.dart @@ -43,7 +43,7 @@ late double screenWidth; late double screenHeight; class Shop extends StatefulWidget { - final int businessId; + final int? businessId; const Shop({Key? key, this.businessId}) : super(key: key); diff --git a/lib/widgets/mobile/shopping_cart_bar.dart b/lib/widgets/mobile/shopping_cart_bar.dart index f043e3f..3397bcc 100644 --- a/lib/widgets/mobile/shopping_cart_bar.dart +++ b/lib/widgets/mobile/shopping_cart_bar.dart @@ -17,10 +17,10 @@ typedef OnEmptyCartListener(); typedef OnPanelOpenCloseRequest(); class ShoppingCartBar extends StatefulWidget { - final GlobalKey endKey; + final GlobalKey? endKey; final Business business; - final OnEmptyCartListener onEmptyCartListener; - final OnPanelOpenCloseRequest onPanelOpenCloseRequest; + final OnEmptyCartListener? onEmptyCartListener; + final OnPanelOpenCloseRequest? onPanelOpenCloseRequest; final bool barAtBottom; final bool hasPicture; ShoppingCartBar({@required this.business, this.endKey, diff --git a/tools/nullfix.py b/tools/nullfix.py index a7eb4bf..133d5f3 100644 --- a/tools/nullfix.py +++ b/tools/nullfix.py @@ -101,6 +101,17 @@ def insert_bang(line, col0, name, kind): return None return None +def make_field_nullable(lines, name): + """找字段声明 'Type name;' 并在类型后加 '?'。返回 (行索引, 新行) 或 (None,None)。""" + pat = re.compile(r'^(\s+(?:final\s+|const\s+)?(?:static\s+)?)(.+)\s+'+re.escape(name)+r';\s*$') + for i,L in enumerate(lines): + m=pat.match(L) + if not m: continue + mod, typ = m.group(1), m.group(2).rstrip() + if '?' in typ or '=' in L: continue + return i, f"{mod}{typ}? {name};" + return None, None + def insert_late(line): stripped=line.strip() if not stripped or stripped.startswith('late '): return None @@ -147,7 +158,16 @@ def apply_round(errs): if cls: new=insert_bang(old, col-1, cls[0], cls[1]) elif rule=='missing_default_value_for_parameter': nm=NAME.search(msg) - if nm: new=insert_nullable_before_name(old, nm.group(1), col-1) + if nm: + pname=nm.group(1) + # field-formal this.x ? 则把字段改可空(跨行) + if ('this.'+pname) in old: + fl=get(path) + fi, fnew = make_field_nullable(fl, pname) + if fi is not None and fl[fi]!=fnew: + fl[fi]=fnew; changed+=1 + else: + new=insert_nullable_before_name(old, pname, col-1) elif rule in ('not_initialized_non_nullable_instance_field','not_initialized_non_nullable_variable'): new=insert_late(old) if new and new!=old: