fix(runtime): 37 late fields with == null checks were wrongly migrated -> nullable. Fixes LateInitializationError crashes on page navigation (shop/checkout/comment/data pages)

This commit is contained in:
2026-08-01 01:58:36 +08:00
parent b49fb59db4
commit 0526baa3c8
32 changed files with 317 additions and 317 deletions

View File

@@ -45,7 +45,7 @@ class MobileCheckout extends StatefulWidget {
}
class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin {
late CartInfo cartInfo;
CartInfo? cartInfo;
Address? shipAddress;
late bool canSubmit;
late List<ErrorMessage> errorMessages;
@@ -53,7 +53,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
late List<BookingDateTime> bookingDateTimeList;
late List<PaymentPlatform> paymentPlatforms;
TextValue? durationInTraffic;
late int selectedCoupon;
int? selectedCoupon;
double couponDiscountAmount = 0;
late List<Coupon> coupons;
@@ -79,7 +79,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
GlobalKey slidingUpPanelKey = GlobalKey();
late SlidingUpPanel slidingUpPanel;
PanelController panelController = PanelController();
late Widget panel;
Widget? panel;
late double subtotal;
@@ -102,7 +102,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
);
}
if (cartInfo.businessInfo!.deliveryPickup == false && cartInfo.businessInfo!.deliveryCanadaPost == false && cartInfo.businessInfo!.deliveryStoreDelivery == false) {
if (cartInfo!.businessInfo!.deliveryPickup == false && cartInfo!.businessInfo!.deliveryCanadaPost == false && cartInfo!.businessInfo!.deliveryStoreDelivery == false) {
return Scaffold(
body: Container(
child: Center(
@@ -197,13 +197,13 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'\$${(cartInfo.totalPrice! - couponDiscountAmount).toStringAsFixed(2)}',
'\$${(cartInfo!.totalPrice! - couponDiscountAmount).toStringAsFixed(2)}',
style: TextStyle(
fontSize: 20.0,
color: Colors.white,
),
),
cartInfo.businessInfo!.isPublic == true ? SizedBox.shrink() : Container(
cartInfo!.businessInfo!.isPublic == true ? SizedBox.shrink() : Container(
padding: EdgeInsets.only(top: 2.0, bottom: 2.0, left: 5.0, right: 5.0),
width: 100.0,
color: Colors.red,
@@ -267,7 +267,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
itemCount: 6,
addAutomaticKeepAlives: true,
itemBuilder: (BuildContext context, int position) {
var deliveryTimeInSeconds = cartInfo.businessInfo!.shippingTime! * 60 + (durationInTraffic != null ? durationInTraffic!.value ?? 0 : 0);
var deliveryTimeInSeconds = cartInfo!.businessInfo!.shippingTime! * 60 + (durationInTraffic != null ? durationInTraffic!.value ?? 0 : 0);
print('aaa: $deliveryTimeInSeconds');
DateTime now = DateTime.now();
var formatter = DateFormat('H:mm');
@@ -341,7 +341,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
);
switch (position) {
case 0:
if (cartInfo.businessInfo!.deliveryPickup == true) {
if (cartInfo!.businessInfo!.deliveryPickup == true) {
return Container(
padding: EdgeInsets.only(
top: 16.0, bottom: 16.0, left: 16.0, right: 16.0),
@@ -389,7 +389,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
Container(
margin: EdgeInsets.only(top: 10.0),
child: Text(
cartInfo.businessInfo!.name!,
cartInfo!.businessInfo!.name!,
style: TextStyle(
fontSize: 17.0,
),
@@ -398,7 +398,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
Container(
margin: EdgeInsets.only(top: 5.0),
child: Text(
cartInfo.businessInfo!.address!.addressLine1!,
cartInfo!.businessInfo!.address!.addressLine1!,
style: TextStyle(
fontSize: 14.0,
color: Colors.black45,
@@ -406,9 +406,9 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
),
),
Container(
child: cartInfo.businessInfo!.address!.addressLine2 != null
&& cartInfo.businessInfo!.address!.addressLine2!.length > 0 ?
Text(cartInfo.businessInfo!.address!.addressLine2!,
child: cartInfo!.businessInfo!.address!.addressLine2 != null
&& cartInfo!.businessInfo!.address!.addressLine2!.length > 0 ?
Text(cartInfo!.businessInfo!.address!.addressLine2!,
style: TextStyle(
fontSize: 14.0,
color: Colors.black45,
@@ -417,7 +417,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
),
Container(
child: Text(
'${cartInfo.businessInfo!.address!.city}, ${cartInfo.businessInfo!.address!.state}, ${cartInfo.businessInfo!.address!.zip}',
'${cartInfo!.businessInfo!.address!.city}, ${cartInfo!.businessInfo!.address!.state}, ${cartInfo!.businessInfo!.address!.zip}',
style: TextStyle(
fontSize: 14.0,
color: Colors.black45,
@@ -427,7 +427,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
Container(
margin: EdgeInsets.only(top: 5.0),
child: Text(
'Tel: ${cartInfo.businessInfo!.phone}',
'Tel: ${cartInfo!.businessInfo!.phone}',
style: TextStyle(
fontSize: 15.0,
color: Colors.black54,
@@ -504,7 +504,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
),
),
onTap: () {
Routes.router.navigateTo(context, '/my-addresses/${cartInfo.businessInfo!.id}', replace: true);
Routes.router.navigateTo(context, '/my-addresses/${cartInfo!.businessInfo!.id}', replace: true);
},
);
break;
@@ -583,7 +583,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
},
);
}
if (cartInfo.businessInfo!.instanceDelivery != true) {
if (cartInfo!.businessInfo!.instanceDelivery != true) {
return Container(
padding: EdgeInsets.only(left: 16.0, right: 16.0, top: 0.0, bottom: 16.0),
child: Text(S.of(context).no_instance_delivery_desc),
@@ -712,7 +712,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
width: double.infinity,
padding: EdgeInsets.only(bottom: 10.0),
child: Text(
cartInfo.businessInfo!.name!,
cartInfo!.businessInfo!.name!,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 16.0,
@@ -731,9 +731,9 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
subtotal = 0.0;
for (var i = 0; i < cartInfo.productList!.length; i++) {
subtotal += cartInfo.productList![i].totalPrice!;
column.children.add(lineItem(cartInfo.productList![i]));
for (var i = 0; i < cartInfo!.productList!.length; i++) {
subtotal += cartInfo!.productList![i].totalPrice!;
column.children.add(lineItem(cartInfo!.productList![i]));
}
column.children.add(GestureDetector(
child: Container(
@@ -826,8 +826,8 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
),
));
if (cartInfo.extraFeeList!.length > 0) {
for (var i = 0; i < cartInfo.extraFeeList!.length; i++) {
if (cartInfo!.extraFeeList!.length > 0) {
for (var i = 0; i < cartInfo!.extraFeeList!.length; i++) {
column.children.add(Container(
padding: EdgeInsets.only(bottom: 16.0),
alignment: Alignment.centerRight,
@@ -838,7 +838,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
Container(
alignment: Alignment.centerRight,
child: Text(
S.of(context).extra_fee_token(cartInfo.extraFeeList![i].name!, cartInfo.extraFeeList![i].rate!),
S.of(context).extra_fee_token(cartInfo!.extraFeeList![i].name!, cartInfo!.extraFeeList![i].rate!),
style: TextStyle(
color: Colors.grey,
),
@@ -848,7 +848,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
width: 100.0,
alignment: Alignment.centerRight,
child: Text(
'${cartInfo.extraFeeList![i].price!.toStringAsFixed(2)}'
'${cartInfo!.extraFeeList![i].price!.toStringAsFixed(2)}'
),
),
],
@@ -876,7 +876,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
width: 100.0,
alignment: Alignment.centerRight,
child: Text(
'${(cartInfo.totalPrice! - couponDiscountAmount).toStringAsFixed(2)}',
'${(cartInfo!.totalPrice! - couponDiscountAmount).toStringAsFixed(2)}',
style: TextStyle(
fontSize: 19.0,
fontWeight: FontWeight.bold,
@@ -1074,7 +1074,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
shippingRates = (response.data['shipping_rates'] as List).map((e) => ShippingRate.fromJson(e)).toList();
selectedShippingRate = (response.data['selected_shipping_rate'] as String).length > 0 ? ShippingRate.fromJson(json.decode(response.data['selected_shipping_rate'])) : null;
int i = 0;
if (cartInfo.businessInfo!.deliveryStoreDelivery == true) {
if (cartInfo!.businessInfo!.deliveryStoreDelivery == true) {
shippingMethodLabels.add(S.of(context).delivery);
shippingMethodIcons.add(Icons.directions_car);
if (deliveryMethod == 'store-delivery') {
@@ -1082,7 +1082,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
}
i++;
}
if (cartInfo.businessInfo!.deliveryCanadaPost == true) {
if (cartInfo!.businessInfo!.deliveryCanadaPost == true) {
shippingMethodLabels.add(S.of(context).canada_post);
shippingMethodIcons.add(Icons.local_shipping);
if (deliveryMethod == 'canada-post') {
@@ -1090,7 +1090,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
}
i++;
}
if (cartInfo.businessInfo!.deliveryPickup == true) {
if (cartInfo!.businessInfo!.deliveryPickup == true) {
shippingMethodLabels.add(S.of(context).pickup);
shippingMethodIcons.add(Icons.store);
if (deliveryMethod == 'pickup') {
@@ -1681,7 +1681,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
return GestureDetector(
child: Container(
decoration: selectedCoupon == 0 ? BoxDecoration(
color: subtotal > cartInfo.businessInfo!.minPrice! ? Colors
color: subtotal > cartInfo!.businessInfo!.minPrice! ? Colors
.transparent : Colors.black38,
border: Border(
top: BorderSide(
@@ -1702,7 +1702,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
),
),
) : BoxDecoration(
color: subtotal > cartInfo.businessInfo!.minPrice! ? Colors
color: subtotal > cartInfo!.businessInfo!.minPrice! ? Colors
.transparent : Colors.black38,
),
child: Row(
@@ -1743,7 +1743,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
return GestureDetector(
child: Container(
decoration: selectedCoupon == coupon.id ? BoxDecoration(
color: subtotal > cartInfo.businessInfo!.minPrice! ? Colors
color: subtotal > cartInfo!.businessInfo!.minPrice! ? Colors
.transparent : Colors.black38,
border: Border(
top: BorderSide(
@@ -1917,7 +1917,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
crossAxisAlignment: CrossAxisAlignment.start,
children: [],
);
if (cartInfo.businessInfo!.quickInputs!.length > 0) {
if (cartInfo!.businessInfo!.quickInputs!.length > 0) {
Wrap w = Wrap(
children: [],
);
@@ -1931,8 +1931,8 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
),
),
));
for (int i = 0; i < cartInfo.businessInfo!.quickInputs!.length; i++) {
String qi = cartInfo.businessInfo!.quickInputs![i].value!;
for (int i = 0; i < cartInfo!.businessInfo!.quickInputs!.length; i++) {
String qi = cartInfo!.businessInfo!.quickInputs![i].value!;
w.children.add(TextButton(
child: Text(
qi,
@@ -2196,7 +2196,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
},
businessId: widget.businessId,
body: {
'cart_id': cartInfo.id,
'cart_id': cartInfo!.id,
'remark': orderRemark,
'booked_at': bookingTimeList.length > 0
? bookingTimeList[bookingTimeIndex].unixTime