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

@@ -21,9 +21,9 @@ class DoubleBackToCloseApp extends StatefulWidget {
/// Creates a widget that allows the user to close the app by double tapping
/// the back-button.
const DoubleBackToCloseApp({
Key key,
@required this.snackBar,
@required this.child,
Key? key,
required this.snackBar,
required this.child,
}) : assert(snackBar != null),
assert(child != null),
super(key: key);
@@ -34,7 +34,7 @@ class DoubleBackToCloseApp extends StatefulWidget {
class _DoubleBackToCloseAppState extends State<DoubleBackToCloseApp> {
/// The last time the user tapped Android's back-button.
DateTime _lastTimeBackButtonWasTapped;
DateTime? _lastTimeBackButtonWasTapped;
/// Returns whether the current platform is Android.
bool get _isAndroid => Theme.of(context).platform == TargetPlatform.android;
@@ -50,7 +50,7 @@ class _DoubleBackToCloseAppState extends State<DoubleBackToCloseApp> {
bool get _isSnackBarVisible =>
(_lastTimeBackButtonWasTapped != null) &&
(widget.snackBar.duration >
DateTime.now().difference(_lastTimeBackButtonWasTapped));
DateTime.now().difference(_lastTimeBackButtonWasTapped!));
/// Returns whether the next back navigation of this route will be handled
/// internally.
@@ -59,7 +59,7 @@ class _DoubleBackToCloseAppState extends State<DoubleBackToCloseApp> {
/// local-history of the current route, in order to handle pop. This is done
/// by [Drawer], for example, so it can close on pop.
bool get _willHandlePopInternally =>
ModalRoute.of(context).willHandlePopInternally;
ModalRoute.of(context)!.willHandlePopInternally;
@override
Widget build(BuildContext context) {

View File

@@ -2,9 +2,9 @@
import 'package:flutter/material.dart';
class IFrameWeb extends StatefulWidget {
final String width;
final String height;
final String src;
final String? width;
final String? height;
final String? src;
const IFrameWeb({this.width, this.height, this.src});

View File

@@ -7,14 +7,12 @@ import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';
import '../store/store.dart';
import 'utils.dart';
import 'package:hive/hive.dart';
import 'package:universal_io/io.dart';
import '../constants.dart';
typedef void PostCallback(Response response);
String generateSignature(String string, {String key}) {
String generateSignature(String string, {String? key}) {
if (key == null) {
key = Constants.API_SECRET;
}
@@ -37,17 +35,17 @@ class HttpUtil {
'Http-Contact-Authorization': '',
'Http-Device-Type': Utils.getOs(checkWeb: true),
'Http-Api-Branch': 'flutter',
'Http-Language-Code': store.state.locale.languageCode,
'Http-Country-Code': store.state.locale.countryCode,
'Http-Language-Code': (store == null || store.state == null || store.state.locale == null) ? 'en' : store.state.locale!.languageCode,
'Http-Country-Code': (store == null || store.state == null || store.state.locale == null) ? 'US' : store.state.locale!.countryCode!,
};
static Future<dynamic> httpGet(String url,
{
Map<String, dynamic> queryParameters,
Map<String, dynamic>? queryParameters,
int businessId = 0,
Function(int, int) receiveProgress,
Function(int, int)? receiveProgress,
bool returnError = false,
Map<String, String> additionalHeaders,
Map<String, String>? additionalHeaders,
}) async {
Map<String, dynamic> localHeaders = json.decode(json.encode(headers));
if (additionalHeaders != null) {
@@ -59,8 +57,7 @@ class HttpUtil {
}
localHeaders['Http-Business-Id'] = businessId == 0 ? '${Constants.BUSINESS_ID}' : businessId.toString();
Box box = await Utils.getBox();
localHeaders['Http-Contact-Authorization'] = box.get(Constants.KEY_ACCESS_TOKEN, defaultValue: '');
localHeaders['Http-Contact-Authorization'] = Utils.prefs?.getString(Constants.KEY_ACCESS_TOKEN) ?? '';
localHeaders['Http-App-Key'] = platformName;
localHeaders['Http-Device-Type'] = platformName;
String requestUrl = Constants.BASE_API_URL + url;
@@ -69,7 +66,9 @@ class HttpUtil {
requestUrl = url;
}
Utils.jsonPrettyPrint(queryParameters);
if (queryParameters != null) {
Utils.jsonPrettyPrint(queryParameters!);
}
Dio dio = Dio();
try {
@@ -84,9 +83,9 @@ class HttpUtil {
// print('response data: ${response.data}');
// Utils.jsonPrettyPrint(response.data);
int statusCode = response.statusCode;
int statusCode = response.statusCode!;
return response.data;
} on DioError catch(e) {
} on DioException catch(e) {
print('HttpGet failed, request: $requestUrl, headers: $localHeaders, error ${e.response}');
if (returnError) {
return e;
@@ -95,16 +94,16 @@ class HttpUtil {
}
}
static Future<dynamic> httpPost(String url, PostCallback callback,
static Future<dynamic> httpPost(String url, PostCallback? callback,
{
Map<String, dynamic> queryParameters,
Map<String, dynamic>? queryParameters,
int businessId = 0,
bool isFormData = false,
Map<String, String> additionalHeaders,
Map<String, dynamic> body,
FormData formData,
Function(int, int) sendProgress,
Function(int, int) receiveProgress,
Map<String, String>? additionalHeaders,
Map<String, dynamic>? body,
FormData? formData,
Function(int, int)? sendProgress,
Function(int, int)? receiveProgress,
bool returnError = false,
}) async {
@@ -116,8 +115,7 @@ class HttpUtil {
localHeaders['Http-Signature'] = generateSignature(url);
}
localHeaders['Http-Business-Id'] = businessId == 0 ? '${Constants.BUSINESS_ID}' : businessId.toString();
Box box = await Utils.getBox();
localHeaders['Http-Contact-Authorization'] = box.get(Constants.KEY_ACCESS_TOKEN, defaultValue: '');
localHeaders['Http-Contact-Authorization'] = Utils.prefs?.getString(Constants.KEY_ACCESS_TOKEN) ?? '';
localHeaders['Http-App-Key'] = platformName;
localHeaders['Http-Device-Type'] = platformName;
@@ -138,7 +136,7 @@ class HttpUtil {
Response response = await dio.post(
requestUrl,
queryParameters: queryParameters == null ? {} : queryParameters,
data: isFormData ? ((formData != null)?formData:FormData.fromMap(body)) : json.encode(body),
data: isFormData ? ((formData != null)?formData:FormData.fromMap(body!)) : json.encode(body),
options: Options(
headers: localHeaders,
contentType: isFormData ? Headers.formUrlEncodedContentType : Headers.jsonContentType,
@@ -149,17 +147,17 @@ class HttpUtil {
// Utils.jsonPrettyPrint(response.data);
int statusCode = response.statusCode;
int statusCode = response.statusCode!;
if (callback != null) {
callback(response);
}
return response.data;
} on DioError catch(e, stacktrace) {
} on DioException catch(e, stacktrace) {
if (e.response != null) {
try {
Utils.jsonPrettyPrint(e.response.data);
Utils.jsonPrettyPrint(e.response?.data);
} catch (err) {
print(e.response.data);
print(e.response?.data);
}
}
if (returnError) {
@@ -169,14 +167,14 @@ class HttpUtil {
}
}
static Future<dynamic> httpPut(String url, PostCallback callback,
static Future<dynamic> httpPut(String url, PostCallback? callback,
{
Map<String, dynamic> queryParameters,
Map<String, dynamic>? queryParameters,
int businessId = 0,
Map<String, String> additionalHeaders,
Map<String, dynamic> body,
Function(int, int) sendProgress,
Function(int, int) receiveProgress,
Map<String, String>? additionalHeaders,
Map<String, dynamic>? body,
Function(int, int)? sendProgress,
Function(int, int)? receiveProgress,
bool returnError = false,
}) async {
@@ -190,8 +188,7 @@ class HttpUtil {
}
localHeaders['Http-Business-Id'] = businessId == 0 ? '${Constants.BUSINESS_ID}' : businessId.toString();
Box box = await Utils.getBox();
localHeaders['Http-Contact-Authorization'] = box.get(Constants.KEY_ACCESS_TOKEN, defaultValue: '');
localHeaders['Http-Contact-Authorization'] = Utils.prefs?.getString(Constants.KEY_ACCESS_TOKEN) ?? '';
localHeaders['Http-App-Key'] = platformName;
localHeaders['Http-Device-Type'] = platformName;
@@ -218,14 +215,14 @@ class HttpUtil {
// Utils.jsonPrettyPrint(response.data);
int statusCode = response.statusCode;
int statusCode = response.statusCode!;
if (callback != null) {
callback(response);
}
return response.data;
} on DioError catch(e) {
} on DioException catch(e) {
if (e.response != null) {
Utils.jsonPrettyPrint(e.response.data);
Utils.jsonPrettyPrint(e.response!.data);
}
if (returnError) {
return e;
@@ -234,14 +231,14 @@ class HttpUtil {
}
}
static Future<dynamic> httpPatch(String url, PostCallback callback,
static Future<dynamic> httpPatch(String url, PostCallback? callback,
{
Map<String, dynamic> queryParameters,
Map<String, dynamic>? queryParameters,
int businessId = 0,
Map<String, String> additionalHeaders,
Map<String, dynamic> body,
Function(int, int) sendProgress,
Function(int, int) receiveProgress,
Map<String, String>? additionalHeaders,
Map<String, dynamic>? body,
Function(int, int)? sendProgress,
Function(int, int)? receiveProgress,
bool returnError = false,
}) async {
@@ -255,8 +252,7 @@ class HttpUtil {
}
localHeaders['Http-Business-Id'] = businessId == 0 ? '${Constants.BUSINESS_ID}' : businessId.toString();
Box box = await Utils.getBox();
localHeaders['Http-Contact-Authorization'] = box.get(Constants.KEY_ACCESS_TOKEN, defaultValue: '');
localHeaders['Http-Contact-Authorization'] = Utils.prefs?.getString(Constants.KEY_ACCESS_TOKEN) ?? '';
localHeaders['Http-App-Key'] = platformName;
localHeaders['Http-Device-Type'] = platformName;
@@ -268,7 +264,9 @@ class HttpUtil {
requestUrl = url;
}
Utils.jsonPrettyPrint(body);
if (body != null) {
Utils.jsonPrettyPrint(body!);
}
Dio dio = Dio();
try {
@@ -285,14 +283,14 @@ class HttpUtil {
// Utils.jsonPrettyPrint(response.data);
int statusCode = response.statusCode;
int statusCode = response.statusCode!;
if (callback != null) {
callback(response);
}
return response.data;
} on DioError catch(e) {
} on DioException catch(e) {
if (e.response != null) {
Utils.jsonPrettyPrint(e.response.data);
Utils.jsonPrettyPrint(e.response!.data);
}
if (returnError) {
return e;
@@ -301,12 +299,12 @@ class HttpUtil {
}
}
static Future<dynamic> httpDelete(String url, PostCallback callback,
static Future<dynamic> httpDelete(String url, PostCallback? callback,
{
Map<String, dynamic> queryParameters,
Map<String, dynamic>? queryParameters,
int businessId = 0,
Map<String, String> additionalHeaders,
Map<String, dynamic> body,
Map<String, String>? additionalHeaders,
Map<String, dynamic>? body,
bool returnError = false,
}) async {
@@ -320,8 +318,7 @@ class HttpUtil {
}
localHeaders['Http-Business-Id'] = businessId == 0 ? '${Constants.BUSINESS_ID}' : businessId.toString();
Box box = await Utils.getBox();
localHeaders['Http-Contact-Authorization'] = box.get(Constants.KEY_ACCESS_TOKEN, defaultValue: '');
localHeaders['Http-Contact-Authorization'] = Utils.prefs?.getString(Constants.KEY_ACCESS_TOKEN) ?? '';
localHeaders['Http-App-Key'] = platformName;
localHeaders['Http-Device-Type'] = platformName;
@@ -333,7 +330,9 @@ class HttpUtil {
requestUrl = url;
}
Utils.jsonPrettyPrint(body);
if (body != null) {
Utils.jsonPrettyPrint(body);
}
Dio dio = Dio();
try {
@@ -348,14 +347,14 @@ class HttpUtil {
// Utils.jsonPrettyPrint(response.data);
int statusCode = response.statusCode;
int statusCode = response.statusCode!;
if (callback != null) {
callback(response);
}
return response.data;
} on DioError catch(e) {
} on DioException catch(e) {
if (e.response != null) {
Utils.jsonPrettyPrint(e.response.data);
Utils.jsonPrettyPrint(e.response!.data);
}
if(returnError) {
return e;

View File

@@ -14,7 +14,7 @@ class ShopScrollController extends ScrollController {
this.coordinator, {
double initialScrollOffset = 0.0,
this.keepScrollOffset = true,
this.debugLabel,
required this.debugLabel,
}) : assert(initialScrollOffset != null),
assert(keepScrollOffset != null),
_initialScrollOffset = initialScrollOffset;
@@ -61,7 +61,7 @@ class ShopScrollController extends ScrollController {
'ScrollController not attached to any scroll views.');
assert(_positions.length == 1,
'ScrollController attached to multiple scroll views.');
return _positions.single;
return _positions.single as ShopScrollPosition;
}
/// 可滚动小部件的当前滚动偏移量
@@ -83,12 +83,12 @@ class ShopScrollController extends ScrollController {
/// 持续时间不能为零。 要在没有动画的情况下跳至特定值,请使用[jumpTo]。
Future<void> animateTo(
double offset, {
@required Duration duration,
@required Curve curve,
required Duration duration,
required Curve curve,
}) {
assert(_positions.isNotEmpty,
'ScrollController not attached to any scroll views.');
final List<Future<void>> animations = List<Future<void>>(_positions.length);
final List<Future<void>> animations = List<Future<void>>.filled(_positions.length, Future<void>.value());
for (int i = 0; i < _positions.length; i += 1)
animations[i] =
_positions[i].animateTo(offset, duration: duration, curve: curve);
@@ -149,7 +149,7 @@ class ShopScrollController extends ScrollController {
/// 则它将是前一个实例。 当环境已更改并且[Scrollable]需要重新创建[ScrollPosition]
/// 对象时,将使用此方法。 第一次创建[ScrollPosition]时为null。
ScrollPosition createScrollPosition(ScrollPhysics physics,
ScrollContext context, ScrollPosition oldPosition) {
ScrollContext context, ScrollPosition? oldPosition) {
return ShopScrollPosition(
coordinator: coordinator,
physics: physics,

View File

@@ -12,15 +12,15 @@ class ShopScrollCoordinator {
/// 页面主 CustomScrollView 控制
final String pageLabel = "page";
ShopScrollController _pageScrollController;
double Function() pinnedHeaderSliverHeightBuilder;
ShopScrollController? _pageScrollController;
double Function()? pinnedHeaderSliverHeightBuilder;
ShopScrollPosition get _pageScrollPosition => _pageScrollController.position;
ShopScrollPosition get _pageScrollPosition => _pageScrollController!.position;
ScrollDragController scrollDragController;
ScrollDragController? scrollDragController;
/// 主页面滑动部件默认位置
double _pageInitialOffset;
double? _pageInitialOffset;
/// 获取主页面滑动控制器
ShopScrollController pageScrollController([double initialOffset = 0.0]) {
@@ -28,27 +28,27 @@ class ShopScrollCoordinator {
_pageInitialOffset = initialOffset;
_pageScrollController = ShopScrollController(this,
debugLabel: pageLabel, initialScrollOffset: initialOffset);
return _pageScrollController;
return _pageScrollController!;
}
/// 创建并获取一个子滑动控制器
ShopScrollController newChildScrollController([String debugLabel]) =>
ShopScrollController(this, debugLabel: debugLabel);
ShopScrollController newChildScrollController([String? debugLabel]) =>
ShopScrollController(this, debugLabel: debugLabel ?? '');
/// 子部件滑动数据协调
/// [userScrollDirection]用户滑动方向
/// [position]被滑动的子部件的位置信息
void applyUserOffset(double delta,
[ScrollDirection userScrollDirection, ShopScrollPosition position]) {
[ScrollDirection? userScrollDirection, ShopScrollPosition? position]) {
if (userScrollDirection == ScrollDirection.reverse) {
updateUserScrollDirection(_pageScrollPosition, userScrollDirection);
updateUserScrollDirection(_pageScrollPosition, userScrollDirection!);
final innerDelta = _pageScrollPosition.applyClampedDragUpdate(delta);
if (innerDelta != 0.0) {
updateUserScrollDirection(position, userScrollDirection);
updateUserScrollDirection(position!, userScrollDirection);
position.applyFullDragUpdate(innerDelta);
}
} else {
updateUserScrollDirection(position, userScrollDirection);
updateUserScrollDirection(position!, userScrollDirection!);
final outerDelta = position.applyClampedDragUpdate(delta);
if (outerDelta != 0.0) {
updateUserScrollDirection(_pageScrollPosition, userScrollDirection);
@@ -60,7 +60,7 @@ class ShopScrollCoordinator {
bool applyContentDimensions(double minScrollExtent, double maxScrollExtent,
ShopScrollPosition position) {
if (pinnedHeaderSliverHeightBuilder != null) {
maxScrollExtent = maxScrollExtent - pinnedHeaderSliverHeightBuilder();
maxScrollExtent = maxScrollExtent - pinnedHeaderSliverHeightBuilder!();
maxScrollExtent = math.max(0.0, maxScrollExtent);
}
return position.applyContentDimensions(
@@ -77,9 +77,9 @@ class ShopScrollCoordinator {
/// 当手指离开屏幕
void onPointerUp(PointerUpEvent event) {
final double _pagePixels = _pageScrollPosition.pixels;
if (0.0 < _pagePixels && _pagePixels < _pageInitialOffset) {
if (0.0 < _pagePixels && _pagePixels < _pageInitialOffset!) {
if (pageExpand == PageExpandState.NotExpand &&
_pageInitialOffset - _pagePixels > _scrollRedundancy) {
_pageInitialOffset! - _pagePixels > _scrollRedundancy) {
_pageScrollPosition
.animateTo(0.0,
duration: const Duration(milliseconds: 400), curve: Curves.ease)
@@ -87,7 +87,7 @@ class ShopScrollCoordinator {
} else {
pageExpand = PageExpandState.Expanding;
_pageScrollPosition
.animateTo(_pageInitialOffset,
.animateTo(_pageInitialOffset!,
duration: const Duration(milliseconds: 400), curve: Curves.ease)
.then((value) => pageExpand = PageExpandState.NotExpand);
}

View File

@@ -11,17 +11,17 @@ import 'shop_scroll_coordinator.dart';
class ShopScrollPosition extends ScrollPosition
implements ScrollActivityDelegate {
final ShopScrollCoordinator coordinator; // 协调器
ScrollDragController _currentDrag;
ScrollDragController? _currentDrag;
double _heldPreviousVelocity = 0.0;
ShopScrollPosition(
{@required ScrollPhysics physics,
@required ScrollContext context,
{required ScrollPhysics physics,
required ScrollContext context,
double initialPixels = 0.0,
bool keepScrollOffset = true,
ScrollPosition oldPosition,
String debugLabel,
@required this.coordinator})
ScrollPosition? oldPosition,
String? debugLabel,
required this.coordinator})
: super(
physics: physics,
context: context,
@@ -40,7 +40,7 @@ class ShopScrollPosition extends ScrollPosition
@override
double setPixels(double newPixels) {
assert(activity.isScrolling);
assert(activity!.isScrolling);
return super.setPixels(newPixels);
}
@@ -51,13 +51,13 @@ class ShopScrollPosition extends ScrollPosition
goIdle();
return;
}
activity.updateDelegate(this);
activity!.updateDelegate(this);
final ShopScrollPosition typedOther = other as ShopScrollPosition;
_userScrollDirection = typedOther._userScrollDirection;
assert(_currentDrag == null);
if (typedOther._currentDrag != null) {
_currentDrag = typedOther._currentDrag;
_currentDrag.updateDelegate(this);
_currentDrag?.updateDelegate(this);
typedOther._currentDrag = null;
}
}
@@ -131,14 +131,14 @@ class ShopScrollPosition extends ScrollPosition
}
@override
void beginActivity(ScrollActivity newActivity) {
void beginActivity(ScrollActivity? newActivity) {
_heldPreviousVelocity = 0.0;
if (newActivity == null) return;
assert(newActivity.delegate == this);
super.beginActivity(newActivity);
_currentDrag?.dispose();
_currentDrag = null;
if (!activity.isScrolling) updateUserScrollDirection(ScrollDirection.idle);
if (!activity!.isScrolling) updateUserScrollDirection(ScrollDirection.idle);
}
/// 将[用户滚动方向]设置为给定值。
@@ -154,7 +154,7 @@ class ShopScrollPosition extends ScrollPosition
@override
ScrollHoldController hold(VoidCallback holdCancelCallback) {
final double previousVelocity = activity.velocity;
final double previousVelocity = activity!.velocity;
final HoldScrollActivity holdActivity =
HoldScrollActivity(delegate: this, onHoldCanceled: holdCancelCallback);
beginActivity(holdActivity);
@@ -195,10 +195,10 @@ class ShopScrollPosition extends ScrollPosition
if (coordinator.pageExpand == PageExpandState.Expanding) return;
}
assert(pixels != null);
final Simulation simulation =
final Simulation? simulation =
physics.createBallisticSimulation(this, velocity);
if (simulation != null) {
beginActivity(BallisticScrollActivity(this, simulation, context.vsync));
beginActivity(BallisticScrollActivity(this, simulation, context.vsync, true));
} else {
goIdle();
}
@@ -220,8 +220,8 @@ class ShopScrollPosition extends ScrollPosition
@override
Future<void> animateTo(
double to, {
@required Duration duration,
@required Curve curve,
required Duration duration,
required Curve curve,
}) {
if (nearEqual(to, pixels, physics.tolerance.distance)) {
// 跳过动画,直接移到我们已经靠近的位置。

View File

@@ -6,15 +6,11 @@ import 'dart:ui' as ui;
import 'package:cached_network_image/cached_network_image.dart';
import 'package:dio/dio.dart';
// import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:hive/hive.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:stripe_payment/stripe_payment.dart';
import '../constants.dart';
@@ -42,174 +38,17 @@ class Util {
}
Util._internal();
// final FirebaseMessaging firebaseMessaging = FirebaseMessaging();
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = new FlutterLocalNotificationsPlugin();
static bool notificationTapped = false;
init() {
// initLocalNotification();
// initFirebaseMessaging();
// ePmqRwRUTmKuFNfbHA-6zq:APA91bEFEQx1YgJqfx0V0VYo86uRDGjG6SP1SPCAZW4OvQ7gMOeKWDQ47bfuEM00YavtKq7ZGpsWfFL7B3ypm00ZA6crjJJLK_-j_H8bS_dnQbLFwyRcW67IXCs5sRkro71bRZv7L1WM
// eventBus.on<SubscribeToTopic>().listen((event) {
// if (firebaseMessaging != null) {
// firebaseMessaging.subscribeToTopic(event.topic);
// }
// });
// eventBus.on<UnSubscribeToTopic>().listen((event) {
// if (firebaseMessaging != null) {
// firebaseMessaging.unsubscribeFromTopic(event.topic);
// }
// });
}
initLocalNotification() async {
var initializationSettingsAndroid = new AndroidInitializationSettings('ic_launcher');
var initializationSettingsIOS = new IOSInitializationSettings(
onDidReceiveLocalNotification: onDidReceiveLocalNotification);
var initializationSettings = new InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,
);
await flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
}
Future onSelectNotification(String payload, {bool replace=false}) async {
print('payload: $payload');
if (payload != null && payload.isNotEmpty) {
Routes.router.navigateTo(store.state.context, payload, replace: replace);
}
}
// initFirebaseMessaging() {
// if (Platform.isIOS) {
// iosPermission();
// }
// firebaseMessaging.getToken().then((token) {
// print('FCM token: $token');
// store.dispatch(UpdateFcmToken(token));
// });
// firebaseMessaging.configure(
// onMessage: (Map<String, dynamic> message) {
// print('FCM onMessage: $message');
// // eventBus.fire(OnFcmReceived(message));
// showNotificationWithDefaultSound(message);
// return;
// },
// onBackgroundMessage: Platform.isIOS ? null : backgroundMessageHandler,
// onResume: (Map<String, dynamic> message) {
// print('FCM onResume: $message');
// if (Platform.isAndroid) {
// if (message != null && message['data'] != null && message['data']['route'] != null) {
// notificationTapped = true;
// onSelectNotification(message['data']['route']);
// }
// } else {
// if (message != null && message['route'] != null) {
// notificationTapped = true;
// onSelectNotification(message['route']);
// }
// }
// return;
// },
// onLaunch: (Map<String, dynamic> message) {
// print('FCM onLaunch: $message');
// if (Platform.isAndroid) {
// if (message != null && message['data'] != null && message['data']['route'] != null) {
// notificationTapped = true;
// onSelectNotification(message['data']['route'], replace: true);
// }
// } else {
// if (message != null && message['route'] != null) {
// notificationTapped = true;
// onSelectNotification(message['route'], replace: true);
// }
// }
// return;
// },
// );
// }
Future onDidReceiveLocalNotification(int id, String title, String body, String payload) async {
showDialog(
context: store.state.context,
builder: (BuildContext context) => CupertinoAlertDialog(
title: Text(title),
content: Text(body),
actions: [
CupertinoDialogAction(
isDefaultAction: true,
child: Text(S.of(context).ok),
onPressed: () async {
Navigator.of(context, rootNavigator: true).pop();
if (payload != null && payload.isNotEmpty) {
Routes.router.navigateTo(context, payload);
}
},
)
],
),
);
}
Future showNotificationWithDefaultSound(Map<String, dynamic> message) async {
var androidPlatformChannelSpecifics = new AndroidNotificationDetails(
'channelId',
'channelName',
'channelDescription',
importance: Importance.max,
priority: Priority.high,
);
var iOSPlatformChannelSpecifics = new IOSNotificationDetails(presentSound: true, badgeNumber: 1);
var platformChannelSpecifics = new NotificationDetails(
android: androidPlatformChannelSpecifics,
iOS: iOSPlatformChannelSpecifics,
);
await flutterLocalNotificationsPlugin.show(
0,
Platform.isAndroid ? message['notification']['title'] : message['title'],
Platform.isAndroid ? message['notification']['body'] : message['body'],
platformChannelSpecifics,
payload: Platform.isAndroid ? message['data']['route'] : message['route'],
);
}
// iosPermission() {
// firebaseMessaging.requestNotificationPermissions(
// const IosNotificationSettings(
// sound: true,
// badge: true,
// alert: true,
// )
// );
// firebaseMessaging.onIosSettingsRegistered.listen((IosNotificationSettings settings) {
// print('IOS settings registered: $settings');
// });
// }
static Future<dynamic> backgroundMessageHandler(Map<String, dynamic> message) {
print('FCM background message handler: $message');
return Future<void>.value();
}
static Future<Box> getBox() async {
final dir = await getApplicationDocumentsDirectory();
Hive.init(dir.path);
Box box = await Hive.openBox('app_data');
return box;
}
static Widget showImage(String imageUrl, {double width, double height,
BoxFit fit, Widget Function(BuildContext, String, dynamic) errorWidget}) {
if (imageUrl != null && imageUrl.isNotEmpty && imageUrl.startsWith('https:')) {
static Widget showImage(String imageUrl, {double? width, double? height,
BoxFit? fit, Widget Function(BuildContext, String, dynamic)? errorWidget}) {
if (imageUrl.isNotEmpty && imageUrl.startsWith('https:')) {
return CachedNetworkImage(
imageUrl: imageUrl,
width: width,
height: width,
fit: fit,
placeholder: (context, url) => Utils.imageLoadingIndicator(width: width, height: height),
placeholder: (context, url) => Utils.imageLoadingIndicator(width: width ?? 30, height: height ?? 30),
errorWidget: errorWidget != null ? errorWidget : (context, url, error) {
return Image.asset(
'assets/images/not_found.png',
@@ -219,13 +58,13 @@ class Util {
);
},
);
} else if (imageUrl != null && imageUrl.isNotEmpty) {
} else if (imageUrl.isNotEmpty) {
return Image.file(
File(imageUrl),
width: width,
height: height,
fit: fit,
errorBuilder: (BuildContext context, Object object, StackTrace stackTrace) {
errorBuilder: (BuildContext context, Object object, StackTrace? stackTrace) {
return Image.asset(
'assets/images/not_found.png',
width: width,
@@ -319,14 +158,14 @@ class Util {
final picker = ImagePicker();
var image = await picker.pickImage(source: ImageSource.gallery);
Navigator.of(context).pop();
uploadPicture(context, File(image.path), user, commentId: commentId, orderId: orderId);
uploadPicture(context, File(image!.path), user, commentId: commentId, orderId: orderId);
}
void getPictureFromCamera(BuildContext context, User user, {int commentId = -1, int orderId = 0}) async {
final picker = ImagePicker();
var image = await picker.pickImage(source: ImageSource.camera);
Navigator.of(context).pop();
uploadPicture(context, File(image.path), user, commentId: commentId, orderId: orderId);
uploadPicture(context, File(image!.path), user, commentId: commentId, orderId: orderId);
}
void uploadPicture(BuildContext context, File image, User user, {int commentId = -1, int orderId = 0}) async {
@@ -456,18 +295,18 @@ class Util {
ImagePicker picker = ImagePicker();
var image = await picker.pickImage(source: ImageSource.gallery);
Navigator.of(context).pop();
onGotFile(imageId, image.path);
onGotFile(imageId, image!.path);
}
void getPictureFromCamera2(BuildContext context, int imageId, OnGotFile onGotFile) async {
ImagePicker picker = ImagePicker();
var image = await picker.pickImage(source: ImageSource.camera);
Navigator.of(context).pop();
onGotFile(imageId, image.path);
onGotFile(imageId, image!.path);
}
Future<void> createTicket(BuildContext context, String msg, List<Map<String, dynamic>> images,
OnSuccess onSuccess, OnError onError, {int id}) {
OnSuccess onSuccess, OnError onError, {int? id}) async {
var formData = FormData();
formData.fields.add(MapEntry("msg", msg));
formData.fields.add(MapEntry('id', id == null ? '0' : id.toString()));
@@ -562,7 +401,7 @@ class Util {
PaymentPlatform paymentPlatform, {
bool googlePay=false,
bool applePay=false,
StripePaymentMethod stripePaymentMethod,
StripePaymentMethod? stripePaymentMethod,
}) {
switch(paymentPlatform.code) {
case Constants.PAYMENT_METHOD_CODE_SQUARE:
@@ -587,7 +426,7 @@ class Util {
StripePayment.setOptions(
StripeOptions(publishableKey: paymentPlatform.publishableKey,
merchantId: paymentPlatform.merchantId,
androidPayMode: paymentPlatform.publishableKey.contains('_test_')
androidPayMode: paymentPlatform.publishableKey!.contains('_test_')
? 'test'
: 'production'
)
@@ -595,14 +434,14 @@ class Util {
StripePayment.paymentRequestWithNativePay(
androidPayOptions: AndroidPayPaymentRequest(
totalPrice: order.totalPrice.toStringAsFixed(2),
currencyCode: order.businessInfo.currency,
currencyCode: order.businessInfo!.currency,
),
applePayOptions: ApplePayPaymentOptions(
currencyCode: order.businessInfo.currency,
countryCode: order.businessInfo.address.country,
currencyCode: order.businessInfo!.currency,
countryCode: order.businessInfo!.address.country,
items: [
ApplePayItem(
label: order.businessInfo.name,
label: order.businessInfo!.name,
amount: order.totalPrice.toStringAsFixed(2),
),
],
@@ -633,7 +472,7 @@ class Util {
),
);
if (paymentMethod != null) {
Utils.stripePaymentIntent(order, null, paymentMethod.id, paymentMethod.type, (response) {
Utils.stripePaymentIntent(order, null, paymentMethod.id!, paymentMethod.type!, (response) {
if (response.data['status'] == Constants.STRIPE_STATUS_REQUIRES_CONFIRMATION) {
StripePayment.confirmPaymentIntent(
PaymentIntent(
@@ -643,8 +482,8 @@ class Util {
).then((paymentIntentResult) {
if (paymentIntentResult.status == Constants.STRIPE_STATUS_SUCCEDED) {
Utils.stripeChargedSuccess(order,
paymentMethod.id,
paymentIntentResult.paymentIntentId,
paymentMethod.id!,
paymentIntentResult.paymentIntentId!,
(response) {
StripePayment.completeNativePayRequest().then((_) {
eventBus.fire(OnOrderUpdated());
@@ -680,10 +519,10 @@ class Util {
}
}
static Future<Uint8List> getBytesFromAsset(String path, int width) async {
static Future<Uint8List?> getBytesFromAsset(String path, int width) async {
ByteData data = await rootBundle.load(path);
ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List(), targetWidth: width);
ui.FrameInfo fi = await codec.getNextFrame();
return (await fi.image.toByteData(format: ui.ImageByteFormat.png)).buffer.asUint8List();
return (await fi.image.toByteData(format: ui.ImageByteFormat.png))?.buffer.asUint8List();
}
}

View File

@@ -5,8 +5,6 @@ import 'dart:typed_data';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:url_launcher/url_launcher.dart';
import '../constants.dart';
@@ -36,27 +34,21 @@ class Util {
}
static Future<Box> getBox() async {
Hive.initFlutter();
Box box = await Hive.openBox('wisetronic_app_data');
return box;
}
static Widget showImage(String imageUrl, {double width, double height,
BoxFit fit, Widget Function(BuildContext, String, dynamic) errorWidget}) {
static Widget showImage(String imageUrl, {double? width, double? height,
BoxFit? fit, Widget Function(BuildContext, String?, dynamic)? errorWidget}) {
return Image.network(imageUrl,
fit: fit,
width: width,
height: height,
cacheWidth: width != null ? width.round() : null,
cacheHeight: height != null ? height.round() : null,
loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent loadingProgress) {
loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) {
if (loadingProgress == null) return child;
return Center(
child: Utils.imageLoadingIndicator(),
);
},
errorBuilder: (BuildContext context, Object object, StackTrace stackTrace) {
errorBuilder: (BuildContext context, Object object, StackTrace? stackTrace) {
print('StackTrace: $stackTrace');
if (errorWidget != null) {
return errorWidget(context, null, null);
@@ -106,16 +98,16 @@ class Util {
}
void startFilePicker(BuildContext context, User user, {int commentId = -1, int orderId = 0}) async {
InputElement uploadInput = FileUploadInputElement();
InputElement uploadInput = FileUploadInputElement() as InputElement;
uploadInput.click();
uploadInput.onChange.listen((e) {
final files = uploadInput.files;
if (files.length >= 1) {
if (files!.length >= 1) {
final File file = files[0];
final FileReader reader = new FileReader();
reader.onLoadEnd.listen((e) {
uploadPicture(context, reader.result, file.name, user, commentId: commentId, orderId: orderId);
uploadPicture(context, reader.result as Uint8List, file.name, user, commentId: commentId, orderId: orderId);
});
reader.onError.listen((e) {
Fluttertoast.showToast(
@@ -210,11 +202,11 @@ class Util {
void startFilePicker2(BuildContext context, int imageId, OnGotFile onGotFile) async {
final _image = await WebImagePicker().pickImage();
onGotFile(imageId, _image.dataScheme);
onGotFile(imageId, _image!.dataScheme);
}
void createTicket(BuildContext context, String msg, List<Map<String, dynamic>> images,
OnSuccess onSuccess, OnError onError, {int id}) {
OnSuccess onSuccess, OnError onError, {int? id}) {
var formData = FormData();
formData.fields.add(MapEntry("msg", msg));
formData.fields.add(MapEntry('id', id == null ? '0' : id.toString()));
@@ -252,7 +244,7 @@ class Util {
PaymentPlatform paymentPlatform, {
bool googlePay=false,
bool applePay=false,
StripePaymentMethod stripePaymentMethod,
StripePaymentMethod? stripePaymentMethod,
}) {
switch(paymentPlatform.code) {
case Constants.PAYMENT_METHOD_CODE_SQUARE:
@@ -293,36 +285,36 @@ class Util {
}
class ImageInfo {
String name;
String data;
String dataScheme;
String path;
String name = '';
String data = '';
String dataScheme = '';
String path = '';
}
class WebImagePicker {
Future<ImageInfo> pickImage() async {
Future<ImageInfo?> pickImage() async {
print('pickImage');
final ImageInfo data = ImageInfo();
final FileUploadInputElement input = FileUploadInputElement();
document.body.children.add(input);
document.body!.children.add(input);
input..accept = 'image/*';
input.click();
await input.onChange.first;
if (input.files.isEmpty) return null;
if (input.files!.isEmpty) return null;
final reader = FileReader();
reader.readAsDataUrl(input.files[0]);
reader.readAsDataUrl(input.files![0]);
await reader.onLoad.first;
final encoded = reader.result as String;
// remove data:image/*;base64 preambule
final stripped =
encoded.replaceFirst(RegExp(r'data:image/[^;]+;base64,'), '');
//final imageBase64 = base64.decode(stripped);
final imageName = input.files?.first?.name;
final imagePath = input.files?.first?.relativePath;
data.name = imageName;
final imageName = input.files?.first.name;
final imagePath = input.files?.first.relativePath;
data.name = imageName!;
data.data = stripped;
data.dataScheme = encoded;
data.path = imagePath;
data.path = imagePath!;
return data;
}
}

View File

@@ -8,7 +8,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:flutter_wisetronic/models/product.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hive/hive.dart';
import 'package:intl/intl.dart';
import 'package:path/path.dart' as path;
import 'package:universal_io/io.dart';
@@ -28,6 +27,7 @@ import '../store/actions.dart';
import '../store/store.dart';
import 'http_util.dart';
import 'util_web.dart' if (dart.library.io) 'util_io.dart';
import 'package:shared_preferences/shared_preferences.dart';
typedef void OnSuccess(Response response);
typedef void OnError(dynamic error);
@@ -37,16 +37,25 @@ typedef void OnOk();
typedef void OnLoadImageError();
class Utils {
static StreamSubscription onProductWillAddToCartSubscription;
static StreamSubscription onProductWillRemoveFromCartSubscription;
static final Utils _utils = Utils._internal();
static SharedPreferences? prefs;
static StreamSubscription? onProductWillAddToCartSubscription;
static StreamSubscription? onProductWillRemoveFromCartSubscription;
factory Utils() {
return _utils;
}
Utils._internal();
init() async {
prefs = await SharedPreferences.getInstance();
onProductWillAddToCartSubscription =
eventBus.on<OnProductWillAddToCart>().listen((event) {
CartInfo cartInfo =
CartInfo? cartInfo =
getCartInfoByBusiness(store.state.cartInfos, event.business);
if (cartInfo == null || cartInfo.productList.length == 0) {
if (cartInfo == null || cartInfo.productList!.length == 0) {
cartInfo = CartInfo();
cartInfo.id = 0;
cartInfo.amountPaid = 0.0;
@@ -57,7 +66,7 @@ class Utils {
id: 0,
price: event.price,
product: event.product,
name: event.product.name,
name: event.product.name!,
description: event.description,
quantity: 1.0);
cartInfo.productList = [lineItem];
@@ -67,15 +76,15 @@ class Utils {
eventBus.fire(new OnCartInfoUpdated());
print('#1');
} else {
if (event.product.productAttributes.length > 0) {
if (event.product.productAttributes!.length > 0) {
CartLineItem lineItem = newCartLineItem(
id: 0,
price: event.price,
product: event.product,
name: event.product.name,
name: event.product.name!,
description: event.description,
quantity: 1.0);
cartInfo.productList.add(lineItem);
cartInfo.productList!.add(lineItem);
addSubproductToCard(cartInfo, lineItem);
store.dispatch(new UpdateCartInfo(addCartInfoToCartInfoList(
store.state.cartInfos, cartInfo)));
@@ -83,8 +92,8 @@ class Utils {
eventBus.fire(new OnCartInfoUpdated());
} else {
int found = -1;
for (var i = 0; i < cartInfo.productList.length; i++) {
if (event.product.id == cartInfo.productList[i].product.id) {
for (var i = 0; i < cartInfo.productList!.length; i++) {
if (event.product.id == cartInfo.productList![i].product!.id) {
found = i;
break;
}
@@ -94,18 +103,18 @@ class Utils {
id: 0,
price: event.price,
product: event.product,
name: event.product.name,
name: event.product.name!,
description: event.description,
quantity: 1.0);
cartInfo.productList.add(lineItem);
cartInfo.productList!.add(lineItem);
addSubproductToCard(cartInfo, lineItem);
store.dispatch(new UpdateCartInfo(addCartInfoToCartInfoList(
store.state.cartInfos, cartInfo)));
print('#3');
eventBus.fire(new OnCartInfoUpdated());
} else {
if (cartInfo.productList[found].quantity + 1.0 >
event.product.leftNum) {
if (cartInfo.productList![found].quantity! + 1.0 >
event.product.leftNum!) {
// Fluttertoast.showToast(
// msg: S.of(context).product_insufficient,
// toastLength: Toast.LENGTH_SHORT,
@@ -113,8 +122,8 @@ class Utils {
// backgroundColor: Colors.red,
// textColor: Colors.white);
} else {
cartInfo.productList[found].quantity += 1;
addSubproductQty(cartInfo, cartInfo.productList[found]);
cartInfo.productList![found].quantity = cartInfo.productList![found].quantity! + 1;
addSubproductQty(cartInfo, cartInfo.productList![found]);
store.dispatch(new UpdateCartInfo(
addCartInfoToCartInfoList(
store.state.cartInfos, cartInfo)));
@@ -127,41 +136,41 @@ class Utils {
});
onProductWillRemoveFromCartSubscription =
eventBus.on<OnProductWillRemoveFromCart>().listen((event) {
CartInfo cartInfo =
CartInfo? cartInfo =
getCartInfoByBusiness(store.state.cartInfos, event.business);
if (cartInfo != null) {
if (cartInfo.productList.length > 0) {
if (cartInfo.productList!.length > 0) {
if (event.productListIndex != -1) {
if (cartInfo.productList[event.productListIndex].quantity <= 1) {
String uuid = cartInfo.productList[event.productListIndex].uuid;
cartInfo.productList.removeAt(event.productListIndex);
if (cartInfo.productList![event.productListIndex].quantity! <= 1) {
String uuid = cartInfo.productList![event.productListIndex].uuid!;
cartInfo.productList!.removeAt(event.productListIndex);
removeSubproduct(cartInfo, uuid);
} else {
cartInfo.productList[event.productListIndex].quantity -= 1;
addSubproductQty(cartInfo, cartInfo.productList[event.productListIndex], remove: true);
cartInfo.productList![event.productListIndex].quantity = cartInfo.productList![event.productListIndex].quantity! - 1;
addSubproductQty(cartInfo, cartInfo.productList![event.productListIndex], remove: true);
}
} else {
int productListIndex = -1;
for (var i = 0; i < cartInfo.productList.length; i++) {
if (cartInfo.productList[i].product.id == event.product.id) {
for (var i = 0; i < cartInfo.productList!.length; i++) {
if (cartInfo.productList![i].product!.id == event.product.id) {
productListIndex = i;
break;
}
}
if (productListIndex != -1) {
if (cartInfo.productList[productListIndex].quantity <= 1) {
String uuid = cartInfo.productList[productListIndex].uuid;
cartInfo.productList.removeAt(productListIndex);
if (cartInfo.productList![productListIndex].quantity! <= 1) {
String uuid = cartInfo.productList![productListIndex].uuid!;
cartInfo.productList!.removeAt(productListIndex);
removeSubproduct(cartInfo, uuid);
} else {
cartInfo.productList[productListIndex].quantity -= 1;
addSubproductQty(cartInfo, cartInfo.productList[productListIndex], remove: true);
cartInfo.productList![productListIndex].quantity = cartInfo.productList![productListIndex].quantity! - 1;
addSubproductQty(cartInfo, cartInfo.productList![productListIndex], remove: true);
}
}
}
}
if (cartInfo.productList.length <= 0) {
if (cartInfo.productList!.length <= 0) {
store.dispatch(UpdateCartInfo(removeCartInfoFromCartInfoList(
store.state.cartInfos, cartInfo)));
} else {
@@ -211,7 +220,7 @@ class Utils {
return false;
}
static Map<String, dynamic> stringToJson(String string) {
static Map<String, dynamic>? stringToJson(String? string) {
if (string == null || string.isEmpty) {
return null;
}
@@ -244,10 +253,6 @@ class Utils {
return platformName;
}
static Future<Box> getBox() async {
return Util.getBox();
}
static Widget imageLoadingIndicator(
{double width = 30.0, double height = 30.0}) {
return SizedBox(
@@ -365,7 +370,7 @@ class Utils {
);
}
static showLoadingDialog(BuildContext context, {String message}) {
static showLoadingDialog(BuildContext context, {String? message}) {
showDialog(
context: context,
barrierDismissible: false,
@@ -468,46 +473,45 @@ class Utils {
}
static void getCurrentUser() {
getBox().then((box) {
int userId = box.get(Constants.KEY_USER_ID, defaultValue: 0);
String accessToken =
box.get(Constants.KEY_ACCESS_TOKEN, defaultValue: '');
if (userId == 0 || accessToken.isEmpty) {
eventBus.fire(new OnGetCurrentUserFailed(Error()));
} else {
HttpUtil.httpGet(
'v1/users/$userId',
queryParameters: {},
businessId: Constants.BUSINESS_ID,
).then((value) {
User user = User.fromJson(value);
store.dispatch(UpdateCurrentUser(user));
eventBus.fire(OnCurrentUserUpdated());
}).catchError((err) {
eventBus.fire(new OnGetCurrentUserFailed(err));
});
}
}).catchError((err) {
eventBus.fire(new OnGetCurrentUserFailed(err));
});
if (store.state.user != null) {
eventBus.fire(OnCurrentUserUpdated());
return;
}
int? userId = prefs?.getInt(Constants.KEY_USER_ID) ?? 0;
String? accessToken = prefs?.getString(Constants.KEY_ACCESS_TOKEN) ?? '';
if (userId == 0 || accessToken.isEmpty) {
eventBus.fire(new OnGetCurrentUserFailed(Error()));
} else {
HttpUtil.httpGet(
'v1/users/$userId',
queryParameters: {},
businessId: Constants.BUSINESS_ID,
).then((value) {
User user = User.fromJson(value);
store.dispatch(UpdateCurrentUser(user));
eventBus.fire(OnCurrentUserUpdated());
}).catchError((err) {
eventBus.fire(new OnGetCurrentUserFailed(err));
});
}
}
static void showMessageDialog(BuildContext context, dynamic error,
{String title, List<Widget> actions, OnOk onOk}) {
{String? title, List<Widget>? actions, OnOk? onOk}) {
String message = '';
print('error $error');
if (error is DioError && error.response != null) {
if (error.response.data['message'] != null) {
message = error.response.data['message'];
} else if (error.response.data['error'] != null) {
if (error.response.data['error'] is String) {
message = error.response.data['error'];
} else if (error.response.data['error']['errmsg'] != null) {
message = error.response.data['error']['errmsg'];
} else if (error.response.data['error']['message'] != null) {
message = error.response.data['error']['message'];
if (error is DioException && error.response != null) {
if (error.response!.data['message'] != null) {
message = error.response!.data['message'];
} else if (error.response!.data['error'] != null) {
if (error.response!.data['error'] is String) {
message = error.response!.data['error'];
} else if (error.response!.data['error']['errmsg'] != null) {
message = error.response!.data['error']['errmsg'];
} else if (error.response!.data['error']['message'] != null) {
message = error.response!.data['error']['message'];
} else {
message = error.response.data.toString();
message = error.response!.data.toString();
}
}
} else if (error is String) {
@@ -540,20 +544,15 @@ class Utils {
}
static Future<List<int>> getLastVisit() async {
Box box = await getBox();
List<dynamic> lastVisit =
json.decode(box.get(Constants.KEY_LAST_VISIT, defaultValue: '[]'));
json.decode(prefs?.getString(Constants.KEY_LAST_VISIT) ?? '[]');
List<int> lv = lastVisit.map((e) => e as int).toList();
store.dispatch(UpdateLastVisit(lv));
return lv;
}
static void saveLastVisit(List<int> lastVisit) {
getBox().then((box) {
box.put(Constants.KEY_LAST_VISIT, lastVisit.toString());
}).catchError((error) {
print('Error occurred: $error');
});
prefs?.setString(Constants.KEY_LAST_VISIT, lastVisit.toString());
}
static String utcDatetimeStringToLocalDatetimeString(
@@ -656,26 +655,26 @@ class Utils {
}
}
static CartInfo getCartInfoByBusiness(
List<CartInfo> cartInfos, Business business) {
static CartInfo? getCartInfoByBusiness(
List<CartInfo>? cartInfos, Business business) {
if (cartInfos == null || cartInfos.length <= 0) {
return null;
}
for (var i = 0; i < cartInfos.length; i++) {
if (cartInfos[i].businessInfo.id == business.id) {
if (cartInfos[i].businessInfo!.id == business.id) {
return cartInfos[i];
}
}
return null;
}
static CartInfo getCartInfoByBusinessId(
List<CartInfo> cartInfos, int businessId) {
static CartInfo? getCartInfoByBusinessId(
List<CartInfo>? cartInfos, int businessId) {
if (cartInfos == null || cartInfos.length <= 0) {
return null;
}
for (var i = 0; i < cartInfos.length; i++) {
if (cartInfos[i].businessInfo.id == businessId) {
if (cartInfos[i].businessInfo!.id == businessId) {
return cartInfos[i];
}
}
@@ -683,13 +682,13 @@ class Utils {
}
static List<CartInfo> addCartInfoToCartInfoList(
List<CartInfo> cartInfos, CartInfo cartInfo) {
List<CartInfo>? cartInfos, CartInfo cartInfo) {
if (cartInfos == null || cartInfos.length <= 0) {
cartInfos = [cartInfo];
} else {
bool found = false;
for (var i = 0; i < cartInfos.length; i++) {
if (cartInfos[i].businessInfo.id == cartInfo.businessInfo.id) {
if (cartInfos[i].businessInfo!.id == cartInfo.businessInfo!.id) {
cartInfos[i] = cartInfo;
found = true;
break;
@@ -699,22 +698,19 @@ class Utils {
cartInfos.add(cartInfo);
}
}
Utils.getBox().then((box) {
box.put(Constants.KEY_CARTINFOS, cartInfos.toString());
}).catchError((error) {
print('Error occurred: $error');
});
prefs?.setString(Constants.KEY_CARTINFOS, cartInfos.toString());
return cartInfos;
}
static List<CartInfo> removeCartInfoFromCartInfoList(
List<CartInfo> cartInfos, CartInfo cartInfo) {
List<CartInfo>? cartInfos, CartInfo? cartInfo) {
if (cartInfos == null || cartInfos.length <= 0 || cartInfo == null) {
prefs?.setString(Constants.KEY_CARTINFOS, cartInfos.toString());
return [];
}
int removeIndex = -1;
for (var i = 0; i < cartInfos.length; i++) {
if (cartInfo.businessInfo.id == cartInfos[i].businessInfo.id) {
if (cartInfo.businessInfo!.id == cartInfos[i].businessInfo!.id) {
removeIndex = i;
break;
}
@@ -722,17 +718,13 @@ class Utils {
if (removeIndex != -1) {
cartInfos.removeAt(removeIndex);
}
getBox().then((box) {
box.put(Constants.KEY_CARTINFOS, cartInfos.toString());
}).catchError((error) {
print('Error occurred: $error');
});
prefs?.setString(Constants.KEY_CARTINFOS, cartInfos.toString());
return cartInfos;
}
static void clearCart(BuildContext context, CartInfo cartInfo,
{OnComplete onComplete}) {
if (cartInfo != null && cartInfo.productList.length > 0) {
{OnComplete? onComplete}) {
if (cartInfo != null && cartInfo.productList!.length > 0) {
showDialog(
context: context,
builder: (BuildContext context) {
@@ -766,7 +758,7 @@ class Utils {
}
static void requireLogin(BuildContext context,
{String returnUrl, bool replace = true, int delayMilliseconds = 400}) {
{String? returnUrl, bool replace = true, int delayMilliseconds = 400}) {
Future.delayed(Duration(milliseconds: delayMilliseconds), () {
if (returnUrl != null) {
store.dispatch(UpdateRedirectRoute(returnUrl));
@@ -775,9 +767,9 @@ class Utils {
});
}
static String getFirstNumberFromString(String numString) {
static String? getFirstNumberFromString(String numString) {
final intInStr = RegExp(r'\d+');
return intInStr.firstMatch(numString).group(0);
return intInStr.firstMatch(numString)?.group(0);
}
static void loadProducts(int businessId, int categoryId, int page, bool more,
@@ -845,7 +837,7 @@ class Utils {
}
}
static String getWeekDayName(BuildContext context, int timestamp, bool shortName) {
static String? getWeekDayName(BuildContext context, int timestamp, bool shortName) {
DateTime date = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
switch(date.weekday) {
case 1:
@@ -854,61 +846,54 @@ class Utils {
} else {
return S.of(context).monday;
}
break;
case 2:
if (shortName) {
return S.of(context).tue;
} else {
return S.of(context).tuesday;
}
break;
case 3:
if (shortName) {
return S.of(context).wed;
} else {
return S.of(context).wednesday;
}
break;
case 4:
if (shortName) {
return S.of(context).thu;
} else {
return S.of(context).thursday;
}
break;
case 5:
if (shortName) {
return S.of(context).fri;
} else {
return S.of(context).friday;
}
break;
case 6:
if (shortName) {
return S.of(context).sat;
} else {
return S.of(context).saturday;
}
break;
case 7:
if (shortName) {
return S.of(context).sun;
} else {
return S.of(context).sunday;
}
break;
}
}
static void stripePaymentIntent(Order order, String customerId, String paymentMethodId, String cardType,
static void stripePaymentIntent(Order order, String? customerId, String paymentMethodId, String cardType,
OnSuccess onSuccess, OnError onError,
{
String cardBrand,
String cardCountry,
int cardExpMonth,
int cardExpYear,
String cardFunding,
String cardLast4,
String? cardBrand,
String? cardCountry,
int? cardExpMonth,
int? cardExpYear,
String? cardFunding,
String? cardLast4,
}) {
HttpUtil.httpPost('v1/stripe-payment-intent',
@@ -919,12 +904,12 @@ class Utils {
'customer_id': customerId == null ? '' : customerId,
'payment_method_id': paymentMethodId,
'payment_method_type': cardType,
'card_brand': cardBrand,
'card_country': cardCountry,
'card_exp_month': cardExpMonth,
'card_exp_year': cardExpYear,
'card_funding': cardFunding,
'card_last4': cardLast4,
'card_brand': cardBrand ?? '',
'card_country': cardCountry ?? '',
'card_exp_month': cardExpMonth ?? 0,
'card_exp_year': cardExpYear ?? 0,
'card_funding': cardFunding ?? '',
'card_last4': cardLast4 ?? '',
},
isFormData: true,
).catchError(onError);
@@ -945,8 +930,8 @@ class Utils {
static int getProductLineInOrder(CartInfo cartInfo) {
int qty = 0;
for (CartLineItem lineItem in cartInfo.productList) {
if (lineItem.product.id != null) {
for (CartLineItem lineItem in cartInfo.productList!) {
if (lineItem.product?.id != null) {
qty += 1;
}
}
@@ -954,10 +939,10 @@ class Utils {
}
static void orderAgain(BuildContext context, CartInfo cartInfo) {
cartInfo.productList.removeWhere((element) => element.product == null || element.product.id == null);
cartInfo.productList!.removeWhere((element) => element.product == null || element.product!.id == null);
store.dispatch(UpdateCartInfo(Utils.addCartInfoToCartInfoList(store.state.cartInfos, cartInfo)));
eventBus.fire(new OnCartInfoUpdated());
Routes.router.navigateTo(context, '/checkout/${cartInfo.businessInfo.id}');
Routes.router.navigateTo(context, '/checkout/${cartInfo.businessInfo!.id}');
}
static String getOrderStatus(BuildContext context, int statusCode) {
@@ -978,42 +963,42 @@ class Utils {
}
static CartLineItem newCartLineItem(
{int id,
double price,
Product product,
String name,
String description,
double quantity,
String parentUuid,
{int? id,
double? price,
Product? product,
String? name,
String? description,
double? quantity,
String? parentUuid,
}) {
CartLineItem lineItem = CartLineItem();
lineItem.unitPrice = price;
lineItem.product = product;
lineItem.name = product.name;
lineItem.name = product?.name ?? '';
lineItem.description = description;
lineItem.quantity = quantity;
lineItem.parentUuid = parentUuid;
lineItem.parentUuid = parentUuid ?? '';
return lineItem;
}
static void addSubproductToCard(CartInfo cartInfo, CartLineItem lineItem) {
if (lineItem.product.subproducts.length > 0) {
for (int j = 0; j < lineItem.product.subproducts.length; j++) {
cartInfo.productList.add(
if (lineItem.product!.subproducts!.length > 0) {
for (int j = 0; j < lineItem.product!.subproducts!.length; j++) {
cartInfo.productList!.add(
newCartLineItem(
id: 0,
price: 0.0,
product: Product(
lineItem.product.subproducts[j].product.id,
lineItem.product.businessId,
lineItem.product.subproducts[j].product.name,
lineItem.product.subproducts[j].product.price,
lineItem.product.subproducts[j].product.description,
lineItem.product.subproducts[j].product.image,
lineItem.product.subproducts[j].product.productAttributes
lineItem.product!.subproducts![j].product.id,
lineItem.product!.businessId!,
lineItem.product!.subproducts![j].product.name,
lineItem.product!.subproducts![j].product.price,
lineItem.product!.subproducts![j].product.description,
lineItem.product!.subproducts![j].product.image,
lineItem.product!.subproducts![j].product.productAttributes
),
name: lineItem.product.subproducts[j].product.name,
description: lineItem.product.subproducts[j].product.description,
name: lineItem.product!.subproducts![j].product.name,
description: lineItem.product!.subproducts![j].product.description,
quantity: 1.0,
parentUuid: lineItem.uuid
)
@@ -1024,16 +1009,16 @@ class Utils {
static void addSubproductQty(CartInfo cartInfo, CartLineItem lineItem,
{bool remove = false}) {
if (lineItem.product.subproducts.length > 0) {
for (var i = 0; i < cartInfo.productList.length; i++) {
CartLineItem lineItem1 = cartInfo.productList[i];
if (lineItem.product!.subproducts!.length > 0) {
for (var i = 0; i < cartInfo.productList!.length; i++) {
CartLineItem lineItem1 = cartInfo.productList![i];
if (lineItem1.parentUuid == lineItem.uuid) {
for (var j = 0; j < lineItem.product.subproducts.length; j++) {
if (lineItem.product.subproducts[j].product.id == lineItem1.product.id) {
for (var j = 0; j < lineItem.product!.subproducts!.length; j++) {
if (lineItem.product!.subproducts![j].product.id == lineItem1.product!.id) {
if (remove) {
lineItem1.quantity -= lineItem.product.subproducts[j].quantity;
lineItem1.quantity = lineItem1.quantity! - lineItem.product!.subproducts![j].quantity;
} else {
lineItem1.quantity += lineItem.product.subproducts[j].quantity;
lineItem1.quantity = lineItem1.quantity! + lineItem.product!.subproducts![j].quantity;
}
break;
}
@@ -1044,7 +1029,7 @@ class Utils {
}
static void removeSubproduct(CartInfo cartInfo, String uuid) {
cartInfo.productList.removeWhere((element) => element.parentUuid == uuid);
cartInfo.productList!.removeWhere((element) => element.parentUuid == uuid);
}
static void openEmail(String email) async {
@@ -1069,7 +1054,7 @@ class Utils {
}
}
static Widget buildLine(String name, dynamic value, {double nameSize, double valueSize}) {
static Widget buildLine(String name, dynamic value, {double? nameSize, double? valueSize}) {
Row row = Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
@@ -1119,7 +1104,7 @@ class Utils {
}
class RuntimeError extends Error {
final int code;
final int? code;
final String message;
RuntimeError(this.message, {this.code});
String toString() => "Runtime Error: $message";