This commit is contained in:
2026-07-12 04:33:48 +08:00
parent f8a90ad305
commit e7ce0f7bae
151 changed files with 2765 additions and 2947 deletions

View File

@@ -1,6 +1,6 @@
import 'package:badges/badges.dart';
import 'package:badges/badges.dart' as badges;
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
@@ -17,16 +17,16 @@ import '../../store/store.dart';
import '../../utils/utils.dart';
class AddRemoveButton extends StatefulWidget {
final Product product;
final Product? product;
final Business business;
final bool addOnly;
final int cartLineItemIndex;
final bool addToBasket;
final bool onHovor;
final bool? addOnly;
final int? cartLineItemIndex;
final bool? addToBasket;
final bool? onHovor;
AddRemoveButton({
this.product,
this.business,
required this.business,
this.addOnly = false,
this.cartLineItemIndex = -1,
this.addToBasket = false,
@@ -40,7 +40,7 @@ class AddRemoveButton extends StatefulWidget {
}
class AddRemoveButtonState extends State<AddRemoveButton> {
int _qty;
int? _qty;
var zeroColor = const Color(0xFFEFEFEF);
var qtyColor = const Color(0xFFFF6666);
var zeroFontColor = const Color(0xFF888888);
@@ -48,7 +48,7 @@ class AddRemoveButtonState extends State<AddRemoveButton> {
var d = 1;
CartInfo cartInfo;
CartInfo? cartInfo;
GlobalKey startKey = GlobalKey();
@@ -59,14 +59,14 @@ class AddRemoveButtonState extends State<AddRemoveButton> {
@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
&& cartInfo.productList[i].unitPrice == 0.0) {
_qty = cartInfo.productList[i].quantity.round();
for (var i = 0; i < cartInfo!.productList!.length; i++) {
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<AddRemoveButton> {
),
);
}
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(
@@ -100,19 +100,19 @@ class AddRemoveButtonState extends State<AddRemoveButton> {
),
);
}
if (widget.addToBasket) {
if (widget.addToBasket!) {
_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) {
_qty = cartInfo.productList[i].quantity.round();
for (var i = 0; i < cartInfo!.productList!.length; i++) {
if (cartInfo!.productList?[i].product?.id == widget.product?.id) {
_qty = cartInfo!.productList?[i].quantity?.round();
break;
}
}
}
if (_qty > 0) {
return Badge(
if (_qty! > 0) {
return badges.Badge(
badgeContent: Text(
'$_qty',
style: TextStyle(
@@ -120,14 +120,17 @@ class AddRemoveButtonState extends State<AddRemoveButton> {
fontSize: 17.0,
),
),
padding: EdgeInsets.all(10),
position: BadgePosition.topEnd(top: -15, end: -10),
badgeColor: Colors.lightBlueAccent,
badgeStyle: badges.BadgeStyle(
padding: EdgeInsets.all(10),
badgeColor: Colors.lightBlueAccent,
),
position: badges.BadgePosition.topEnd(top: -15, end: -10),
child: ElevatedButton.icon(
style: ElevatedButton.styleFrom(
primary: Colors.redAccent,
onPrimary: Colors.white,
padding: EdgeInsets.only(left: 32, right: 32, top: 20, bottom: 20),
backgroundColor: Colors.redAccent,
foregroundColor: Colors.white,
padding:
EdgeInsets.only(left: 32, right: 32, top: 20, bottom: 20),
elevation: 2.0,
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(10.0),
@@ -154,7 +157,7 @@ class AddRemoveButtonState extends State<AddRemoveButton> {
} else {
return ElevatedButton.icon(
style: ElevatedButton.styleFrom(
primary: Colors.redAccent,
backgroundColor: Colors.redAccent,
padding: EdgeInsets.only(left: 32, right: 32, top: 20, bottom: 20),
elevation: 2.0,
shape: new RoundedRectangleBorder(
@@ -179,7 +182,7 @@ class AddRemoveButtonState extends State<AddRemoveButton> {
},
);
}
} else if (widget.addOnly) {
} else if (widget.addOnly!) {
return Container(
key: startKey,
padding: EdgeInsets.all(0.0),
@@ -197,15 +200,15 @@ class AddRemoveButtonState extends State<AddRemoveButton> {
_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) {
_qty = cartInfo.productList[i].quantity.round();
for (var i = 0; i < cartInfo!.productList!.length; i++) {
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,
@@ -219,13 +222,13 @@ class AddRemoveButtonState extends State<AddRemoveButton> {
style: new TextStyle(
fontSize: 13.0,
fontWeight: FontWeight.bold,
color: _qty > 0 ? qtyFontColor : zeroFontColor
color: _qty! > 0 ? qtyFontColor : zeroFontColor
),
),
),
padding: EdgeInsets.all(5.0).copyWith(left: 10.0, right: 10.0),
decoration: BoxDecoration(
color: _qty > 0 ? qtyColor : zeroColor,
color: _qty! > 0 ? qtyColor : zeroColor,
shape: BoxShape.rectangle,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0),
@@ -242,7 +245,7 @@ class AddRemoveButtonState extends State<AddRemoveButton> {
],
);
} else {
if (!widget.onHovor && _qty == 0) {
if (!widget.onHovor! && _qty == 0) {
return SizedBox.shrink();
}
return new Row(
@@ -258,13 +261,13 @@ class AddRemoveButtonState extends State<AddRemoveButton> {
style: new TextStyle(
fontSize: 13.0,
fontWeight: FontWeight.bold,
color: _qty > 0 ? qtyFontColor : zeroFontColor
color: _qty! > 0 ? qtyFontColor : zeroFontColor
),
),
),
padding: EdgeInsets.all(5.0).copyWith(left: 10.0, right: 10.0),
decoration: BoxDecoration(
color: _qty > 0 ? qtyColor : zeroColor,
color: _qty! > 0 ? qtyColor : zeroColor,
shape: BoxShape.rectangle,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0),
@@ -299,7 +302,7 @@ class AddRemoveButtonState extends State<AddRemoveButton> {
),
),
onTap: () {
if (_qty > 0) {
if (_qty! > 0) {
_removeFromCart(context);
}
},
@@ -312,7 +315,7 @@ class AddRemoveButtonState extends State<AddRemoveButton> {
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,
@@ -321,23 +324,23 @@ class AddRemoveButtonState extends State<AddRemoveButton> {
textColor: Colors.white
);
} else {
cartInfo.productList[widget.cartLineItemIndex].quantity += 1.0;
Utils.addSubproductQty(cartInfo, cartInfo.productList[widget.cartLineItemIndex]);
cartInfo!.productList![widget.cartLineItemIndex!].quantity = cartInfo!.productList![widget.cartLineItemIndex!].quantity! + 1.0;
Utils.addSubproductQty(cartInfo!, cartInfo!.productList![widget.cartLineItemIndex!]);
store.dispatch(UpdateCartInfo(
Utils.addCartInfoToCartInfoList(store.state.cartInfos, cartInfo)));
Utils.addCartInfoToCartInfoList(store.state.cartInfos, cartInfo!)));
eventBus.fire(new OnCartInfoUpdated());
}
} else {
if (widget.product.productAttributes.length > 0) {
if (widget.product!.productAttributes!.length > 0) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) =>
new AttributeSelection(
product: widget.product, business: widget.business, startKey: startKey,)),
product: widget.product!, business: widget.business, startKey: startKey,)),
);
} else {
eventBus.fire(new OnProductWillAddToCart(widget.product, {},
widget.product.price, widget.product.description,
eventBus.fire(new OnProductWillAddToCart(widget.product!, {},
widget.product!.price!, widget.product!.description!,
widget.business, buttonKey: startKey));
}
}
@@ -345,7 +348,7 @@ class AddRemoveButtonState extends State<AddRemoveButton> {
void _removeFromCart(BuildContext context) {
if (widget.cartLineItemIndex != -1) {
if (cartInfo.productList[widget.cartLineItemIndex].quantity <= 1) {
if (cartInfo!.productList![widget.cartLineItemIndex!].quantity! <= 1) {
showDialog(
context: context,
builder: (BuildContext context) {
@@ -375,23 +378,23 @@ class AddRemoveButtonState extends State<AddRemoveButton> {
}
} else {
eventBus.fire(new OnProductWillRemoveFromCart(
widget.product, -1, widget.business));
widget.product!, -1, widget.business));
}
}
void _removeCartLineItem() {
if (cartInfo.productList[widget.cartLineItemIndex].quantity <= 1) {
String uuid = cartInfo.productList[widget.cartLineItemIndex].uuid;
cartInfo.productList.removeAt(widget.cartLineItemIndex);
Utils.removeSubproduct(cartInfo, uuid);
if (cartInfo!.productList![widget.cartLineItemIndex!].quantity! <= 1) {
String uuid = cartInfo!.productList![widget.cartLineItemIndex!].uuid!;
cartInfo!.productList?.removeAt(widget.cartLineItemIndex!);
Utils.removeSubproduct(cartInfo!, uuid);
} else {
cartInfo.productList[widget.cartLineItemIndex].quantity -= 1;
Utils.addSubproductQty(cartInfo, cartInfo.productList[widget.cartLineItemIndex], remove: true);
cartInfo!.productList![widget.cartLineItemIndex!].quantity = cartInfo!.productList![widget.cartLineItemIndex!].quantity! - 1;
Utils.addSubproductQty(cartInfo!, cartInfo!.productList![widget.cartLineItemIndex!], remove: true);
}
if (cartInfo.productList.length <= 0) {
if (cartInfo!.productList!.length <= 0) {
store.dispatch(new UpdateCartInfo(Utils.removeCartInfoFromCartInfoList(store.state.cartInfos, cartInfo)));
} else {
store.dispatch(new UpdateCartInfo(Utils.addCartInfoToCartInfoList(store.state.cartInfos, cartInfo)));
store.dispatch(new UpdateCartInfo(Utils.addCartInfoToCartInfoList(store.state.cartInfos, cartInfo!)));
}
eventBus.fire(new OnCartInfoUpdated());
}

View File

@@ -5,23 +5,23 @@ import 'popup_animation_widget.dart';
class AnimationPointManager {
List<AnimatedWidget> list = [];
static AnimationController controller1;
static AnimationController controller2;
static AnimationController? controller1;
static AnimationController? controller2;
Future<void> addParabolicAniamtion({
@required TickerProvider vsync,
@required GlobalKey stackKey,
@required GlobalKey startKey,
@required GlobalKey endKey,
@required Duration duration,
@required AnimationStatusListener statusListener,
required TickerProvider vsync,
required GlobalKey stackKey,
required GlobalKey startKey,
required GlobalKey endKey,
required Duration duration,
required AnimationStatusListener statusListener,
Color color = Colors.red,
double size = 20,
Offset startAdjustOffset = Offset.zero,
Offset endAdjustOffset = Offset.zero,
}) async {
controller1 = createController(vsync, duration);
Animation animation = createAnimation(controller1);
Animation<double> animation = createAnimation(controller1);
AnimatedWidget animatedWidget = ParabolicAnimationWidget(
animation: animation,
@@ -37,9 +37,9 @@ class AnimationPointManager {
statusListener(AnimationStatus.dismissed);
try {
await controller1.forward().orCancel;
await controller1?.forward().orCancel;
list.remove(animatedWidget);
controller1.dispose();
controller1?.dispose();
print('Controller1 disposed');
} on TickerCanceled {
print("Ticker Canceled");
@@ -51,31 +51,31 @@ class AnimationPointManager {
}
Future<void> addPopupAniamtion({
@required TickerProvider vsync,
@required GlobalKey stackKey,
@required GlobalKey startKey,
@required Widget child,
Duration duration,
required TickerProvider vsync,
required GlobalKey stackKey,
required GlobalKey startKey,
required Widget child,
required Duration duration,
Offset popupOffset = Offset.zero,
AnimationStatusListener statusListener,
AnimationStatusListener? statusListener,
}) async {
controller2 = createController(vsync, duration);
AnimatedWidget animatedWidget = PopupAnimationWidget(
animation: controller2.view,
animation: controller2!.view,
stackKey: stackKey,
startKey: startKey,
child: child,
popupOffset: popupOffset,
);
list.add(animatedWidget);
statusListener(AnimationStatus.dismissed);
if (statusListener != null) statusListener(AnimationStatus.dismissed);
try {
await controller2.forward().orCancel;
await controller2.reverse().orCancel;
await controller2?.forward().orCancel;
await controller2?.reverse().orCancel;
list.remove(animatedWidget);
controller2.dispose();
controller2?.dispose();
print('Controller2 disposed');
} on TickerCanceled {
print("Ticker Canceled");
@@ -83,7 +83,7 @@ class AnimationPointManager {
print('Error: $error');
}
statusListener(AnimationStatus.completed);
if (statusListener != null) statusListener(AnimationStatus.completed);
}
static AnimationController createController(

View File

@@ -14,7 +14,7 @@ import 'rules.dart';
import 'options_base.dart';
class CheckOptions extends OptionsBase {
CheckOptions({@required Product product, @required int index, @required Map<String, dynamic> selections})
CheckOptions({required Product product, required int index, required Map<String, dynamic> selections})
: super(product: product, index: index, selections: selections);
@override
@@ -50,14 +50,14 @@ class CheckOptionsState extends OptionsBaseState<CheckOptions> {
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Text(
S.of(context).check_option_select_token(product.productAttributes[this.index].name),
S.of(context).check_option_select_token(product!.productAttributes![this.index!].name),
style: new TextStyle(
fontSize: 12.5,
),
overflow: TextOverflow.ellipsis,
),
new Text(
product.productAttributes[this.index].required ? S.of(context).check_option_is_required : S.of(context).check_option_is_optional,
product!.productAttributes![this.index!].required ? S.of(context).check_option_is_required : S.of(context).check_option_is_optional,
style: new TextStyle(
fontSize: 10.0,
color: new Color(0xFF999999)
@@ -95,25 +95,25 @@ class CheckOptionsState extends OptionsBaseState<CheckOptions> {
'adjust_amount': adjustAmount
};
var cloneSelections = json.decode(json.encode(selections));
int idx = Utils.selectionsContains(cloneSelections, product.productAttributes[index].name, name);
int idx = Utils.selectionsContains(cloneSelections, product!.productAttributes![index!].name, name);
if (idx != -1) {
(cloneSelections[product.productAttributes[index].name.toUpperCase()] as List).removeAt(idx);
} else if (cloneSelections.containsKey(product.productAttributes[index].name.toUpperCase())) {
(cloneSelections[product.productAttributes[index].name.toUpperCase()] as List).add(opt);
(cloneSelections[product!.productAttributes![index!].name.toUpperCase()] as List).removeAt(idx);
} else if (cloneSelections.containsKey(product!.productAttributes![index!].name.toUpperCase())) {
(cloneSelections[product!.productAttributes![index!].name.toUpperCase()] as List).add(opt);
} else {
cloneSelections[product.productAttributes[index].name.toUpperCase()] = [opt];
cloneSelections[product!.productAttributes![index!].name.toUpperCase()] = [opt];
}
if (idx != -1 && (cloneSelections[product.productAttributes[index].name.toUpperCase()] as List).length == 0) {
cloneSelections.remove(product.productAttributes[index].name.toUpperCase());
if (idx != -1 && (cloneSelections[product!.productAttributes![index!].name.toUpperCase()] as List).length == 0) {
cloneSelections.remove(product!.productAttributes![index!].name.toUpperCase());
}
setOptionsStateDisabled(product.productAttributes[index].name, false);
setOptionsStateDisabled(product!.productAttributes![index!].name, false);
setState(() {
selections = cloneSelections;
});
eventBus.fire(new OnAttributeSelectionsChanged(selections));
eventBus.fire(new OnAttributeSelectionsChanged(selections!));
}
Widget _getOptionWidget() {
@@ -121,20 +121,20 @@ class CheckOptionsState extends OptionsBaseState<CheckOptions> {
children: <Widget>[],
);
List<ProductOption> productOptions = product.productAttributes[index].productOptions;
List<ProductOption> productOptions = product!.productAttributes![index!].productOptions;
if (!optionsState.containsKey(product.productAttributes[index].name)) {
if (!optionsState.containsKey(product!.productAttributes![index!].name)) {
List<Map<String, dynamic>> optionState = [];
for (var i = 0; i < productOptions.length; i++) {
optionState.add({'name': product.productAttributes[index].productOptions[i].name, 'disabled': false, 'check': false});
optionState.add({'name': product!.productAttributes![index!].productOptions[i].name, 'disabled': false, 'check': false});
}
optionsState[product.productAttributes[index].name] = optionState;
optionsState[product!.productAttributes![index!].name] = optionState;
}
if (selections.containsKey(product.productAttributes[index].name.toUpperCase())) {
if (selections!.containsKey(product!.productAttributes![index!].name.toUpperCase())) {
Map<String, dynamic> attrExtraJson = Utils.stringToJson(
product.productAttributes[index].extra);
Map<String, dynamic>? attrExtraJson = Utils.stringToJson(
product!.productAttributes![index!].extra);
if (attrExtraJson != null) {
var selectLimitIfFieldEqualsTo = Rule.getRule(
attrExtraJson, Rule.RULE_SELECT_LIMIT_IF_FIELD_EQUALS_TO);
@@ -147,15 +147,15 @@ class CheckOptionsState extends OptionsBaseState<CheckOptions> {
int limitQty = selectLimitIfFieldEqualsTo1[Rule
.RULE_KEY_FORCE_LIMITED];
thisLimitQty = limitQty;
if ((selections[product.productAttributes[index].name
if ((selections![product!.productAttributes![index!].name
.toUpperCase()] as List).length >= limitQty) {
disableOptionIfNotSelected();
}
} else if (Utils.getSelectedAttributeValue(selections, selectLimitIfFieldEqualsTo1[Rule.RULE_KEY_FIELD_KEY]).length > 0) {
if (selectLimitIfFieldEqualsTo1.containsKey(Utils.getSelectedAttributeValue(selections, selectLimitIfFieldEqualsTo1[Rule.RULE_KEY_FIELD_KEY])[0])) {
int limitQty = selectLimitIfFieldEqualsTo1[Utils.getSelectedAttributeValue(selections, selectLimitIfFieldEqualsTo1[Rule.RULE_KEY_FIELD_KEY])[0]];
} else if (Utils.getSelectedAttributeValue(selections!, selectLimitIfFieldEqualsTo1[Rule.RULE_KEY_FIELD_KEY]).length > 0) {
if (selectLimitIfFieldEqualsTo1.containsKey(Utils.getSelectedAttributeValue(selections!, selectLimitIfFieldEqualsTo1[Rule.RULE_KEY_FIELD_KEY])[0])) {
int limitQty = selectLimitIfFieldEqualsTo1[Utils.getSelectedAttributeValue(selections!, selectLimitIfFieldEqualsTo1[Rule.RULE_KEY_FIELD_KEY])[0]];
thisLimitQty = limitQty;
if ((selections[product.productAttributes[index].name
if ((selections![product!.productAttributes![index!].name
.toUpperCase()] as List).length >= limitQty) {
disableOptionIfNotSelected();
}
@@ -168,15 +168,15 @@ class CheckOptionsState extends OptionsBaseState<CheckOptions> {
int limitQty = selectLimitIfFieldEqualsTo[Rule
.RULE_KEY_FORCE_LIMITED];
thisLimitQty = limitQty;
if ((selections[product.productAttributes[index].name
if ((selections![product!.productAttributes![index!].name
.toUpperCase()] as List).length >= limitQty) {
disableOptionIfNotSelected();
}
} else if (Utils.getSelectedAttributeValue(selections, selectLimitIfFieldEqualsTo[Rule.RULE_KEY_FIELD_KEY]).length > 0) {
if (selectLimitIfFieldEqualsTo.containsKey(Utils.getSelectedAttributeValue(selections, selectLimitIfFieldEqualsTo[Rule.RULE_KEY_FIELD_KEY])[0])) {
int limitQty = selectLimitIfFieldEqualsTo[Utils.getSelectedAttributeValue(selections, selectLimitIfFieldEqualsTo[Rule.RULE_KEY_FIELD_KEY])[0]];
} else if (Utils.getSelectedAttributeValue(selections!, selectLimitIfFieldEqualsTo[Rule.RULE_KEY_FIELD_KEY]).length > 0) {
if (selectLimitIfFieldEqualsTo.containsKey(Utils.getSelectedAttributeValue(selections!, selectLimitIfFieldEqualsTo[Rule.RULE_KEY_FIELD_KEY])[0])) {
int limitQty = selectLimitIfFieldEqualsTo[Utils.getSelectedAttributeValue(selections!, selectLimitIfFieldEqualsTo[Rule.RULE_KEY_FIELD_KEY])[0]];
thisLimitQty = limitQty;
if ((selections[product.productAttributes[index].name
if ((selections![product!.productAttributes![index!].name
.toUpperCase()] as List).length >= limitQty) {
disableOptionIfNotSelected();
}
@@ -187,7 +187,7 @@ class CheckOptionsState extends OptionsBaseState<CheckOptions> {
}
for (var i = 0; i < productOptions.length; i++) {
Map<String, dynamic> extraJson = Utils.stringToJson(
Map<String, dynamic>? extraJson = Utils.stringToJson(
productOptions[i].extra);
if (extraJson != null) {
Map<String, dynamic> exclusiveRule = Rule.getRule(
@@ -195,12 +195,12 @@ class CheckOptionsState extends OptionsBaseState<CheckOptions> {
Map<String, dynamic> multiItemRule = Rule.getRule(extraJson, Rule.RULE_ACTUAL_QTY_IS);
if (exclusiveRule != null) {
if (thisLimitQty > 0 && !_checkOptionIsCheck(productOptions[i].name)) {
optionsState[product.productAttributes[index].name][i]['disabled'] = true;
optionsState[product!.productAttributes![index!].name][i]['disabled'] = true;
} else {
if (_checkOptionIsCheck(productOptions[i].name)) {
setOptionsStateDisabled(
product.productAttributes[index].name, true);
optionsState[product.productAttributes[index]
product!.productAttributes![index!].name, true);
optionsState[product!.productAttributes![index!]
.name][i]['disabled'] = false;
break;
}
@@ -208,12 +208,12 @@ class CheckOptionsState extends OptionsBaseState<CheckOptions> {
}
if (multiItemRule != null) {
if (_checkOptionIsCheck(productOptions[i].name)) {
if (multiItemRule[Rule.RULE_ACTUAL_QTY_IS] > thisLimitQty - (selections[product.productAttributes[index].name.toUpperCase()] as List).length) {
if (multiItemRule[Rule.RULE_ACTUAL_QTY_IS] > thisLimitQty - (selections![product!.productAttributes![index!].name.toUpperCase()] as List).length) {
disableOptionIfNotSelected();
}
} else {
if (multiItemRule[Rule.RULE_ACTUAL_QTY_IS] > thisLimitQty - (selections[product.productAttributes[index].name.toUpperCase()] as List).length) {
optionsState[product.productAttributes[index]
if (multiItemRule[Rule.RULE_ACTUAL_QTY_IS] > thisLimitQty - (selections![product!.productAttributes![index!].name.toUpperCase()] as List).length) {
optionsState[product!.productAttributes![index!]
.name][i]['disabled'] = true;
}
}
@@ -222,26 +222,26 @@ class CheckOptionsState extends OptionsBaseState<CheckOptions> {
}
}
List<Map<String, dynamic>> optionState = optionsState[product.productAttributes[index].name];
List<Map<String, dynamic>> optionState = optionsState[product!.productAttributes![index!].name];
for (var i = 0; i < optionState.length; i++) {
Widget optionWidget = _getOptionCheck(
product.productAttributes[index].productOptions[i], optionState[i]['disabled'], i);
product!.productAttributes![index!].productOptions[i], optionState[i]['disabled'], i);
row.children.add(optionWidget);
}
return row;
}
void disableOptionIfNotSelected() {
setOptionsStateDisabled(product.productAttributes[index].name, true);
for (var i = 0; i < optionsState[product.productAttributes[index].name].length; i++) {
if (Utils.selectionsContains(selections, product.productAttributes[index].name, optionsState[product.productAttributes[index].name][i]['name']) != -1) {
optionsState[product.productAttributes[index].name][i]['disabled'] = false;
setOptionsStateDisabled(product!.productAttributes![index!].name, true);
for (var i = 0; i < optionsState[product!.productAttributes![index!].name].length; i++) {
if (Utils.selectionsContains(selections!, product!.productAttributes![index!].name, optionsState[product!.productAttributes![index!].name][i]['name']) != -1) {
optionsState[product!.productAttributes![index!].name][i]['disabled'] = false;
}
}
}
bool _checkOptionIsCheck(String name) {
if (Utils.selectionsContains(selections, product.productAttributes[index].name, name) != -1) {
if (Utils.selectionsContains(selections!, product!.productAttributes![index!].name, name) != -1) {
return true;
}
return false;
@@ -251,7 +251,7 @@ class CheckOptionsState extends OptionsBaseState<CheckOptions> {
bool disabled = optDisabled;
bool check = _checkOptionIsCheck(productOption.name);
Map<String, dynamic> extraJson = Utils.stringToJson(productOption.extra);
Map<String, dynamic>? extraJson = Utils.stringToJson(productOption.extra);
// Utils.jsonPrettyPrint(extraJson);
double extraAdjustAmount = 0.0;
@@ -262,13 +262,13 @@ class CheckOptionsState extends OptionsBaseState<CheckOptions> {
if (sizeBaseAdjustment is List) {
for (var i = 0; i < (sizeBaseAdjustment as List).length; i++) {
Map<String, dynamic> sizeBaseAdjustment1 = sizeBaseAdjustment[i];
List<String> attValues = Utils.getSelectedAttributeValue(selections, sizeBaseAdjustment1[Rule.RULE_KEY_FIELD_KEY]);
List<String> attValues = Utils.getSelectedAttributeValue(selections!, sizeBaseAdjustment1[Rule.RULE_KEY_FIELD_KEY]);
if (attValues.length > 0 && sizeBaseAdjustment1.containsKey(attValues[0])) {
extraAdjustAmount += sizeBaseAdjustment1[attValues[0]];
}
}
} else {
List<String> attValues = Utils.getSelectedAttributeValue(selections, sizeBaseAdjustment[Rule.RULE_KEY_FIELD_KEY]);
List<String> attValues = Utils.getSelectedAttributeValue(selections!, sizeBaseAdjustment[Rule.RULE_KEY_FIELD_KEY]);
if (attValues.length > 0 && sizeBaseAdjustment.containsKey(attValues[0])) {
extraAdjustAmount += sizeBaseAdjustment[attValues[0]];
}
@@ -282,7 +282,7 @@ class CheckOptionsState extends OptionsBaseState<CheckOptions> {
for (var i = 0; i < (disabledRule as List).length; i++) {
Map<String, dynamic> disabledRule1 = disabledRule[i];
List<String> attValues = Utils.getSelectedAttributeValue(
selections, disabledRule1[Rule.RULE_KEY_FIELD_KEY]);
selections!, disabledRule1[Rule.RULE_KEY_FIELD_KEY]);
if (attValues.length > 0 &&
disabledRule1.containsKey(attValues[0])) {
disabled = true;
@@ -301,7 +301,7 @@ class CheckOptionsState extends OptionsBaseState<CheckOptions> {
}
} else {
List<String> attValues = Utils.getSelectedAttributeValue(
selections, disabledRule[Rule.RULE_KEY_FIELD_KEY]);
selections!, disabledRule[Rule.RULE_KEY_FIELD_KEY]);
if (attValues.length > 0) {
for (String s in attValues) {
if (disabledRule.containsKey(s) && disabledRule[s]) {

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_wisetronic/models/product.dart';
import '../../../models/product.dart';
typedef void OnOptionTapped(String name, int quantity, double adjustAmount);
@@ -9,16 +9,16 @@ abstract class OptionsBase extends StatefulWidget {
final Product product;
final int index;
final Map<String, dynamic> selections;
OptionsBase({@required Product product, @required int index, @required Map<String, dynamic> selections})
OptionsBase({required Product product, required int index, required Map<String, dynamic> selections})
: product = product,
index = index,
selections = selections;
}
abstract class OptionsBaseState<Base extends OptionsBase> extends State<Base> {
Product product;
Map<String, dynamic> selections;
int index;
Product? product;
Map<String, dynamic>? selections;
int? index;
final Color disabledBackgroundColor = new Color(0xFFBCBCBC);

View File

@@ -14,7 +14,7 @@ import 'options_base.dart';
import 'rules.dart';
class QtyOptions extends OptionsBase {
QtyOptions({@required Product product, @required int index, @required Map<String, dynamic> selections})
QtyOptions({required Product product, required int index, required Map<String, dynamic> selections})
: super(product: product, index: index, selections: selections);
@override
@@ -41,14 +41,14 @@ class QtyOptionsState extends OptionsBaseState<QtyOptions> {
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Text(
S.of(context).check_option_select_token(product.productAttributes[this.index].name),
S.of(context).check_option_select_token(product!.productAttributes![this.index!].name),
style: new TextStyle(
fontSize: 12.5,
),
overflow: TextOverflow.ellipsis,
),
new Text(
product.productAttributes[this.index].required ? S.of(context).check_option_is_required : S.of(context).check_option_is_optional,
product!.productAttributes![this.index!].required ? S.of(context).check_option_is_required : S.of(context).check_option_is_optional,
style: new TextStyle(
fontSize: 10.0,
color: new Color(0xFF999999)
@@ -86,38 +86,38 @@ class QtyOptionsState extends OptionsBaseState<QtyOptions> {
'adjust_amount': adjustAmount
};
var cloneSelections = json.decode(json.encode(selections));
int idx = Utils.selectionsContains(cloneSelections, product.productAttributes[index].name, name);
int idx = Utils.selectionsContains(cloneSelections, product!.productAttributes![index!].name, name);
if (idx != -1) {
if (quantity == 1) {
cloneSelections[product.productAttributes[index].name.toUpperCase()][idx]['quantity'] += 1;
optionsState[product.productAttributes[index].name][optIndex]['quantity'] = cloneSelections[product.productAttributes[index].name.toUpperCase()][idx]['quantity'];
cloneSelections[product!.productAttributes![index!].name.toUpperCase()][idx]['quantity'] += 1;
optionsState[product!.productAttributes![index!].name][optIndex]['quantity'] = cloneSelections[product!.productAttributes![index!].name.toUpperCase()][idx]['quantity'];
} else {
if (cloneSelections[product.productAttributes[index].name.toUpperCase()][idx]['quantity'] - 1 > 0) {
cloneSelections[product.productAttributes[index].name.toUpperCase()][idx]['quantity'] -= 1;
optionsState[product.productAttributes[index].name][optIndex]['quantity'] = cloneSelections[product.productAttributes[index].name.toUpperCase()][idx]['quantity'];
if (cloneSelections[product!.productAttributes![index!].name.toUpperCase()][idx]['quantity'] - 1 > 0) {
cloneSelections[product!.productAttributes![index!].name.toUpperCase()][idx]['quantity'] -= 1;
optionsState[product!.productAttributes![index!].name][optIndex]['quantity'] = cloneSelections[product!.productAttributes![index!].name.toUpperCase()][idx]['quantity'];
} else {
(cloneSelections[product.productAttributes[index].name.toUpperCase()] as List).removeAt(idx);
optionsState[product.productAttributes[index].name][optIndex]['quantity'] = 0;
(cloneSelections[product!.productAttributes![index!].name.toUpperCase()] as List).removeAt(idx);
optionsState[product!.productAttributes![index!].name][optIndex]['quantity'] = 0;
}
}
} else if (cloneSelections.containsKey(product.productAttributes[index].name.toUpperCase())) {
(cloneSelections[product.productAttributes[index].name.toUpperCase()] as List).add(opt);
optionsState[product.productAttributes[index].name][optIndex]['quantity'] = 1;
} else if (cloneSelections.containsKey(product!.productAttributes![index!].name.toUpperCase())) {
(cloneSelections[product!.productAttributes![index!].name.toUpperCase()] as List).add(opt);
optionsState[product!.productAttributes![index!].name][optIndex]['quantity'] = 1;
} else {
cloneSelections[product.productAttributes[index].name.toUpperCase()] = [opt];
optionsState[product.productAttributes[index].name][optIndex]['quantity'] = 1;
cloneSelections[product!.productAttributes![index!].name.toUpperCase()] = [opt];
optionsState[product!.productAttributes![index!].name][optIndex]['quantity'] = 1;
}
if (idx != -1 && (cloneSelections[product.productAttributes[index].name.toUpperCase()] as List).length == 0) {
cloneSelections.remove(product.productAttributes[index].name.toUpperCase());
if (idx != -1 && (cloneSelections[product!.productAttributes![index!].name.toUpperCase()] as List).length == 0) {
cloneSelections.remove(product!.productAttributes![index!].name.toUpperCase());
}
setOptionsStateDisabled(product.productAttributes[index].name, false);
setOptionsStateDisabled(product!.productAttributes![index!].name, false);
setState(() {
selections = cloneSelections;
});
eventBus.fire(new OnAttributeSelectionsChanged(selections));
eventBus.fire(new OnAttributeSelectionsChanged(selections!));
}
Widget _getOptionWidget() {
@@ -125,24 +125,24 @@ class QtyOptionsState extends OptionsBaseState<QtyOptions> {
children: <Widget>[],
);
List<ProductOption> productOptions = product.productAttributes[index].productOptions;
List<ProductOption> productOptions = product!.productAttributes![index!].productOptions;
if (!optionsState.containsKey(product.productAttributes[index].name)) {
if (!optionsState.containsKey(product!.productAttributes![index!].name)) {
List<Map<String, dynamic>> optionState = [];
for (var i = 0; i < productOptions.length; i++) {
int qty = 0;
int idx = Utils.selectionsContains(selections, product.productAttributes[index].name, productOptions[i].name);
int idx = Utils.selectionsContains(selections!, product!.productAttributes![index!].name, productOptions[i].name);
if (idx != -1) {
qty = selections[product.productAttributes[index].name.toUpperCase()][idx]['quantity'];
qty = selections![product!.productAttributes![index!].name.toUpperCase()][idx]['quantity'];
}
optionState.add({'name': product.productAttributes[index].productOptions[i].name, 'disabled': false, 'quantity': qty, 'check': false});
optionState.add({'name': product!.productAttributes![index!].productOptions[i].name, 'disabled': false, 'quantity': qty, 'check': false});
}
optionsState[product.productAttributes[index].name] = optionState;
optionsState[product!.productAttributes![index!].name] = optionState;
}
if (selections.containsKey(product.productAttributes[index].name.toUpperCase())) {
Map<String, dynamic> attrExtraJson = Utils.stringToJson(
product.productAttributes[index].extra);
if (selections!.containsKey(product!.productAttributes![index!].name.toUpperCase())) {
Map<String, dynamic>? attrExtraJson = Utils.stringToJson(
product!.productAttributes![index!].extra);
if (attrExtraJson != null) {
var selectLimitIfFieldEqualsTo = Rule.getRule(
attrExtraJson, Rule.RULE_SELECT_LIMIT_IF_FIELD_EQUALS_TO);
@@ -155,15 +155,15 @@ class QtyOptionsState extends OptionsBaseState<QtyOptions> {
int limitQty = selectLimitIfFieldEqualsTo1[Rule
.RULE_KEY_FORCE_LIMITED];
thisLimitQty = limitQty;
if ((selections[product.productAttributes[index].name
if ((selections![product!.productAttributes![index!].name
.toUpperCase()] as List).length >= limitQty) {
disableOptionIfNotSelected();
}
} else if (Utils.getSelectedAttributeValue(selections, selectLimitIfFieldEqualsTo1[Rule.RULE_KEY_FIELD_KEY]).length > 0) {
if (selectLimitIfFieldEqualsTo1.containsKey(Utils.getSelectedAttributeValue(selections, selectLimitIfFieldEqualsTo1[Rule.RULE_KEY_FIELD_KEY])[0])) {
int limitQty = selectLimitIfFieldEqualsTo1[Utils.getSelectedAttributeValue(selections, selectLimitIfFieldEqualsTo1[Rule.RULE_KEY_FIELD_KEY])[0]];
} else if (Utils.getSelectedAttributeValue(selections!, selectLimitIfFieldEqualsTo1[Rule.RULE_KEY_FIELD_KEY]).length > 0) {
if (selectLimitIfFieldEqualsTo1.containsKey(Utils.getSelectedAttributeValue(selections!, selectLimitIfFieldEqualsTo1[Rule.RULE_KEY_FIELD_KEY])[0])) {
int limitQty = selectLimitIfFieldEqualsTo1[Utils.getSelectedAttributeValue(selections!, selectLimitIfFieldEqualsTo1[Rule.RULE_KEY_FIELD_KEY])[0]];
thisLimitQty = limitQty;
if ((selections[product.productAttributes[index].name
if ((selections![product!.productAttributes![index!].name
.toUpperCase()] as List).length >= limitQty) {
disableOptionIfNotSelected();
}
@@ -176,15 +176,15 @@ class QtyOptionsState extends OptionsBaseState<QtyOptions> {
int limitQty = selectLimitIfFieldEqualsTo[Rule
.RULE_KEY_FORCE_LIMITED];
thisLimitQty = limitQty;
if ((selections[product.productAttributes[index].name
if ((selections![product!.productAttributes![index!].name
.toUpperCase()] as List).length >= limitQty) {
disableOptionIfNotSelected();
}
} else if (Utils.getSelectedAttributeValue(selections, selectLimitIfFieldEqualsTo[Rule.RULE_KEY_FIELD_KEY]).length > 0) {
if (selectLimitIfFieldEqualsTo.containsKey(Utils.getSelectedAttributeValue(selections, selectLimitIfFieldEqualsTo[Rule.RULE_KEY_FIELD_KEY])[0])) {
int limitQty = selectLimitIfFieldEqualsTo[Utils.getSelectedAttributeValue(selections, selectLimitIfFieldEqualsTo[Rule.RULE_KEY_FIELD_KEY])[0]];
} else if (Utils.getSelectedAttributeValue(selections!, selectLimitIfFieldEqualsTo[Rule.RULE_KEY_FIELD_KEY]).length > 0) {
if (selectLimitIfFieldEqualsTo.containsKey(Utils.getSelectedAttributeValue(selections!, selectLimitIfFieldEqualsTo[Rule.RULE_KEY_FIELD_KEY])[0])) {
int limitQty = selectLimitIfFieldEqualsTo[Utils.getSelectedAttributeValue(selections!, selectLimitIfFieldEqualsTo[Rule.RULE_KEY_FIELD_KEY])[0]];
thisLimitQty = limitQty;
if ((selections[product.productAttributes[index].name
if ((selections![product!.productAttributes![index!].name
.toUpperCase()] as List).length >= limitQty) {
disableOptionIfNotSelected();
}
@@ -195,7 +195,7 @@ class QtyOptionsState extends OptionsBaseState<QtyOptions> {
}
for (var i = 0; i < productOptions.length; i++) {
Map<String, dynamic> extraJson = Utils.stringToJson(
Map<String, dynamic>? extraJson = Utils.stringToJson(
productOptions[i].extra);
if (extraJson != null) {
Map<String, dynamic> exclusiveRule = Rule.getRule(
@@ -203,12 +203,12 @@ class QtyOptionsState extends OptionsBaseState<QtyOptions> {
Map<String, dynamic> multiItemRule = Rule.getRule(extraJson, Rule.RULE_ACTUAL_QTY_IS);
if (exclusiveRule != null) {
if (thisLimitQty > 0 && !_checkOptionIsCheck(productOptions[i].name)) {
optionsState[product.productAttributes[index].name][i]['disabled'] = true;
optionsState[product!.productAttributes![index!].name][i]['disabled'] = true;
} else {
if (_checkOptionIsCheck(productOptions[i].name)) {
setOptionsStateDisabled(
product.productAttributes[index].name, true);
optionsState[product.productAttributes[index]
product!.productAttributes![index!].name, true);
optionsState[product!.productAttributes![index!]
.name][i]['disabled'] = false;
break;
}
@@ -216,12 +216,12 @@ class QtyOptionsState extends OptionsBaseState<QtyOptions> {
}
if (multiItemRule != null) {
if (_checkOptionIsCheck(productOptions[i].name)) {
if (multiItemRule[Rule.RULE_ACTUAL_QTY_IS] > thisLimitQty - (selections[product.productAttributes[index].name.toUpperCase()] as List).length) {
if (multiItemRule[Rule.RULE_ACTUAL_QTY_IS] > thisLimitQty - (selections![product!.productAttributes![index!].name.toUpperCase()] as List).length) {
disableOptionIfNotSelected();
}
} else {
if (multiItemRule[Rule.RULE_ACTUAL_QTY_IS] > thisLimitQty - (selections[product.productAttributes[index].name.toUpperCase()] as List).length) {
optionsState[product.productAttributes[index]
if (multiItemRule[Rule.RULE_ACTUAL_QTY_IS] > thisLimitQty - (selections![product!.productAttributes![index!].name.toUpperCase()] as List).length) {
optionsState[product!.productAttributes![index!]
.name][i]['disabled'] = true;
}
}
@@ -230,26 +230,26 @@ class QtyOptionsState extends OptionsBaseState<QtyOptions> {
}
}
List<Map<String, dynamic>> optionState = optionsState[product.productAttributes[index].name];
List<Map<String, dynamic>> optionState = optionsState[product!.productAttributes![index!].name];
for (var i = 0; i < optionState.length; i++) {
Widget optionWidget = _getOptionQty(
product.productAttributes[index].productOptions[i], optionState[i]['disabled'], optionState[i]['quantity'], i);
product!.productAttributes![index!].productOptions[i], optionState[i]['disabled'], optionState[i]['quantity'], i);
row.children.add(optionWidget);
}
return row;
}
void disableOptionIfNotSelected() {
setOptionsStateDisabled(product.productAttributes[index].name, true);
for (var i = 0; i < optionsState[product.productAttributes[index].name].length; i++) {
if (Utils.selectionsContains(selections, product.productAttributes[index].name, optionsState[product.productAttributes[index].name][i]['name']) != -1) {
optionsState[product.productAttributes[index].name][i]['disabled'] = false;
setOptionsStateDisabled(product!.productAttributes![index!].name, true);
for (var i = 0; i < optionsState[product!.productAttributes![index!].name].length; i++) {
if (Utils.selectionsContains(selections!, product!.productAttributes![index!].name, optionsState[product!.productAttributes![index!].name][i]['name']) != -1) {
optionsState[product!.productAttributes![index!].name][i]['disabled'] = false;
}
}
}
bool _checkOptionIsCheck(String name) {
if (Utils.selectionsContains(selections, product.productAttributes[index].name, name) != -1) {
if (Utils.selectionsContains(selections!, product!.productAttributes![index!].name, name) != -1) {
return true;
}
return false;
@@ -259,7 +259,7 @@ class QtyOptionsState extends OptionsBaseState<QtyOptions> {
bool disabled = optDisabled;
bool check = _checkOptionIsCheck(productOption.name);
Map<String, dynamic> extraJson = Utils.stringToJson(productOption.extra);
Map<String, dynamic>? extraJson = Utils.stringToJson(productOption.extra);
// Utils.jsonPrettyPrint(extraJson);
double extraAdjustAmount = 0.0;
@@ -270,13 +270,13 @@ class QtyOptionsState extends OptionsBaseState<QtyOptions> {
if (sizeBaseAdjustment is List) {
for (var i = 0; i < (sizeBaseAdjustment as List).length; i++) {
Map<String, dynamic> sizeBaseAdjustment1 = sizeBaseAdjustment[i];
List<String> attValues = Utils.getSelectedAttributeValue(selections, sizeBaseAdjustment1[Rule.RULE_KEY_FIELD_KEY]);
List<String> attValues = Utils.getSelectedAttributeValue(selections!, sizeBaseAdjustment1[Rule.RULE_KEY_FIELD_KEY]);
if (attValues.length > 0 && sizeBaseAdjustment1.containsKey(attValues[0])) {
extraAdjustAmount += sizeBaseAdjustment1[attValues[0]];
}
}
} else {
List<String> attValues = Utils.getSelectedAttributeValue(selections, sizeBaseAdjustment[Rule.RULE_KEY_FIELD_KEY]);
List<String> attValues = Utils.getSelectedAttributeValue(selections!, sizeBaseAdjustment[Rule.RULE_KEY_FIELD_KEY]);
if (attValues.length > 0 && sizeBaseAdjustment.containsKey(attValues[0])) {
extraAdjustAmount += sizeBaseAdjustment[attValues[0]];
}
@@ -290,7 +290,7 @@ class QtyOptionsState extends OptionsBaseState<QtyOptions> {
for (var i = 0; i < (disabledRule as List).length; i++) {
Map<String, dynamic> disabledRule1 = disabledRule[i];
List<String> attValues = Utils.getSelectedAttributeValue(
selections, disabledRule1[Rule.RULE_KEY_FIELD_KEY]);
selections!, disabledRule1[Rule.RULE_KEY_FIELD_KEY]);
if (attValues.length > 0 &&
disabledRule1.containsKey(attValues[0])) {
disabled = true;
@@ -309,7 +309,7 @@ class QtyOptionsState extends OptionsBaseState<QtyOptions> {
}
} else {
List<String> attValues = Utils.getSelectedAttributeValue(
selections, disabledRule[Rule.RULE_KEY_FIELD_KEY]);
selections!, disabledRule[Rule.RULE_KEY_FIELD_KEY]);
if (attValues.length > 0) {
for (String s in attValues) {
if (disabledRule.containsKey(s) && disabledRule[s]) {

View File

@@ -14,7 +14,7 @@ import 'options_base.dart';
import 'rules.dart';
class RadioOptions extends OptionsBase {
RadioOptions({@required Product product, @required int index, @required Map<String, dynamic> selections})
RadioOptions({required Product product, required int index, required Map<String, dynamic> selections})
: super(product: product, index: index, selections: selections);
@override
@@ -40,14 +40,14 @@ class RadioOptionsState extends OptionsBaseState<RadioOptions> {
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Text(
S.of(context).radio_option_select_token(product.productAttributes[this.index].name),
S.of(context).radio_option_select_token(product!.productAttributes![this.index!].name),
style: new TextStyle(
fontSize: 12.5,
),
overflow: TextOverflow.ellipsis,
),
new Text(
product.productAttributes[this.index].required ? S.of(context).radio_option_is_required : S.of(context).radio_option_is_optional,
product!.productAttributes![this.index!].required ? S.of(context).radio_option_is_required : S.of(context).radio_option_is_optional,
style: new TextStyle(
fontSize: 10.0,
color: new Color(0xFF999999)
@@ -85,24 +85,24 @@ class RadioOptionsState extends OptionsBaseState<RadioOptions> {
'adjust_amount': adjustAmount
};
var cloneSelections = json.decode(json.encode(selections));
if (product.productAttributes[index].required) {
cloneSelections[product.productAttributes[index].name.toUpperCase()] = [opt];
if (product!.productAttributes![index!].required) {
cloneSelections[product!.productAttributes![index!].name.toUpperCase()] = [opt];
} else {
if (cloneSelections.containsKey(product.productAttributes[index].name.toUpperCase())
&& Utils.equalsIgnoreCase(cloneSelections[product.productAttributes[index].name.toUpperCase()][0]['name'], name)) {
cloneSelections.remove(product.productAttributes[index].name.toUpperCase());
if (cloneSelections.containsKey(product!.productAttributes![index!].name.toUpperCase())
&& Utils.equalsIgnoreCase(cloneSelections[product!.productAttributes![index!].name.toUpperCase()][0]['name'], name)) {
cloneSelections.remove(product!.productAttributes![index!].name.toUpperCase());
} else {
cloneSelections[product.productAttributes[index].name.toUpperCase()] = [opt];
cloneSelections[product!.productAttributes![index!].name.toUpperCase()] = [opt];
}
}
Map<String, dynamic> extraJson = Utils.stringToJson(productOption.extra);
Map<String, dynamic>? extraJson = Utils.stringToJson(productOption.extra);
if (extraJson != null) {
Map<String, dynamic> exclusiveRule = Rule.getRule(
extraJson, Rule.RULE_EXCLUSIVE_SELECTION);
if (exclusiveRule != null) {
if (_checkOptionIsCheck(productOption.name)) {
setOptionsStateDisabled(product.productAttributes[index].name, false);
setOptionsStateDisabled(product!.productAttributes![index!].name, false);
}
}
}
@@ -110,7 +110,7 @@ class RadioOptionsState extends OptionsBaseState<RadioOptions> {
setState(() {
selections = cloneSelections;
});
eventBus.fire(new OnAttributeSelectionsChanged(selections));
eventBus.fire(new OnAttributeSelectionsChanged(selections!));
}
Widget _getOptionWidget() {
@@ -118,42 +118,42 @@ class RadioOptionsState extends OptionsBaseState<RadioOptions> {
children: <Widget>[],
);
List<ProductOption> productOptions = product.productAttributes[index].productOptions;
List<ProductOption> productOptions = product!.productAttributes![index!].productOptions;
if (!optionsState.containsKey(product.productAttributes[index].name)) {
if (!optionsState.containsKey(product!.productAttributes![index!].name)) {
List<Map<String, dynamic>> optionState = [];
for (var i = 0; i < productOptions.length; i++) {
optionState.add({'name': product.productAttributes[index].productOptions[i].name, 'disabled': false, 'check': false});
optionState.add({'name': product!.productAttributes![index!].productOptions[i].name, 'disabled': false, 'check': false});
}
optionsState[product.productAttributes[index].name] = optionState;
optionsState[product!.productAttributes![index!].name] = optionState;
}
for (var i = 0; i < productOptions.length; i++) {
Map<String, dynamic> extraJson = Utils.stringToJson(productOptions[i].extra);
Map<String, dynamic>? extraJson = Utils.stringToJson(productOptions[i].extra);
if (extraJson != null) {
Map<String, dynamic> exclusiveRule = Rule.getRule(
extraJson, Rule.RULE_EXCLUSIVE_SELECTION);
if (exclusiveRule != null) {
if (_checkOptionIsCheck(productOptions[i].name)) {
setOptionsStateDisabled(product.productAttributes[index].name, true);
optionsState[product.productAttributes[index].name][i]['disabled'] = false;
setOptionsStateDisabled(product!.productAttributes![index!].name, true);
optionsState[product!.productAttributes![index!].name][i]['disabled'] = false;
break;
}
}
}
}
List<Map<String, dynamic>> optionState = optionsState[product.productAttributes[index].name];
List<Map<String, dynamic>> optionState = optionsState[product!.productAttributes![index!].name];
for (var i = 0; i < optionState.length; i++) {
Widget optionWidget = _getOptionRadio(
product.productAttributes[index].productOptions[i], optionState[i]['disabled'], i);
product!.productAttributes![index!].productOptions[i], optionState[i]['disabled'], i);
row.children.add(optionWidget);
}
return row;
}
bool _checkOptionIsCheck(String name) {
if (Utils.selectionsContains(selections, product.productAttributes[index].name, name) != -1) {
if (Utils.selectionsContains(selections!, product!.productAttributes![index!].name, name) != -1) {
return true;
}
return false;
@@ -163,7 +163,7 @@ class RadioOptionsState extends OptionsBaseState<RadioOptions> {
bool disabled = optDisabled;
bool check = _checkOptionIsCheck(productOption.name);
Map<String, dynamic> extraJson = Utils.stringToJson(productOption.extra);
Map<String, dynamic>? extraJson = Utils.stringToJson(productOption.extra);
// Utils.jsonPrettyPrint(extraJson);
double extraAdjustAmount = 0.0;
@@ -174,13 +174,13 @@ class RadioOptionsState extends OptionsBaseState<RadioOptions> {
if (sizeBaseAdjustment is List) {
for (var i = 0; i < (sizeBaseAdjustment as List).length; i++) {
Map<String, dynamic> sizeBaseAdjustment1 = sizeBaseAdjustment[i];
List<String> attValues = Utils.getSelectedAttributeValue(selections, sizeBaseAdjustment1[Rule.RULE_KEY_FIELD_KEY]);
List<String> attValues = Utils.getSelectedAttributeValue(selections!, sizeBaseAdjustment1[Rule.RULE_KEY_FIELD_KEY]);
if (attValues.length > 0 && sizeBaseAdjustment1.containsKey(attValues[0])) {
extraAdjustAmount += sizeBaseAdjustment1[attValues[0]];
}
}
} else {
List<String> attValues = Utils.getSelectedAttributeValue(selections, sizeBaseAdjustment[Rule.RULE_KEY_FIELD_KEY]);
List<String> attValues = Utils.getSelectedAttributeValue(selections!, sizeBaseAdjustment[Rule.RULE_KEY_FIELD_KEY]);
if (attValues.length > 0 && sizeBaseAdjustment.containsKey(attValues[0])) {
extraAdjustAmount += sizeBaseAdjustment[attValues[0]];
}
@@ -194,7 +194,7 @@ class RadioOptionsState extends OptionsBaseState<RadioOptions> {
for (var i = 0; i < (disabledRule as List).length; i++) {
Map<String, dynamic> disabledRule1 = disabledRule[i];
List<String> attValues = Utils.getSelectedAttributeValue(
selections, disabledRule1[Rule.RULE_KEY_FIELD_KEY]);
selections!, disabledRule1[Rule.RULE_KEY_FIELD_KEY]);
if (attValues.length > 0 &&
disabledRule1.containsKey(attValues[0])) {
disabled = true;
@@ -213,7 +213,7 @@ class RadioOptionsState extends OptionsBaseState<RadioOptions> {
}
} else {
List<String> attValues = Utils.getSelectedAttributeValue(
selections, disabledRule[Rule.RULE_KEY_FIELD_KEY]);
selections!, disabledRule[Rule.RULE_KEY_FIELD_KEY]);
if (attValues.length > 0) {
for (String s in attValues) {
if (disabledRule.containsKey(s) && disabledRule[s]) {

View File

@@ -2,7 +2,7 @@
import 'package:flutter/material.dart';
class BottomNav extends StatefulWidget {
const BottomNav({Key key}) : super(key: key);
const BottomNav({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() {

View File

@@ -7,10 +7,10 @@ import '../../routes.dart';
import 'navigationbar.dart';
class BreadCrumbs extends StatelessWidget {
final List<BreadCrumb> breadCrumbs;
final List<BreadCrumb>? breadCrumbs;
final bool hasBack;
final OnBackPress onBackPress;
const BreadCrumbs(this.hasBack, {this.breadCrumbs, Key key, this.onBackPress}) : super(key: key);
final OnBackPress? onBackPress;
const BreadCrumbs(this.hasBack, {this.breadCrumbs, Key? key, this.onBackPress}) : super(key: key);
@override
Widget build(BuildContext context) {
@@ -49,17 +49,17 @@ class BreadCrumbs extends StatelessWidget {
));
}
if (breadCrumbs != null) {
for (int i = 0; i < breadCrumbs.length; i++) {
BreadCrumb breadCrumb = breadCrumbs[i];
for (int i = 0; i < breadCrumbs!.length; i++) {
BreadCrumb breadCrumb = breadCrumbs![i];
if (breadCrumb.text == null && breadCrumb.item != null) {
if (breadCrumb.onTap == null) {
widgets.add(breadCrumb.item);
widgets.add(breadCrumb.item!);
} else {
widgets.add(MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
child: breadCrumb.item,
onTap: breadCrumb.onTap,
child: breadCrumb.item!,
onTap: breadCrumb.onTap as GestureTapCallback?,
),
));
}
@@ -94,7 +94,7 @@ class BreadCrumbs extends StatelessWidget {
color: Colors.blueAccent,
),
Text(
breadCrumb.text,
breadCrumb.text ?? '',
style: TextStyle(
color: Colors.blueAccent,
fontSize: 14.0,
@@ -103,7 +103,7 @@ class BreadCrumbs extends StatelessWidget {
],
) :
Text(
breadCrumb.text,
breadCrumb.text ?? '',
style: TextStyle(
color: Colors.blueAccent,
fontSize: 14.0,
@@ -113,7 +113,7 @@ class BreadCrumbs extends StatelessWidget {
],
),
onTap: () {
Routes.router.navigateTo(context, breadCrumb.route);
Routes.router.navigateTo(context, breadCrumb.route ?? '');
},
),
),
@@ -145,7 +145,7 @@ class BreadCrumbs extends StatelessWidget {
color: Colors.lightBlueAccent,
),
Text(
breadCrumb.text,
breadCrumb.text ?? '',
style: TextStyle(
color: Colors.black54,
fontSize: 14.0,
@@ -155,7 +155,7 @@ class BreadCrumbs extends StatelessWidget {
],
) :
Text(
breadCrumb.text,
breadCrumb.text ?? '',
style: TextStyle(
color: Colors.black54,
fontSize: 14.0,
@@ -184,11 +184,11 @@ class BreadCrumbs extends StatelessWidget {
}
class BreadCrumb {
final String text;
final String route;
final IconData icon;
final Widget item;
final Function onTap;
final String? text;
final String? route;
final IconData? icon;
final Widget? item;
final Function? onTap;
BreadCrumb(this.text, this.route, {this.icon, this.item, this.onTap});
}

View File

@@ -6,8 +6,8 @@ import 'style.dart';
class Carousel extends StatefulWidget {
Carousel({
double height = 200.0,
List<Widget> pages,
bool autoPlay,
List<Widget>? pages,
bool autoPlay = false,
Duration duration = const Duration(seconds: 2),
Duration animationDuration = const Duration(milliseconds: 1000),
})
@@ -17,11 +17,11 @@ class Carousel extends StatefulWidget {
duration = duration,
animationDuration = animationDuration;
final double height;
final List<Widget> pages;
final bool autoPlay;
final Duration duration;
final Duration animationDuration;
final double? height;
final List<Widget>? pages;
final bool? autoPlay;
final Duration? duration;
final Duration? animationDuration;
@override
createState() => new CarouselState();
@@ -30,7 +30,7 @@ class Carousel extends StatefulWidget {
class CarouselState extends State<Carousel> {
final _pageController = new PageController();
Timer _timer;
Timer? _timer;
int _currentPage = 0;
bool reverse = false;
GlobalKey<IndicatorState> _indicatorStateKey = new GlobalKey();
@@ -38,13 +38,13 @@ class CarouselState extends State<Carousel> {
@override
void initState() {
super.initState();
if (widget.autoPlay) {
_timer = new Timer.periodic(widget.duration, (timer) {
if (widget.autoPlay!) {
_timer = new Timer.periodic(widget.duration!, (timer) {
_pageController.animateToPage(_currentPage,
duration: widget.animationDuration, curve: Curves.linear);
duration: widget.animationDuration!, curve: Curves.linear);
if (!reverse) {
_currentPage += 1;
if (_currentPage == widget.pages.length) {
if (_currentPage == widget.pages?.length) {
_currentPage -= 1;
reverse = true;
}
@@ -61,9 +61,9 @@ class CarouselState extends State<Carousel> {
@override
void dispose() {
_pageController?.dispose();
_pageController.dispose();
if (_timer != null) {
_timer.cancel();
_timer!.cancel();
}
super.dispose();
}
@@ -77,10 +77,10 @@ class CarouselState extends State<Carousel> {
color: Style.backgroundColor,
child: new PageView(
controller: _pageController,
children: widget.pages,
children: widget.pages!,
onPageChanged: (index) {
_currentPage = index;
_indicatorStateKey.currentState.changeIndex(index);
_indicatorStateKey.currentState?.changeIndex(index);
},
),
),
@@ -91,7 +91,7 @@ class CarouselState extends State<Carousel> {
child: new Align(
child: new Indicator(
key: _indicatorStateKey,
count: widget.pages.length,
count: widget.pages!.length,
),
alignment: Alignment.center,
),
@@ -102,11 +102,11 @@ class CarouselState extends State<Carousel> {
}
class Indicator extends StatefulWidget {
Indicator({Key key, int count})
Indicator({Key? key, int? count})
: count = count,
super(key: key);
final int count;
final int? count;
@override
createState() => new IndicatorState();
@@ -124,7 +124,7 @@ class IndicatorState extends State<Indicator> {
@override
Widget build(BuildContext context) {
var indicators = <Widget>[];
for (var i = 0; i < widget.count; ++i) {
for (var i = 0; i < widget.count!; ++i) {
indicators.add(new Container(
width: 5.0,
height: 5.0,
@@ -135,7 +135,7 @@ class IndicatorState extends State<Indicator> {
));
}
return new SizedBox(
width: widget.count * 15.0,
width: widget.count! * 15.0,
height: 30.0,
child: new Row(
children: indicators,

View File

@@ -4,9 +4,9 @@ import '../../generated/l10n.dart';
import '../../utils/double_back_to_close_app.dart';
class DoubleBackToCloseAppWrapper extends StatelessWidget {
final Widget child;
final Widget? child;
const DoubleBackToCloseAppWrapper({Key key, this.child}) : super(key: key);
const DoubleBackToCloseAppWrapper({Key? key, this.child}) : super(key: key);
@override
Widget build(BuildContext context) {
@@ -20,7 +20,7 @@ class DoubleBackToCloseAppWrapper extends StatelessWidget {
),
),
),
child: child,
child: child!,
);
}
}

View File

@@ -12,8 +12,8 @@ import '../../utils/utils.dart';
class DownloadItem extends StatefulWidget {
final dynamic desc;
final double width;
const DownloadItem(this.desc, {Key key, this.width}) : super(key: key);
final double? width;
const DownloadItem(this.desc, {Key? key, this.width}) : super(key: key);
@override
State<StatefulWidget> createState() {
@@ -52,7 +52,7 @@ class DownloadItemState extends State<DownloadItem> {
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,
@@ -186,9 +186,9 @@ class DownloadItemState extends State<DownloadItem> {
}
Widget getDownloadButton() {
String downloadUrl;
String os = Utils.getOs();
String selectedOs;
String? downloadUrl;
String? os = Utils.getOs();
String? selectedOs;
List<String> supportedOss = [];
for (int i = 0; i < (widget.desc['urls'] as List).length; i++) {
supportedOss.add((widget.desc['urls'] as List)[i]['os']);
@@ -244,7 +244,7 @@ class DownloadItemState extends State<DownloadItem> {
} else if (downloadUrl != null && downloadUrl.isNotEmpty) {
return ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Theme.of(context).primaryColor,
backgroundColor: Theme.of(context).primaryColor,
padding: EdgeInsets.all(8)
),
child: Row(
@@ -255,7 +255,7 @@ class DownloadItemState extends State<DownloadItem> {
padding: EdgeInsets.only(right: 0.0, left: 6.0, top: 6.0, bottom: 6.0),
child: Icon(
IconData(
Utils.getOsFontHex(selectedOs),
Utils.getOsFontHex(selectedOs!),
fontFamily: 'wisetronic',
fontPackage: null
),

View File

@@ -7,14 +7,14 @@ import 'package:responsive_builder/responsive_builder.dart';
class IndexCarousel extends StatelessWidget {
final List<Gallery> galleries;
const IndexCarousel(this.galleries, {Key key}) : super(key: key);
const IndexCarousel(this.galleries, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ScreenTypeLayout(
mobile: MobileIndexCarousel(galleries),
tablet: DesktopIndexCarousel(galleries),
desktop: DesktopIndexCarousel(galleries),
return ScreenTypeLayout.builder(
mobile: (context) => MobileIndexCarousel(galleries),
tablet: (context) => DesktopIndexCarousel(galleries),
desktop: (context) => DesktopIndexCarousel(galleries),
);
}

View File

@@ -6,14 +6,14 @@ import 'package:responsive_builder/responsive_builder.dart';
class IndexMainContent1 extends StatelessWidget {
final String message;
const IndexMainContent1(this.message, {Key key}) : super(key: key);
const IndexMainContent1(this.message, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ScreenTypeLayout(
mobile: MobileIndexMainContent1(message),
tablet: DesktopIndexMainContent1(message),
desktop: DesktopIndexMainContent1(message),
return ScreenTypeLayout.builder(
mobile: (context) => MobileIndexMainContent1(message),
tablet: (context) => DesktopIndexMainContent1(message),
desktop: (context) => DesktopIndexMainContent1(message),
);
}

View File

@@ -6,14 +6,14 @@ import 'package:responsive_builder/responsive_builder.dart';
class IndexMainContent2 extends StatelessWidget {
final Map<String, dynamic> content;
const IndexMainContent2(this.content, {Key key}) : super(key: key);
const IndexMainContent2(this.content, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ScreenTypeLayout(
mobile: MobileIndexMainContent2(content),
tablet: DesktopIndexMainContent2(content),
desktop: DesktopIndexMainContent2(content),
return ScreenTypeLayout.builder(
mobile: (context) => MobileIndexMainContent2(content),
tablet: (context) => DesktopIndexMainContent2(content),
desktop: (context) => DesktopIndexMainContent2(content),
);
}

View File

@@ -6,14 +6,14 @@ import 'package:responsive_builder/responsive_builder.dart';
class IndexMainContent3 extends StatelessWidget {
final Map<String, dynamic> content;
const IndexMainContent3(this.content, {Key key}) : super(key: key);
const IndexMainContent3(this.content, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ScreenTypeLayout(
mobile: MobileIndexMainContent3(content),
tablet: DesktopIndexMainContent3(content),
desktop: DesktopIndexMainContent3(content),
return ScreenTypeLayout.builder(
mobile: (context) => MobileIndexMainContent3(content),
tablet: (context) => DesktopIndexMainContent3(content),
desktop: (context) => DesktopIndexMainContent3(content),
);
}

View File

@@ -9,17 +9,17 @@ import 'breadcrumbs.dart';
typedef OnBackPress();
class MiniNavigationBar extends StatefulWidget implements PreferredSizeWidget {
final Key key;
final Key? key;
final String title;
final bool back;
final bool toHome;
final bool showMe;
final List<BreadCrumb> breadCrumbs;
final double breadCrumbHeight;
final Widget shoppingCart;
final List<BreadCrumb>? breadCrumbs;
final double? breadCrumbHeight;
final Widget? shoppingCart;
MiniNavigationBar({Key key, PreferredSizeWidget bottom, String title,
bool back, bool toHome, bool showMe, this.breadCrumbs,
MiniNavigationBar({Key? key, PreferredSizeWidget? bottom, String? title,
bool? back, bool? toHome, bool? showMe, this.breadCrumbs,
this.breadCrumbHeight, this.shoppingCart})
: key = key,
preferredSize = breadCrumbHeight != null ? Size.fromHeight(kToolbarHeight + breadCrumbHeight) :
@@ -43,12 +43,12 @@ class MiniNavigationBarState extends State<MiniNavigationBar> {
@override
Widget build(BuildContext context) {
return ScreenTypeLayout(
mobile: MobileNavigationBar(title: widget.title, back: widget.back,
return ScreenTypeLayout.builder(
mobile: (context) => MobileNavigationBar(title: widget.title, back: widget.back,
toHome: widget.toHome, showMe: widget.showMe,),
tablet: DesktopNavigationBar(hasBack: widget.back,
tablet: (context) => DesktopNavigationBar(hasBack: widget.back,
breadCrumbs: widget.breadCrumbs, shoppingCart: widget.shoppingCart,),
desktop: DesktopNavigationBar(hasBack: widget.back,
desktop: (context) => DesktopNavigationBar(hasBack: widget.back,
breadCrumbs: widget.breadCrumbs, shoppingCart: widget.shoppingCart,),
);
}

View File

@@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
import '../../constants.dart';
class NavigationBarLogo extends StatelessWidget {
const NavigationBarLogo({Key key}) : super(key: key);
const NavigationBarLogo({Key? key}) : super(key: key);
static const IconData logoData = IconData(
Constants.FONT_WISETRONIC,

View File

@@ -6,30 +6,30 @@ class ParabolicAnimationWidget extends AnimatedWidget {
final GlobalKey stackKey;
final GlobalKey startKey;
final GlobalKey endKey;
final double size;
final Color color;
final Offset startAdjustOffset;
final Offset endAdjustOffset;
final double? size;
final Color? color;
final Offset? startAdjustOffset;
final Offset? endAdjustOffset;
ParabolicAnimationWidget({
@required Animation<double> animation,
@required this.stackKey,
@required this.startKey,
@required this.endKey,
required Animation<double> animation,
required this.stackKey,
required this.startKey,
required this.endKey,
this.size = 20.0,
this.color = Colors.red,
this.startAdjustOffset = Offset.zero,
this.endAdjustOffset = Offset.zero,
}) : super(listenable: animation);
Offset _startOffset;
Offset _endOffset;
Offset _startOffset = Offset.zero;
Offset _endOffset = Offset.zero;
@override
Widget build(BuildContext context) {
_calPoints();
final Animation<double> animation = listenable;
final Animation<double> animation = listenable as Animation<double>;
final double time = animation.value;
// 设time=1 已知两点坐标 和 初速度 可求出 加速度 a
@@ -58,7 +58,7 @@ class ParabolicAnimationWidget extends AnimatedWidget {
width: size,
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.all(Radius.circular(size / 2.0))),
borderRadius: BorderRadius.all(Radius.circular(size! / 2.0))),
),
),
);
@@ -66,26 +66,26 @@ class ParabolicAnimationWidget extends AnimatedWidget {
void _calPoints() {
if (_startOffset == null) {
RenderBox stackBox = stackKey.currentContext.findRenderObject();
RenderBox stackBox = stackKey.currentContext?.findRenderObject() as RenderBox;
Offset stackBoxOffset = stackBox.globalToLocal(Offset.zero);
EdgeInsets startMargin = _margin(startKey);
RenderBox startBox = startKey.currentContext.findRenderObject();
RenderBox startBox = startKey.currentContext?.findRenderObject() as RenderBox;
_startOffset = startBox.localToGlobal(Offset(
startMargin.left + startAdjustOffset.dx,
stackBoxOffset.dy + startMargin.top + startAdjustOffset.dy));
startMargin.left + startAdjustOffset!.dx,
stackBoxOffset.dy + startMargin.top + startAdjustOffset!.dy));
EdgeInsets endMargin = _margin(endKey);
RenderBox endBox = endKey.currentContext.findRenderObject();
RenderBox endBox = endKey.currentContext?.findRenderObject() as RenderBox;
_endOffset = endBox.localToGlobal(Offset(
endMargin.left + endAdjustOffset.dx,
stackBoxOffset.dy + endMargin.top + endAdjustOffset.dy));
endMargin.left + endAdjustOffset!.dx,
stackBoxOffset.dy + endMargin.top + endAdjustOffset!.dy));
}
}
EdgeInsets _margin(GlobalKey key) {
final Widget widget = key.currentContext.widget;
EdgeInsets margin = (widget is Container) ? widget.margin : EdgeInsets.zero;
final Widget widget = key.currentContext!.widget;
EdgeInsets margin = (widget is Container) ? widget.margin as EdgeInsets : EdgeInsets.zero;
return margin ?? EdgeInsets.zero;
}
}

View File

@@ -1,5 +1,3 @@
import 'package:countdown/countdown.dart';
import 'package:flutter/material.dart';
import 'package:pinput/pin_put/pin_put.dart';
@@ -7,17 +5,17 @@ import '../../generated/l10n.dart';
import '../../models/user.dart';
import '../../utils/http_util.dart';
import '../../utils/utils.dart';
import '../../vendor/countdown/src/countdown_base.dart';
typedef OnCodeVerified();
typedef OnCancel();
class PaymentVerificationCodeDialog extends StatefulWidget {
final Key key;
final User user;
final OnCodeVerified onCodeVerified;
final OnCancel onCancel;
const PaymentVerificationCodeDialog(this.user, this.onCodeVerified, this.onCancel, {this.key});
const PaymentVerificationCodeDialog(this.user, this.onCodeVerified, this.onCancel, {Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() {
@@ -33,8 +31,8 @@ class PaymentVerificationCodeDialogState extends State<PaymentVerificationCodeDi
String getCodeText = '';
String paymentCodeEncrypt = '';
String verifyMethod;
String verifyName;
String verifyMethod = '';
String verifyName = '';
final TextEditingController _pinPutController = TextEditingController();
final FocusNode _pinPutFocusNode = FocusNode();
@@ -115,7 +113,7 @@ class PaymentVerificationCodeDialogState extends State<PaymentVerificationCodeDi
followingFieldDecoration: _pinPutDecoration.copyWith(
borderRadius: BorderRadius.circular(5),
border: Border.all(
color: Colors.deepPurpleAccent.withOpacity(.5),
color: Colors.deepPurpleAccent.withAlpha(50),
),
),
),

View File

@@ -10,15 +10,15 @@ class PopupAnimationWidget extends AnimatedWidget {
final Animation<double> animation;
PopupAnimationWidget({
@required this.animation,
@required this.stackKey,
@required this.startKey,
@required this.child,
required this.animation,
required this.stackKey,
required this.startKey,
required this.child,
this.color = Colors.yellow,
this.popupOffset = Offset.zero,
}) : super(listenable: animation);
Offset _startOffset;
Offset _startOffset = Offset.zero;
Offset _offset = Offset.zero;
@override
@@ -49,11 +49,11 @@ class PopupAnimationWidget extends AnimatedWidget {
void _calAnimation() {
if (_startOffset == null) {
final RenderBox stackBox = stackKey.currentContext.findRenderObject();
final RenderBox stackBox = stackKey.currentContext?.findRenderObject() as RenderBox;
final Offset stackBoxOffset = stackBox.globalToLocal(Offset.zero);
final EdgeInsets startMargin = _margin(startKey);
final RenderBox startBox = startKey.currentContext.findRenderObject();
final RenderBox startBox = startKey.currentContext?.findRenderObject() as RenderBox;
_startOffset = startBox.localToGlobal(Offset(
startMargin.left + popupOffset.dx,
@@ -62,9 +62,9 @@ class PopupAnimationWidget extends AnimatedWidget {
}
EdgeInsets _margin(GlobalKey key) {
final Widget widget = key.currentContext.widget;
final Widget widget = key.currentContext!.widget;
final EdgeInsets margin =
(widget is Container) ? widget.margin : EdgeInsets.zero;
(widget is Container) ? widget.margin as EdgeInsets : EdgeInsets.zero;
return margin ?? EdgeInsets.zero;
}
}

View File

@@ -9,7 +9,7 @@ enum TrimMode {
class ReadMoreText extends StatefulWidget {
const ReadMoreText(
this.data, {
Key key,
Key? key,
this.trimExpandedText = ' read less',
this.trimCollapsedText = ' ...read more',
this.colorClickableText,
@@ -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();
@@ -57,8 +57,8 @@ class ReadMoreTextState extends State<ReadMoreText> {
@override
Widget build(BuildContext context) {
final DefaultTextStyle defaultTextStyle = DefaultTextStyle.of(context);
TextStyle effectiveTextStyle = widget.style;
if (widget.style == null || widget.style.inherit) {
TextStyle? effectiveTextStyle = widget.style;
if (widget.style == null || widget.style!.inherit) {
effectiveTextStyle = defaultTextStyle.style.merge(widget.style);
}
@@ -66,7 +66,7 @@ class ReadMoreTextState extends State<ReadMoreText> {
widget.textAlign ?? defaultTextStyle.textAlign ?? TextAlign.start;
final textDirection = widget.textDirection ?? Directionality.of(context);
final textScaleFactor =
widget.textScaleFactor ?? MediaQuery.textScaleFactorOf(context);
widget.textScaleFactor ?? MediaQuery.textScalerOf(context).scale(1);
final overflow = defaultTextStyle.overflow;
final locale =
widget.locale ?? Localizations.localeOf(context);
@@ -76,7 +76,7 @@ class ReadMoreTextState extends State<ReadMoreText> {
TextSpan link = TextSpan(
text: _readMore ? widget.trimCollapsedText : widget.trimExpandedText,
style: effectiveTextStyle.copyWith(
style: effectiveTextStyle?.copyWith(
color: colorClickableText,
),
recognizer: TapGestureRecognizer()..onTap = _onTapLink,
@@ -98,7 +98,7 @@ class ReadMoreTextState extends State<ReadMoreText> {
text: link,
textAlign: textAlign,
textDirection: textDirection,
textScaleFactor: textScaleFactor,
textScaler: TextScaler.linear(textScaleFactor),
maxLines: widget.trimLines,
ellipsis: overflow == TextOverflow.ellipsis ? _kEllipsis : null,
locale: locale,
@@ -115,7 +115,7 @@ class ReadMoreTextState extends State<ReadMoreText> {
// Get the endIndex of data
bool linkLongerThanLine = false;
int endIndex;
int? endIndex;
if (linkSize.width < maxWidth) {
final pos = textPainter.getPositionForOffset(Offset(

View File

@@ -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;
@@ -36,7 +36,7 @@ class ShowPrice extends StatelessWidget {
Container(
padding: EdgeInsets.only(top: largeFontSize / 10.0),
child: Text(
currencySign,
currencySign!,
style: TextStyle(
fontSize: smallFontSize,
color: color,
@@ -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,

View File

@@ -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> 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,
@@ -164,7 +164,7 @@ class SlidingUpPanel extends StatefulWidget {
final PanelState defaultPanelState;
SlidingUpPanel({
Key key,
Key? key,
this.panel,
this.panelBuilder,
this.body,
@@ -211,9 +211,9 @@ class SlidingUpPanel extends StatefulWidget {
class _SlidingUpPanelState extends State<SlidingUpPanel> with SingleTickerProviderStateMixin{
AnimationController _ac;
AnimationController? _ac;
ScrollController _sc;
ScrollController? _sc;
bool _scrollingEnabled = false;
VelocityTracker _vt = VelocityTracker.withKind(PointerDeviceKind.touch);
@@ -228,19 +228,19 @@ class _SlidingUpPanelState extends State<SlidingUpPanel> with SingleTickerProvid
duration: const Duration(milliseconds: 300),
value: widget.defaultPanelState == PanelState.CLOSED ? 0.0 : 1.0 //set the default panel state (i.e. set initial value of _ac)
)..addListener((){
if(widget.onPanelSlide != null) widget.onPanelSlide(_ac.value);
if(widget.onPanelSlide != null) widget.onPanelSlide!(_ac!.value);
if(widget.onPanelOpened != null && _ac.value == 1.0) widget.onPanelOpened();
if(widget.onPanelOpened != null && _ac!.value == 1.0) widget.onPanelOpened!();
if(widget.onPanelClosed != null && _ac.value == 0.0) widget.onPanelClosed();
if(widget.onPanelClosed != null && _ac!.value == 0.0) widget.onPanelClosed!();
});
// prevent the panel content from being scrolled only if the widget is
// draggable and panel scrolling is enabled
_sc = new ScrollController();
_sc.addListener((){
if(widget.isDraggable && !_scrollingEnabled)
_sc.jumpTo(0);
_sc!.addListener((){
if(widget.isDraggable! && !_scrollingEnabled)
_sc!.jumpTo(0);
});
widget.controller?._addState(this);
@@ -254,11 +254,11 @@ class _SlidingUpPanelState extends State<SlidingUpPanel> with SingleTickerProvid
//make the back widget take up the entire back side
widget.body != null ? AnimatedBuilder(
animation: _ac,
animation: _ac!,
builder: (context, child){
return Positioned(
top: widget.parallaxEnabled ? _getParallax() : 0.0,
child: child,
top: widget.parallaxEnabled! ? _getParallax() : 0.0,
child: child!,
);
},
child: Container(
@@ -278,7 +278,7 @@ class _SlidingUpPanelState extends State<SlidingUpPanel> with SingleTickerProvid
} : null,
onTap: widget.backdropTapClosesPanel ? () => _close() : null,
child: AnimatedBuilder(
animation: _ac,
animation: _ac!,
builder: (context, _) {
return Container(
height: MediaQuery.of(context).size.height,
@@ -287,7 +287,7 @@ class _SlidingUpPanelState extends State<SlidingUpPanel> with SingleTickerProvid
//set color to null so that touch events pass through
//to the body when the panel is closed, otherwise,
//if a color exists, then touch events won't go through
color: _ac.value == 0.0 ? null : widget.backdropColor.withOpacity(widget.backdropOpacity * _ac.value),
color: _ac!.value == 0.0 ? null : widget.backdropColor.withOpacity(widget.backdropOpacity * _ac!.value),
);
}
),
@@ -296,10 +296,10 @@ class _SlidingUpPanelState extends State<SlidingUpPanel> with SingleTickerProvid
//the actual sliding part
!_isPanelVisible ? Container() : _gestureHandler(
child: AnimatedBuilder(
animation: _ac,
animation: _ac!,
builder: (context, child) {
return Container(
height: _ac.value * (widget.maxHeight - widget.minHeight) + widget.minHeight,
height: _ac!.value * (widget.maxHeight - widget.minHeight) + widget.minHeight,
margin: widget.margin,
padding: widget.padding,
decoration: widget.renderPanelSheet ? BoxDecoration(
@@ -320,13 +320,13 @@ class _SlidingUpPanelState extends State<SlidingUpPanel> 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
? widget.panel
: widget.panelBuilder(_sc),
: widget.panelBuilder!(_sc!),
),
),
@@ -334,14 +334,14 @@ class _SlidingUpPanelState extends State<SlidingUpPanel> with SingleTickerProvid
widget.header != null ? Positioned(
top: widget.slideDirection == SlideDirection.UP ? 0.0 : null,
bottom: widget.slideDirection == SlideDirection.DOWN ? 0.0 : null,
child: widget.header,
child: widget.header!,
) : Container(),
// footer
widget.footer != null ? Positioned(
top: widget.slideDirection == SlideDirection.UP ? null : 0.0,
bottom: widget.slideDirection == SlideDirection.DOWN ? null : 0.0,
child: widget.footer
child: widget.footer!
) : Container(),
// collapsed panel
@@ -349,12 +349,12 @@ class _SlidingUpPanelState extends State<SlidingUpPanel> 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(
opacity: Tween(begin: 1.0, end: 0.0).animate(_ac),
opacity: Tween(begin: 1.0, end: 0.0).animate(_ac!),
// if the panel is open ignore pointers (touch events) on the collapsed
// child so that way touch events go through to whatever is underneath
@@ -375,22 +375,22 @@ class _SlidingUpPanelState extends State<SlidingUpPanel> with SingleTickerProvid
@override
void dispose(){
_ac.dispose();
_ac?.dispose();
super.dispose();
}
double _getParallax(){
if(widget.slideDirection == SlideDirection.UP)
return -_ac.value * (widget.maxHeight - widget.minHeight) * widget.parallaxOffset;
return -_ac!.value * (widget.maxHeight - widget.minHeight) * widget.parallaxOffset;
else
return _ac.value * (widget.maxHeight - widget.minHeight) * widget.parallaxOffset;
return _ac!.value * (widget.maxHeight - widget.minHeight) * widget.parallaxOffset;
}
// returns a gesture detector if panel is used
// and a listener if panelBuilder is used.
// this is because the listener is designed only for use with linking the scrolling of
// panels and using it for panels that don't want to linked scrolling yields odd results
Widget _gestureHandler({Widget child}){
Widget _gestureHandler({required Widget child}){
if (!widget.isDraggable) return child;
if (widget.panel != null){
@@ -418,15 +418,15 @@ class _SlidingUpPanelState extends State<SlidingUpPanel> with SingleTickerProvid
// only slide the panel if scrolling is not enabled
if(!_scrollingEnabled){
if(widget.slideDirection == SlideDirection.UP)
_ac.value -= dy / (widget.maxHeight - widget.minHeight);
_ac!.value -= dy / (widget.maxHeight - widget.minHeight);
else
_ac.value += dy / (widget.maxHeight - widget.minHeight);
_ac!.value += dy / (widget.maxHeight - widget.minHeight);
}
// if the panel is open and the user hasn't scrolled, we need to determine
// whether to enable scrolling if the user swipes up, or disable closing and
// begin to close the panel if the user swipes down
if(_isPanelOpen && _sc.hasClients && _sc.offset <= 0){
if(_isPanelOpen && _sc!.hasClients && _sc!.offset <= 0){
setState(() {
if(dy < 0){
_scrollingEnabled = true;
@@ -443,7 +443,7 @@ class _SlidingUpPanelState extends State<SlidingUpPanel> with SingleTickerProvid
double kSnap = 8;
//let the current animation finish before starting a new one
if(_ac.isAnimating) return;
if(_ac!.isAnimating) return;
// if scrolling is allowed and the panel is open, we don't want to close
// the panel if they swipe up on the scrollable
@@ -458,9 +458,9 @@ class _SlidingUpPanelState extends State<SlidingUpPanel> with SingleTickerProvid
// get minimum distances to figure out where the panel is at
double d2Close = _ac.value;
double d2Open = 1 - _ac.value;
double d2Snap = ((widget.snapPoint ?? 3) -_ac.value).abs(); // large value if null results in not every being the min
double d2Close = _ac!.value;
double d2Open = 1 - _ac!.value;
double d2Snap = ((widget.snapPoint ?? 3) -_ac!.value).abs(); // large value if null results in not every being the min
double minDistance = min(d2Close, min(d2Snap, d2Open));
// check if velocity is sufficient for a fling
@@ -469,18 +469,18 @@ class _SlidingUpPanelState extends State<SlidingUpPanel> with SingleTickerProvid
// snapPoint exists
if(widget.panelSnapping && widget.snapPoint != null){
if(v.pixelsPerSecond.dy.abs() >= kSnap*minFlingVelocity || minDistance == d2Snap)
_ac.fling(velocity: visualVelocity);
_ac!.fling(velocity: visualVelocity);
else
_flingPanelToPosition(widget.snapPoint, visualVelocity);
_flingPanelToPosition(widget.snapPoint!, visualVelocity);
// no snap point exists
}else if(widget.panelSnapping){
_ac.fling(velocity: visualVelocity);
_ac!.fling(velocity: visualVelocity);
// panel snapping disabled
}else{
_ac.animateTo(
_ac.value + visualVelocity * 0.16,
_ac!.animateTo(
_ac!.value + visualVelocity * 0.16,
duration: Duration(milliseconds: 410),
curve: Curves.decelerate,
);
@@ -495,7 +495,7 @@ class _SlidingUpPanelState extends State<SlidingUpPanel> with SingleTickerProvid
if(minDistance == d2Close){
_close();
}else if(minDistance == d2Snap){
_flingPanelToPosition(widget.snapPoint, visualVelocity);
_flingPanelToPosition(widget.snapPoint!, visualVelocity);
}else{
_open();
}
@@ -510,12 +510,12 @@ class _SlidingUpPanelState extends State<SlidingUpPanel> with SingleTickerProvid
stiffness: 500.0,
ratio: 1.0,
),
_ac.value,
_ac!.value,
targetPos,
velocity
);
_ac.animateWith(simulation);
_ac!.animateWith(simulation);
}
//---------------------------------
@@ -524,17 +524,17 @@ class _SlidingUpPanelState extends State<SlidingUpPanel> with SingleTickerProvid
//close the panel
Future<void> _close(){
return _ac.fling(velocity: -1.0);
return _ac!.fling(velocity: -1.0);
}
//open the panel
Future<void> _open(){
return _ac.fling(velocity: 1.0);
return _ac!.fling(velocity: 1.0);
}
//hide the panel (completely offscreen)
Future<void> _hide(){
return _ac.fling(velocity: -1.0).then((x){
return _ac!.fling(velocity: -1.0).then((x){
setState(() {
_isPanelVisible = false;
});
@@ -543,7 +543,7 @@ class _SlidingUpPanelState extends State<SlidingUpPanel> with SingleTickerProvid
//show the panel (in collapsed mode)
Future<void> _show(){
return _ac.fling(velocity: -1.0).then((x){
return _ac!.fling(velocity: -1.0).then((x){
setState(() {
_isPanelVisible = true;
});
@@ -552,41 +552,41 @@ class _SlidingUpPanelState extends State<SlidingUpPanel> with SingleTickerProvid
//animate the panel position to value - must
//be between 0.0 and 1.0
Future<void> _animatePanelToPosition(double value, {Duration duration, Curve curve = Curves.linear}){
Future<void> _animatePanelToPosition(double value, {required Duration duration, Curve curve = Curves.linear}){
assert(0.0 <= value && value <= 1.0);
return _ac.animateTo(value, duration: duration, curve: curve);
return _ac!.animateTo(value, duration: duration, curve: curve);
}
//animate the panel position to the snap point
//REQUIRES that widget.snapPoint != null
Future<void> _animatePanelToSnapPoint({Duration duration, Curve curve = Curves.linear}){
Future<void> _animatePanelToSnapPoint({required Duration duration, Curve curve = Curves.linear}){
assert(widget.snapPoint != null);
return _ac.animateTo(widget.snapPoint, duration: duration, curve: curve);
return _ac!.animateTo(widget.snapPoint!, duration: duration, curve: curve);
}
//set the panel position to value - must
//be between 0.0 and 1.0
set _panelPosition(double value){
assert(0.0 <= value && value <= 1.0);
_ac.value = value;
_ac!.value = value;
}
//get the current panel position
//returns the % offset from collapsed state
//as a decimal between 0.0 and 1.0
double get _panelPosition => _ac.value;
double get _panelPosition => _ac!.value;
//returns whether or not
//the panel is still animating
bool get _isPanelAnimating => _ac.isAnimating;
bool get _isPanelAnimating => _ac!.isAnimating;
//returns whether or not the
//panel is open
bool get _isPanelOpen => _ac.value == 1.0;
bool get _isPanelOpen => _ac!.value == 1.0;
//returns whether or not the
//panel is closed
bool get _isPanelClosed => _ac.value == 0.0;
bool get _isPanelClosed => _ac!.value == 0.0;
//returns whether or not the
//panel is shown/hidden
@@ -602,7 +602,7 @@ class _SlidingUpPanelState extends State<SlidingUpPanel> with SingleTickerProvid
class PanelController{
_SlidingUpPanelState _panelState;
_SlidingUpPanelState? _panelState;
void _addState(_SlidingUpPanelState panelState){
this._panelState = panelState;
@@ -616,27 +616,27 @@ class PanelController{
/// Closes the sliding panel to its collapsed state (i.e. to the minHeight)
Future<void> close(){
assert(isAttached, "PanelController must be attached to a SlidingUpPanel");
return _panelState._close();
return _panelState!._close();
}
/// Opens the sliding panel fully
/// (i.e. to the maxHeight)
Future<void> open(){
assert(isAttached, "PanelController must be attached to a SlidingUpPanel");
return _panelState._open();
return _panelState!._open();
}
/// Hides the sliding panel (i.e. is invisible)
Future<void> hide(){
assert(isAttached, "PanelController must be attached to a SlidingUpPanel");
return _panelState._hide();
return _panelState!._hide();
}
/// Shows the sliding panel in its collapsed state
/// (i.e. "un-hide" the sliding panel)
Future<void> show(){
assert(isAttached, "PanelController must be attached to a SlidingUpPanel");
return _panelState._show();
return _panelState!._show();
}
/// Animates the panel position to the value.
@@ -644,20 +644,20 @@ class PanelController{
/// where 0.0 is fully collapsed and 1.0 is completely open.
/// (optional) duration specifies the time for the animation to complete
/// (optional) curve specifies the easing behavior of the animation.
Future<void> animatePanelToPosition(double value, {Duration duration, Curve curve = Curves.linear}){
Future<void> animatePanelToPosition(double value, {required Duration duration, Curve curve = Curves.linear}){
assert(isAttached, "PanelController must be attached to a SlidingUpPanel");
assert(0.0 <= value && value <= 1.0);
return _panelState._animatePanelToPosition(value, duration: duration, curve: curve);
return _panelState!._animatePanelToPosition(value, duration: duration, curve: curve);
}
/// Animates the panel position to the snap point
/// Requires that the SlidingUpPanel snapPoint property is not null
/// (optional) duration specifies the time for the animation to complete
/// (optional) curve specifies the easing behavior of the animation.
Future<void> animatePanelToSnapPoint({Duration duration, Curve curve = Curves.linear}){
Future<void> animatePanelToSnapPoint({required Duration duration, Curve curve = Curves.linear}){
assert(isAttached, "PanelController must be attached to a SlidingUpPanel");
assert(_panelState.widget.snapPoint != null, "SlidingUpPanel snapPoint property must not be null");
return _panelState._animatePanelToSnapPoint(duration: duration, curve: curve);
assert(_panelState!.widget.snapPoint != null, "SlidingUpPanel snapPoint property must not be null");
return _panelState!._animatePanelToSnapPoint(duration: duration, curve: curve);
}
/// Sets the panel position (without animation).
@@ -666,7 +666,7 @@ class PanelController{
set panelPosition(double value){
assert(isAttached, "PanelController must be attached to a SlidingUpPanel");
assert(0.0 <= value && value <= 1.0);
_panelState._panelPosition = value;
_panelState!._panelPosition = value;
}
/// Gets the current panel position.
@@ -677,35 +677,35 @@ class PanelController{
/// 1.0 is full open.
double get panelPosition{
assert(isAttached, "PanelController must be attached to a SlidingUpPanel");
return _panelState._panelPosition;
return _panelState!._panelPosition;
}
/// Returns whether or not the panel is
/// currently animating.
bool get isPanelAnimating{
assert(isAttached, "PanelController must be attached to a SlidingUpPanel");
return _panelState._isPanelAnimating;
return _panelState!._isPanelAnimating;
}
/// Returns whether or not the
/// panel is open.
bool get isPanelOpen{
assert(isAttached, "PanelController must be attached to a SlidingUpPanel");
return _panelState._isPanelOpen;
return _panelState!._isPanelOpen;
}
/// Returns whether or not the
/// panel is closed.
bool get isPanelClosed{
assert(isAttached, "PanelController must be attached to a SlidingUpPanel");
return _panelState._isPanelClosed;
return _panelState!._isPanelClosed;
}
/// Returns whether or not the
/// panel is shown/hidden.
bool get isPanelShown{
assert(isAttached, "PanelController must be attached to a SlidingUpPanel");
return _panelState._isPanelShown;
return _panelState!._isPanelShown;
}
}

View File

@@ -16,11 +16,10 @@ import '../../utils/utils.dart';
class StripePay extends StatefulWidget {
final Key key;
final Order order;
final PaymentPlatform paymentPlatform;
final StripePaymentMethod stripePaymentMethod;
const StripePay(this.order, this.paymentPlatform, {this.key, this.stripePaymentMethod});
final StripePaymentMethod? stripePaymentMethod;
const StripePay(this.order, this.paymentPlatform, {Key? key, this.stripePaymentMethod}) : super(key: key);
@override
State<StatefulWidget> createState() {
@@ -33,7 +32,7 @@ class StripePayState extends State<StripePay> {
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey();
bool isSubmitting;
bool isSubmitting = false;
@override
Widget build(BuildContext context) {
@@ -71,9 +70,9 @@ class StripePayState extends State<StripePay> {
}
_paymentWithPaymentMethod(BuildContext context) async {
Utils.stripePaymentIntent(widget.order, widget.stripePaymentMethod.customerId,
widget.stripePaymentMethod.paymentMethodId,
widget.stripePaymentMethod.paymentMethodType, (response){
Utils.stripePaymentIntent(widget.order, widget.stripePaymentMethod?.customerId,
widget.stripePaymentMethod!.paymentMethodId,
widget.stripePaymentMethod!.paymentMethodType, (response){
if (response.data['status'] == Constants.STRIPE_STATUS_REQUIRES_CONFIRMATION) {
StripePayment.confirmPaymentIntent(
@@ -84,8 +83,8 @@ class StripePayState extends State<StripePay> {
).then((paymentIntentResult) {
if (paymentIntentResult.status == Constants.STRIPE_STATUS_SUCCEDED) {
Utils.stripeChargedSuccess(widget.order,
widget.stripePaymentMethod.paymentMethodId,
paymentIntentResult.paymentIntentId,
widget.stripePaymentMethod!.paymentMethodId,
paymentIntentResult.paymentIntentId!,
(response) {
eventBus.fire(OnOrderUpdated());
Routes.router.navigateTo(context, '/orderdetail/${widget
@@ -107,7 +106,7 @@ class StripePayState extends State<StripePay> {
StripePayment.paymentRequestWithCardForm(
CardFormPaymentRequest()
).then((paymentMethod) {
Utils.stripePaymentIntent(widget.order, null, paymentMethod.id, paymentMethod.type, (response){
Utils.stripePaymentIntent(widget.order, null, paymentMethod.id!, paymentMethod.type!, (response){
if (response.data['status'] == Constants.STRIPE_STATUS_REQUIRES_CONFIRMATION) {
StripePayment.confirmPaymentIntent(
@@ -118,8 +117,8 @@ class StripePayState extends State<StripePay> {
).then((paymentIntentResult) {
if (paymentIntentResult.status == Constants.STRIPE_STATUS_SUCCEDED) {
Utils.stripeChargedSuccess(widget.order,
paymentMethod.id,
paymentIntentResult.paymentIntentId,
paymentMethod.id!,
paymentIntentResult.paymentIntentId!,
(response) {
eventBus.fire(OnOrderUpdated());
Routes.router.navigateTo(context, '/orderdetail/${widget
@@ -133,12 +132,12 @@ class StripePayState extends State<StripePay> {
}).catchError(showErrorDialog);
}
}, (showErrorDialog),
cardBrand: paymentMethod.card.brand,
cardCountry: paymentMethod.card.country,
cardExpMonth: paymentMethod.card.expMonth,
cardExpYear: paymentMethod.card.expYear,
cardFunding: paymentMethod.card.funding,
cardLast4: paymentMethod.card.last4,
cardBrand: paymentMethod.card!.brand,
cardCountry: paymentMethod.card!.country,
cardExpMonth: paymentMethod.card!.expMonth,
cardExpYear: paymentMethod.card!.expYear,
cardFunding: paymentMethod.card!.funding,
cardLast4: paymentMethod.card!.last4,
);
}).catchError(showErrorDialog);
isSubmitting = true;

View File

@@ -10,26 +10,26 @@ import '../../routes.dart';
class TextLink extends StatelessWidget {
final String title;
final String url;
final Color color;
final Color hoverColor;
final double paddingHorizontal;
final double paddingVertical;
final FontWeight fontWeight;
final bool selected;
final bool isLink;
final bool replace;
final bool clearStack;
final bool maintainState;
final bool rootNavigator;
final TransitionType transition;
final bool closeDrawer;
final bool isEmail;
final bool isPhone;
final double fontSize;
final bool isAddress;
final TextOverflow overflow;
final int maxLines;
final String? url;
final Color? color;
final Color? hoverColor;
final double? paddingHorizontal;
final double? paddingVertical;
final FontWeight? fontWeight;
final bool? selected;
final bool? isLink;
final bool? replace;
final bool? clearStack;
final bool? maintainState;
final bool? rootNavigator;
final TransitionType? transition;
final bool? closeDrawer;
final bool? isEmail;
final bool? isPhone;
final double? fontSize;
final bool? isAddress;
final TextOverflow? overflow;
final int? maxLines;
TextLink(this.title, this.url, {
this.color,
@@ -38,19 +38,19 @@ class TextLink extends StatelessWidget {
this.paddingVertical,
this.fontWeight,
this.selected,
bool isLink,
bool replace,
bool clearStack,
bool maintainState,
bool rootNavigator,
bool? isLink,
bool? replace,
bool? clearStack,
bool? maintainState,
bool? rootNavigator,
this.transition,
bool closeDrawer,
bool isEmail,
bool isPhone,
double fontSize,
bool isAddress,
TextOverflow overflow,
int maxLines,
bool? closeDrawer,
bool? isEmail,
bool? isPhone,
double? fontSize,
bool? isAddress,
TextOverflow? overflow,
int? maxLines,
}) :
isLink = isLink ?? false,
replace = replace ?? false,
@@ -101,7 +101,7 @@ class TextLink extends StatelessWidget {
},
),
decoration: BoxDecoration(
border: (selected != null && selected) ? Border(
border: (selected != null && selected!) ? Border(
bottom: BorderSide(
color: color ?? Colors.blue,
width: 3.0,
@@ -110,27 +110,27 @@ class TextLink extends StatelessWidget {
),
),
onTap: () async {
if (selected == null || !selected) {
if (isEmail) {
Utils.openEmail(url);
} else if (isPhone) {
Utils.callPhone(url);
} else if (isAddress) {
await launch('https://maps.google.com/?q=${url}');
} else if (!isLink) {
if (closeDrawer) {
if (selected == null || !selected!) {
if (isEmail!) {
Utils.openEmail(url!);
} else if (isPhone!) {
Utils.callPhone(url!);
} else if (isAddress!) {
await launchUrl(Uri.parse('https://maps.google.com/?q=${url}'));
} else if (!isLink!) {
if (closeDrawer!) {
Routes.router.pop(context);
}
Routes.router.navigateTo(
context, url,
replace: replace,
clearStack: clearStack,
maintainState: maintainState,
rootNavigator: rootNavigator,
context, url!,
replace: replace!,
clearStack: clearStack!,
maintainState: maintainState!,
rootNavigator: rootNavigator!,
);
} else {
if (await canLaunch(url)) {
await launch(url);
if (await canLaunchUrl(Uri.parse(url!))) {
await launchUrl(Uri.parse(url!));
} else {
throw 'Could not launch $url';
}