import 'dart:math'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:fluttertoast/fluttertoast.dart'; import '../../constants.dart'; import '../../dialog/logout_dialog.dart'; import '../../events/eventbus.dart'; import '../../events/events.dart'; import '../../generated/l10n.dart'; import '../../models/user.dart'; import '../../routes.dart'; import '../../store/actions.dart'; import '../../store/store.dart'; import '../../utils/shop_scroll_controller.dart'; import '../../utils/shop_scroll_coordinator.dart'; import '../../utils/util_web.dart' if (dart.library.io) '../../utils/util_io.dart'; import '../../utils/utils.dart'; MediaQueryData mediaQuery; double statusBarHeight; double screenHeight; class MobileMe extends StatefulWidget { final Key key; const MobileMe({this.key}) : super(key: key); @override State createState() { return MobileMeState(); } } class MobileMeState extends State { int userId; String accessToken; bool isLoading; User _user; ShopScrollCoordinator _shopCoordinator; ShopScrollController _pageScrollController; final double _sliverAppBarInitHeight = 165.0; final double _appBarHeight = 85.0; ShopScrollController _listScrollController1; @override Widget build(BuildContext context) { store.dispatch(UpdateContext(context)); if (isLoading) { return new Scaffold( body: Center( child: SpinKitWave( color: Colors.lightBlueAccent, size: 40.0, ), ), ); } mediaQuery ??= MediaQuery.of(context); screenHeight ??= mediaQuery.size.height; statusBarHeight ??= mediaQuery.padding.top; _pageScrollController ??= _shopCoordinator.pageScrollController(_sliverAppBarInitHeight * -1.0); _shopCoordinator.pinnedHeaderSliverHeightBuilder ??= () { return statusBarHeight + kToolbarHeight + _appBarHeight; }; _listScrollController1 = _shopCoordinator.newChildScrollController(); Widget userInfo = GestureDetector( child: Container( padding: EdgeInsets.only(left: 16.0, right: 16.0, top: 5.0, bottom: 5.0), margin: EdgeInsets.only(top: kToolbarHeight + 40.0), color: Colors.transparent, child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( margin: EdgeInsets.only(right: 5.0), child: _user != null && _user.avatarUrl.isNotEmpty ? Util.showImage( 'https:${_user.avatarUrl}', width: 60, height: 60, fit: BoxFit.fill, errorWidget: (context, url, error) => Icon( Icons.account_circle, size: 60.0, color: Theme.of(context).scaffoldBackgroundColor, ), ) : Icon( Icons.person_outline, size: 60.0, color: Colors.white38, ), ), Expanded( child: Container( height: 60.0, child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( child: Text( _user != null ? _user.nickname : S.of(context).please_login, style: TextStyle( color: Theme.of(context).scaffoldBackgroundColor, fontSize: 28.0, ), ), ), Visibility( visible: _user != null, child: Container( child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( child: Icon( Icons.phone_iphone, color: Theme.of(context).scaffoldBackgroundColor, size: 20.0, ), ), Container( child: Text( _user != null ? Utils.safePhoneNumber(_user.mobile) : '', style: TextStyle( color: Theme.of(context).scaffoldBackgroundColor, fontSize: 16.0, ), ), ) ], ), ), ), ], ), ), ), Container( child: Icon( Icons.arrow_forward_ios, color: Theme.of(context).scaffoldBackgroundColor, size: 20.0, ), color: Colors.transparent, ), ], ), ), onTap: () { if (_user != null) { Routes.router.navigateTo(context, '/user-profile'); } else { Routes.router.navigateTo(context, '/login'); } }, ); Listener listener = Listener( onPointerUp: _shopCoordinator.onPointerUp, child: CustomScrollView( controller: _pageScrollController, physics: ClampingScrollPhysics(), slivers: [ SliverAppBar( pinned: true, floating: true, snap: true, title: Text(S.of(context).me), centerTitle: true, backgroundColor: Theme.of(context).primaryColor, expandedHeight: _sliverAppBarInitHeight, actions: [], flexibleSpace: FlexibleSpaceBar( background: userInfo, collapseMode: CollapseMode.none, ), ), SliverPersistentHeader( pinned: true, floating: false, delegate: _SliverAppBarDelegate( minHeight: _appBarHeight, maxHeight: _appBarHeight, child: Container( child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Expanded( child: Container( padding: EdgeInsets.only( left: 16.0, right: 16.0, top: 16.0, bottom: 16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( child: Text( _user != null ? '${_user.wallet.toStringAsFixed(2)}' : '0.00', style: TextStyle( fontSize: 24.0, color: Colors.redAccent, ), ), ), Container( child: Text( S.of(context).wallet, style: TextStyle( fontSize: 12.0, color: Colors.grey, ), ), ) ], ), decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Colors.black12, width: 6.0, ), right: BorderSide( color: Colors.black12, width: 1.0, ), ), ), ), ), Expanded( child: GestureDetector( child: Container( padding: EdgeInsets.only( left: 16.0, right: 16.0, top: 16.0, bottom: 16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( child: Text( _user != null ? '${_user.coupon}' : '0', style: TextStyle( fontSize: 24.0, color: Colors.orangeAccent, ), ), ), Container( child: Text( S.of(context).red_coupon, style: TextStyle( fontSize: 12.0, color: Colors.grey, ), ), ) ], ), decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Colors.black12, width: 6.0, ), right: BorderSide( color: Colors.black12, width: 1.0, ), ), ), ), onTap: () { if (_user != null) { Routes.router .navigateTo(context, '/coupons/${_user.id}'); } else { _pleaseLoginToast(); } }, ), ), Expanded( child: Container( padding: EdgeInsets.only( left: 16.0, right: 16.0, top: 16.0, bottom: 16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( child: Text( _user != null ? '${_user.points}' : '0', style: TextStyle( fontSize: 24.0, color: Colors.lightGreen, ), ), ), Container( child: Text( S.of(context).point, style: TextStyle( fontSize: 12.0, color: Colors.grey, ), ), ) ], ), decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Colors.black12, width: 6.0, ), ), ), ), ), ], ), ), ), ), SliverFillRemaining( child: ListView.builder( controller: _listScrollController1, itemCount: 7, itemBuilder: (BuildContext context, int i) { Widget item; switch (i) { case 0: item = GestureDetector( child: Container( padding: EdgeInsets.only( left: 16.0, right: 16.0, top: 16.0, bottom: 16.0), child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( padding: EdgeInsets.only(right: 5.0), child: Icon( Icons.settings_overscan, size: 20.0, ), ), Container( child: Text( S.of(context).ocr_scan, style: TextStyle( fontSize: 15.0, ), ), ), Expanded( child: SizedBox(), ), Container( child: Icon( Icons.arrow_forward_ios, size: 15.0, color: Colors.grey, ), ), ], ), decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Colors.black12, width: 1.0))), ), onTap: () { if (_user != null) { if (kIsWeb) { showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: Text(S.of(context).error), content: Text( S.of(context).feature_not_available_web, ), actions: [ TextButton( onPressed: () { Routes.router.pop(context); }, child: Text(S.of(context).ok)), ], ); }); } else { Routes.router.navigateTo( context, '/ocr-scan', ); } } else { _pleaseLoginToast(); } }, ); break; case 1: item = GestureDetector( child: Container( padding: EdgeInsets.only( left: 16.0, right: 16.0, top: 16.0, bottom: 16.0), child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( padding: EdgeInsets.only(right: 5.0), child: Icon( Icons.lock, size: 20.0, ), ), Container( child: Text( S.of(context).change_password, style: TextStyle( fontSize: 15.0, ), ), ), Expanded( child: SizedBox(), ), Container( child: Icon( Icons.arrow_forward_ios, size: 15.0, color: Colors.grey, ), ), ], ), decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Colors.black12, width: 1.0))), ), onTap: () { if (_user != null) { Routes.router.navigateTo( context, '/change-password', ); } else { _pleaseLoginToast(); } }, ); break; case 2: item = GestureDetector( child: Container( padding: EdgeInsets.only( left: 16.0, right: 16.0, top: 16.0, bottom: 16.0), child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( padding: EdgeInsets.only(right: 5.0), child: Icon( Icons.sticky_note_2_outlined, size: 20.0, ), ), Container( child: Text( S.of(context).my_orders, style: TextStyle( fontSize: 15.0, ), ), ), Expanded( child: SizedBox(), ), Container( child: Icon( Icons.arrow_forward_ios, size: 15.0, color: Colors.grey, ), ), ], ), decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Colors.black12, width: 1.0))), ), onTap: () { if (_user != null) { Routes.router.navigateTo(context, '/orders'); } else { _pleaseLoginToast(); } }, ); break; case 3: item = GestureDetector( child: Container( padding: EdgeInsets.only( left: 16.0, right: 16.0, top: 16.0, bottom: 16.0), child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( padding: EdgeInsets.only(right: 5.0), child: Icon( Icons.location_on, size: 20.0, ), ), Container( child: Text( S.of(context).my_addresses, style: TextStyle( fontSize: 15.0, ), ), ), Expanded( child: SizedBox(), ), Container( child: Icon( Icons.arrow_forward_ios, size: 15.0, color: Colors.grey, ), ), ], ), decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Colors.black12, width: 1.0))), ), onTap: () { if (_user != null) { Routes.router.navigateTo(context, '/my-addresses/-1'); } else { _pleaseLoginToast(); } }, ); break; case 4: item = GestureDetector( child: Container( padding: EdgeInsets.only( left: 16.0, right: 16.0, top: 16.0, bottom: 16.0), child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( padding: EdgeInsets.only(right: 5.0), child: Icon( Icons.credit_card, size: 20.0, ), ), Container( child: Text( S.of(context).my_cards, style: TextStyle( fontSize: 15.0, ), ), ), Expanded( child: SizedBox(), ), Container( child: Icon( Icons.arrow_forward_ios, size: 15.0, color: Colors.grey, ), ), ], ), decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Colors.black12, width: 1.0))), ), onTap: () { if (_user != null) { Routes.router.navigateTo(context, '/my-cards'); } else { _pleaseLoginToast(); } }, ); break; case 5: item = GestureDetector( child: Container( padding: EdgeInsets.only( left: 16.0, right: 16.0, top: 16.0, bottom: 16.0), child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( padding: EdgeInsets.only(right: 5.0), child: Icon( Icons.headset_mic, size: 20.0, ), ), Container( child: Text( S.of(context).my_support, style: TextStyle( fontSize: 15.0, ), ), ), Expanded( child: SizedBox(), ), Container( child: Icon( Icons.arrow_forward_ios, size: 15.0, color: Colors.grey, ), ), ], ), decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Colors.black12, width: 1.0))), ), onTap: () { if (_user != null) { if (_user.email == null || _user.email.isEmpty) { showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: Text(S.of(context).warning), content: Text(S.of(context).email_needed), actions: [ TextButton( child: Text(S.of(context).cancel), onPressed: () { Navigator.of(context).pop(); }, ), ElevatedButton( style: ElevatedButton.styleFrom( primary: Theme.of(context).primaryColor, textStyle: TextStyle( color: Colors.white, ), ), child: Text(S.of(context).ok), onPressed: () { Navigator.of(context).pop(); Routes.router.navigateTo(context, '/change-mobile-email/2'); }, ), ], ); }); } else { Routes.router.navigateTo(context, '/my-support/${Constants.BUSINESS_ID}'); } } else { _pleaseLoginToast(); } }, ); break; case 6: if (_user == null) { item = SizedBox.shrink(); } else { item = GestureDetector( child: Container( padding: EdgeInsets.only( left: 16.0, right: 16.0, top: 16.0, bottom: 16.0), child: Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( child: Text( S.of(context).logout, style: TextStyle( fontSize: 16.0, fontWeight: FontWeight.bold, color: Colors.red, ), ), ), Container( margin: EdgeInsets.only(left: 10.0), child: Icon( Icons.logout, color: Colors.redAccent, ), ), ], ), ), decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Colors.black12, width: 1.0))), ), onTap: () { showDialog( context: context, builder: (BuildContext context) { return logoutDialog(context); }); }, ); } break; } return item; }, ), ), ], ), ); return listener; } @override void initState() { super.initState(); setState(() { isLoading = true; _user = null; }); _shopCoordinator = ShopScrollCoordinator(); eventBus.on().listen((event) { if (mounted) { setState(() { isLoading = false; _user = store.state.user; }); } }); eventBus.on().listen((event) { if (mounted) { setState(() { isLoading = false; _user = null; }); } }); Utils.getCurrentUser(); } void _toLogin() { Routes.router .navigateTo(context, '/login', replace: true, clearStack: true); } _pleaseLoginToast() { Fluttertoast.showToast( msg: S.of(context).please_login, toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.CENTER, backgroundColor: Colors.black54, textColor: Colors.white); } } class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate { _SliverAppBarDelegate({ @required this.minHeight, @required this.maxHeight, @required this.child, }); final double minHeight; final double maxHeight; final Widget child; @override double get minExtent => this.minHeight; @override double get maxExtent => max(maxHeight, minHeight); @override Widget build( BuildContext context, double shrinkOffset, bool overlapsContent) { return SizedBox.expand(child: child); } @override bool shouldRebuild(_SliverAppBarDelegate oldDelegate) { return maxHeight != oldDelegate.maxHeight || minHeight != oldDelegate.minHeight || child != oldDelegate.child; } }