diff --git a/lib/src/screens/ionia/auth/ionia_create_account_page.dart b/lib/src/screens/ionia/auth/ionia_create_account_page.dart index 3fd912404..e0c0ecb35 100644 --- a/lib/src/screens/ionia/auth/ionia_create_account_page.dart +++ b/lib/src/screens/ionia/auth/ionia_create_account_page.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; +import 'package:cake_wallet/typography.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/ionia/ionia_view_model.dart'; import 'package:flutter/material.dart'; @@ -33,11 +34,8 @@ class IoniaCreateAccountPage extends BasePage { Widget middle(BuildContext context) { return Text( S.current.sign_up, - style: TextStyle( - fontSize: 22, - fontFamily: 'Lato', + style: textLargeSemiBold( color: Theme.of(context).accentTextTheme.display4.backgroundColor, - fontWeight: FontWeight.w900, ), ); } diff --git a/lib/src/screens/ionia/auth/ionia_login_page.dart b/lib/src/screens/ionia/auth/ionia_login_page.dart index 584682341..b47944f4d 100644 --- a/lib/src/screens/ionia/auth/ionia_login_page.dart +++ b/lib/src/screens/ionia/auth/ionia_login_page.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; +import 'package:cake_wallet/typography.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/ionia/ionia_view_model.dart'; import 'package:flutter/material.dart'; @@ -34,10 +35,8 @@ class IoniaLoginPage extends BasePage { Widget middle(BuildContext context) { return Text( S.current.login, - style: TextStyle( - fontSize: 22, - fontFamily: 'Lato', - fontWeight: FontWeight.w900, + style: textLargeSemiBold( + color: Theme.of(context).accentTextTheme.display4.backgroundColor, ), ); } diff --git a/lib/src/screens/ionia/auth/ionia_verify_otp_page.dart b/lib/src/screens/ionia/auth/ionia_verify_otp_page.dart index 2af82350a..fb254f71d 100644 --- a/lib/src/screens/ionia/auth/ionia_verify_otp_page.dart +++ b/lib/src/screens/ionia/auth/ionia_verify_otp_page.dart @@ -38,11 +38,8 @@ class IoniaVerifyIoniaOtp extends BasePage { Widget middle(BuildContext context) { return Text( S.current.verification, - style: TextStyle( - fontSize: 22, - fontFamily: 'Lato', + style: textLargeSemiBold( color: Theme.of(context).accentTextTheme.display4.backgroundColor, - fontWeight: FontWeight.w900, ), ); } diff --git a/lib/src/screens/ionia/auth/ionia_welcome_page.dart b/lib/src/screens/ionia/auth/ionia_welcome_page.dart index 66e89899b..85e06faae 100644 --- a/lib/src/screens/ionia/auth/ionia_welcome_page.dart +++ b/lib/src/screens/ionia/auth/ionia_welcome_page.dart @@ -2,6 +2,7 @@ import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/typography.dart'; import 'package:cake_wallet/view_model/ionia/ionia_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter/src/widgets/framework.dart'; @@ -15,11 +16,8 @@ class IoniaWelcomePage extends BasePage { Widget middle(BuildContext context) { return Text( S.current.welcome_to_cakepay, - style: TextStyle( - fontSize: 22, - fontFamily: 'Lato', + style: textLargeSemiBold( color: Theme.of(context).accentTextTheme.display4.backgroundColor, - fontWeight: FontWeight.w900, ), ); } @@ -90,11 +88,13 @@ class IoniaWelcomePage extends BasePage { S.of(context).login, style: TextStyle( color: Palette.blueCraiola, - fontSize: 16, + fontSize: 18, + letterSpacing: 1.5, fontWeight: FontWeight.w900, ), ), - ) + ), + SizedBox(height: 20) ], ) ], diff --git a/lib/src/screens/ionia/cards/ionia_activate_debit_card_page.dart b/lib/src/screens/ionia/cards/ionia_activate_debit_card_page.dart index 91fd8615c..f35ddd8bb 100644 --- a/lib/src/screens/ionia/cards/ionia_activate_debit_card_page.dart +++ b/lib/src/screens/ionia/cards/ionia_activate_debit_card_page.dart @@ -5,6 +5,7 @@ import 'package:cake_wallet/src/screens/ionia/widgets/text_icon_button.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; +import 'package:cake_wallet/typography.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/ionia/ionia_view_model.dart'; import 'package:flutter/material.dart'; @@ -21,11 +22,8 @@ class IoniaActivateDebitCardPage extends BasePage { Widget middle(BuildContext context) { return Text( S.current.debit_card, - style: TextStyle( - fontSize: 22, + style: textLargeSemiBold( color: Theme.of(context).accentTextTheme.display4.backgroundColor, - fontFamily: 'Lato', - fontWeight: FontWeight.w900, ), ); } diff --git a/lib/src/screens/ionia/cards/ionia_buy_card_detail_page.dart b/lib/src/screens/ionia/cards/ionia_buy_card_detail_page.dart index 6d56ad362..9975e095d 100644 --- a/lib/src/screens/ionia/cards/ionia_buy_card_detail_page.dart +++ b/lib/src/screens/ionia/cards/ionia_buy_card_detail_page.dart @@ -58,11 +58,7 @@ class IoniaBuyGiftCardDetailPage extends StatelessWidget { Widget middle(BuildContext context) { return Text( merchant.legalName, - style: TextStyle( - fontSize: 22, - fontFamily: 'Lato', - fontWeight: FontWeight.w900, - ), + style: textLargeSemiBold(color: Theme.of(context).accentTextTheme.display4.backgroundColor), ); } diff --git a/lib/src/screens/ionia/cards/ionia_buy_gift_card.dart b/lib/src/screens/ionia/cards/ionia_buy_gift_card.dart index e46b9ea0a..fc16db938 100644 --- a/lib/src/screens/ionia/cards/ionia_buy_gift_card.dart +++ b/lib/src/screens/ionia/cards/ionia_buy_gift_card.dart @@ -69,6 +69,7 @@ class IoniaBuyGiftCardPage extends BasePage { child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox(height: 150), BaseTextFormField( @@ -79,7 +80,7 @@ class IoniaBuyGiftCardPage extends BasePage { hintText: '1000', placeholderTextStyle: TextStyle( color: Theme.of(context).primaryTextTheme.headline.color, - fontWeight: FontWeight.w500, + fontWeight: FontWeight.w600, fontSize: 36, ), borderColor: Theme.of(context).primaryTextTheme.headline.color, @@ -100,7 +101,7 @@ class IoniaBuyGiftCardPage extends BasePage { '${merchant.acceptedCurrency}: ', style: TextStyle( color: Colors.white, - fontWeight: FontWeight.w900, + fontWeight: FontWeight.w600, fontSize: 36, ), ), @@ -109,6 +110,7 @@ class IoniaBuyGiftCardPage extends BasePage { SizedBox(height: 8), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( S.of(context).min_amount(merchant.minimumCardPurchase.toString()), @@ -133,7 +135,7 @@ class IoniaBuyGiftCardPage extends BasePage { child: CardItem( title: merchant.legalName, backgroundColor: Theme.of(context).accentTextTheme.display4.backgroundColor.withOpacity(0.1), - discount: 0.0, + discount: merchant.minimumDiscount, titleColor: Theme.of(context).accentTextTheme.display4.backgroundColor, subtitleColor: Theme.of(context).hintColor, subTitle: merchant.isOnline ? S.of(context).online : S.of(context).offline, @@ -147,10 +149,15 @@ class IoniaBuyGiftCardPage extends BasePage { Padding( padding: EdgeInsets.only(bottom: 12), child: PrimaryButton( - onPressed: () => Navigator.of(context).pushNamed(Routes.ioniaBuyGiftCardDetailPage, arguments: [merchant] ), + onPressed: () { + Navigator.of(context).pushNamed(Routes.ioniaBuyGiftCardDetailPage, arguments: [merchant] ); + }, text: S.of(context).continue_text, color: Theme.of(context).accentTextTheme.body2.color, - textColor: Theme.of(context).primaryTextTheme.body1.color, + textColor: Theme.of(context) + .accentTextTheme + .headline + .decorationColor, ), ), SizedBox(height: 30), diff --git a/lib/src/screens/ionia/cards/ionia_debit_card_page.dart b/lib/src/screens/ionia/cards/ionia_debit_card_page.dart index 0d2a6294f..42684e8ff 100644 --- a/lib/src/screens/ionia/cards/ionia_debit_card_page.dart +++ b/lib/src/screens/ionia/cards/ionia_debit_card_page.dart @@ -22,11 +22,8 @@ class IoniaDebitCardPage extends BasePage { Widget middle(BuildContext context) { return Text( S.current.debit_card, - style: TextStyle( - fontSize: 22, - fontFamily: 'Lato', + style: textLargeSemiBold( color: Theme.of(context).accentTextTheme.display4.backgroundColor, - fontWeight: FontWeight.w900, ), ); } diff --git a/lib/src/screens/ionia/cards/ionia_manage_cards_page.dart b/lib/src/screens/ionia/cards/ionia_manage_cards_page.dart index a2f885774..15ce9e644 100644 --- a/lib/src/screens/ionia/cards/ionia_manage_cards_page.dart +++ b/lib/src/screens/ionia/cards/ionia_manage_cards_page.dart @@ -1,19 +1,19 @@ +import 'package:cake_wallet/ionia/ionia_merchant.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/ionia/widgets/card_item.dart'; import 'package:cake_wallet/src/screens/ionia/widgets/card_menu.dart'; -import 'package:cake_wallet/src/widgets/market_place_item.dart'; +import 'package:cake_wallet/src/widgets/cake_scrollbar.dart'; import 'package:cake_wallet/themes/theme_base.dart'; +import 'package:cake_wallet/typography.dart'; import 'package:cake_wallet/view_model/ionia/ionia_view_model.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:mobx/mobx.dart'; class IoniaManageCardsPage extends BasePage { - IoniaManageCardsPage(this._ioniaViewModel); - + IoniaManageCardsPage(this._ioniaViewModel); final IoniaViewModel _ioniaViewModel; @override @@ -64,7 +64,7 @@ class IoniaManageCardsPage extends BasePage { highlightColor: Colors.transparent, splashColor: Colors.transparent, padding: EdgeInsets.all(0), - onPressed: () => Navigator.pushReplacementNamed(context, Routes.dashboard), + onPressed: () => Navigator.pop(context), child: _backButton), ), ); @@ -74,113 +74,43 @@ class IoniaManageCardsPage extends BasePage { Widget middle(BuildContext context) { return Text( S.of(context).manage_cards, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.w500, + style: textLargeSemiBold( color: Theme.of(context).accentTextTheme.display3.backgroundColor, ), ); } - final ScrollController _scrollController = ScrollController(); @override Widget trailing(BuildContext context) { - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - _TrailingIcon( - asset: 'assets/images/card.png', - onPressed: () => Navigator.pushNamed(context, Routes.ioniaDebitCardPage), - ), - SizedBox(width: 16), + return _TrailingIcon( asset: 'assets/images/profile.png', onPressed: () {}, - ), - ], ); } @override Widget body(BuildContext context) { - final filterIcon = Image.asset( - 'assets/images/filter.png', - color: Theme.of(context).textTheme.caption.decorationColor, - ); return Padding( padding: const EdgeInsets.all(14.0), child: Column( children: [ - MarketPlaceItem( - onTap: () {}, - title: S.of(context).setup_your_debit_card, - subTitle: S.of(context).no_id_required, - ), - SizedBox(height: 48), Container( padding: EdgeInsets.only(left: 2, right: 22), height: 32, - child: Row( - children: [ - Expanded(child: _SearchWidget()), - SizedBox(width: 10), - Container( - width: 32, - padding: EdgeInsets.all(8), - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.15), - border: Border.all( - color: Colors.white.withOpacity(0.2), - ), - borderRadius: BorderRadius.circular(10), - ), - child: filterIcon, - ) - ], - ), + child: _SearchWidget() + ), SizedBox(height: 8), Expanded( - child: Observer( - builder: (_) { - final merchantsList = _ioniaViewModel.ioniaMerchants; - return RawScrollbar( - thumbColor: Colors.white.withOpacity(0.15), - radius: Radius.circular(20), - isAlwaysShown: true, - thickness: 2, - controller: _scrollController, - child: ListView.separated( - padding: EdgeInsets.only(left: 2, right: 22), - controller: _scrollController, - itemCount: merchantsList.length, - separatorBuilder: (_, __) => SizedBox(height: 4), - itemBuilder: (_, index) { - final merchant = merchantsList[index]; - return CardItem( - logoUrl: merchant.logoUrl, - onTap: () => Navigator.of(context).pushNamed(Routes.ioniaBuyGiftCardPage, - arguments: [merchant]), - title: merchant.legalName, - subTitle: merchant.isOnline ? S.of(context).online : S.of(context).offline, - backgroundColor: Theme.of(context).textTheme.title.backgroundColor, - titleColor: Theme.of(context) - .accentTextTheme - .display3 - .backgroundColor, - subtitleColor: Theme.of(context) - .accentTextTheme - .display2 - .backgroundColor, - discount: merchant.minimumDiscount, - ); - }, - ), - ); - } - ), + child: Observer(builder: (_) { + return IoniaManageCardsPageBody(scrollOffsetFromTop: _ioniaViewModel.scrollOffsetFromTop, + ioniaMerchants: _ioniaViewModel.ioniaMerchants, + onSetScrollOffset: (offset) => _ioniaViewModel.setScrollOffsetFromTop(offset), + ); + }), ), ], ), @@ -188,6 +118,81 @@ class IoniaManageCardsPage extends BasePage { } } +class IoniaManageCardsPageBody extends StatefulWidget { + const IoniaManageCardsPageBody({ + Key key, + @required this.scrollOffsetFromTop, + @required this.ioniaMerchants, + @required this.onSetScrollOffset, + }) : super(key: key); + + + final List<IoniaMerchant> ioniaMerchants; + final double scrollOffsetFromTop; + final Function(double) onSetScrollOffset; + + @override + _IoniaManageCardsPageBodyState createState() => _IoniaManageCardsPageBodyState(); +} + +class _IoniaManageCardsPageBodyState extends State<IoniaManageCardsPageBody> { + + double get backgroundHeight => MediaQuery.of(context).size.height * 0.75; + double thumbHeight = 72; + bool get isAlwaysShowScrollThumb => merchantsList == null ? false : merchantsList.length > 3; + + + List<IoniaMerchant> get merchantsList => widget.ioniaMerchants; + + final _scrollController = ScrollController(); + +@override + void initState() { + _scrollController.addListener(() { + final scrollOffsetFromTop = _scrollController.hasClients + ? (_scrollController.offset / _scrollController.position.maxScrollExtent * (backgroundHeight - thumbHeight)) + : 0.0; + widget.onSetScrollOffset(scrollOffsetFromTop); + }); + super.initState(); + } + @override + Widget build(BuildContext context) { + return Stack(children: [ + ListView.separated( + padding: EdgeInsets.only(left: 2, right: 22), + controller: _scrollController, + itemCount: merchantsList.length, + separatorBuilder: (_, __) => SizedBox(height: 4), + itemBuilder: (_, index) { + final merchant = merchantsList[index]; + return CardItem( + logoUrl: merchant.logoUrl, + onTap: () => Navigator.of(context).pushNamed(Routes.ioniaBuyGiftCardPage, arguments: [merchant]), + title: merchant.legalName, + subTitle: merchant.isOnline ? S.of(context).online : S.of(context).offline, + backgroundColor: Theme.of(context).textTheme.title.backgroundColor, + titleColor: Theme.of(context).accentTextTheme.display3.backgroundColor, + subtitleColor: Theme.of(context).accentTextTheme.display2.backgroundColor, + discount: merchant.minimumDiscount, + ); + }, + ), + isAlwaysShowScrollThumb + ? CakeScrollbar( + backgroundHeight: backgroundHeight, + thumbHeight: thumbHeight, + rightOffset: 1, + width: 3, + backgroundColor: Theme.of(context).textTheme.caption.decorationColor.withOpacity(0.05), + thumbColor: Theme.of(context).textTheme.caption.decorationColor.withOpacity(0.5), + fromTop: widget.scrollOffsetFromTop, + ) + : Offstage() + ]); + } +} + class _SearchWidget extends StatelessWidget { const _SearchWidget({ Key key, @@ -212,7 +217,7 @@ class _SearchWidget extends StatelessWidget { left: 10, ), fillColor: Colors.white.withOpacity(0.15), - hintText: 'Search', + hintText: S.of(context).search, hintStyle: TextStyle( color: Colors.white.withOpacity(0.6), ), @@ -263,3 +268,5 @@ class _TrailingIcon extends StatelessWidget { ); } } + + diff --git a/lib/src/screens/ionia/widgets/card_item.dart b/lib/src/screens/ionia/widgets/card_item.dart index 38946da5a..9a46072fd 100644 --- a/lib/src/screens/ionia/widgets/card_item.dart +++ b/lib/src/screens/ionia/widgets/card_item.dart @@ -46,8 +46,9 @@ class CardItem extends StatelessWidget { ClipOval( child: Image.network( logoUrl, - width: 42.0, - height: 42.0, + width: 40.0, + height: 40.0, + fit: BoxFit.cover, loadingBuilder: (BuildContext _, Widget child, ImageChunkEvent loadingProgress) { if (loadingProgress == null) { return child; diff --git a/lib/src/widgets/cake_scrollbar.dart b/lib/src/widgets/cake_scrollbar.dart index 6ccf391c6..6a0cb2e14 100644 --- a/lib/src/widgets/cake_scrollbar.dart +++ b/lib/src/widgets/cake_scrollbar.dart @@ -5,13 +5,19 @@ class CakeScrollbar extends StatelessWidget { @required this.backgroundHeight, @required this.thumbHeight, @required this.fromTop, - this.rightOffset = 6 + this.rightOffset = 6, + this.backgroundColor, + this.thumbColor, + this.width = 6, }); final double backgroundHeight; final double thumbHeight; final double fromTop; + final double width; final double rightOffset; + final Color backgroundColor; + final Color thumbColor; @override Widget build(BuildContext context) { @@ -19,11 +25,10 @@ class CakeScrollbar extends StatelessWidget { right: rightOffset, child: Container( height: backgroundHeight, - width: 6, + width: width, decoration: BoxDecoration( - color: Theme.of(context).textTheme.body1.decorationColor, - borderRadius: BorderRadius.all(Radius.circular(3)) - ), + color: backgroundColor ?? Theme.of(context).textTheme.body1.decorationColor, + borderRadius: BorderRadius.all(Radius.circular(3))), child: Stack( children: <Widget>[ AnimatedPositioned( @@ -31,16 +36,14 @@ class CakeScrollbar extends StatelessWidget { top: fromTop, child: Container( height: thumbHeight, - width: 6.0, + width: width, decoration: BoxDecoration( - color: Theme.of(context).textTheme.body1.color, - borderRadius: BorderRadius.all(Radius.circular(3)) - ), + color: thumbColor ?? Theme.of(context).textTheme.body1.color, + borderRadius: BorderRadius.all(Radius.circular(3))), ), ) ], ), - ) - ); + )); } -} \ No newline at end of file +} diff --git a/lib/src/widgets/discount_badge.dart b/lib/src/widgets/discount_badge.dart index c3f9e2148..d4e9836b2 100644 --- a/lib/src/widgets/discount_badge.dart +++ b/lib/src/widgets/discount_badge.dart @@ -12,23 +12,22 @@ class DiscountBadge extends StatelessWidget { @override Widget build(BuildContext context) { - return Stack( - alignment: Alignment.centerRight, - children: [ - Image.asset('assets/images/badge_discount.png'), - Padding( - padding: const EdgeInsets.only(right: 10.0), - child: Text( - S.of(context).discount(percentage.toString()), - style: TextStyle( - color: Colors.white, - fontSize: 12, - fontWeight: FontWeight.w500, - fontFamily: 'Lato', - ), + return Container( + padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4), + child: Text( S.of(context).discount(percentage.toString()), + style: TextStyle( + color: Colors.white, + fontSize: 12, + fontWeight: FontWeight.w500, + fontFamily: 'Lato', ), - ) - ], - ); - } + ), + decoration: BoxDecoration( + image: DecorationImage( + fit: BoxFit.fill, + image: AssetImage('assets/images/badge_discount.png'), + ), + ), + ); + } } diff --git a/lib/view_model/ionia/ionia_view_model.dart b/lib/view_model/ionia/ionia_view_model.dart index cc2483890..34cdcf31a 100644 --- a/lib/view_model/ionia/ionia_view_model.dart +++ b/lib/view_model/ionia/ionia_view_model.dart @@ -8,12 +8,13 @@ part 'ionia_view_model.g.dart'; class IoniaViewModel = IoniaViewModelBase with _$IoniaViewModel; abstract class IoniaViewModelBase with Store { - IoniaViewModelBase({this.ioniaService}) : createUserState = IoniaCreateStateSuccess(), otpState = IoniaOtpSendDisabled(), - cardState = IoniaNoCardState(), ioniaMerchants = [] { - _getMerchants().then((value){ + cardState = IoniaNoCardState(), + ioniaMerchants = [], + scrollOffsetFromTop = 0.0 { + _getMerchants().then((value) { ioniaMerchants = value; }); _getAuthStatus().then((value) => isLoggedIn = value); @@ -21,6 +22,9 @@ abstract class IoniaViewModelBase with Store { final IoniaService ioniaService; + @observable + double scrollOffsetFromTop; + @observable IoniaCreateAccountState createUserState; @@ -96,7 +100,11 @@ abstract class IoniaViewModelBase with Store { } } - Future<List<IoniaMerchant>> _getMerchants()async{ + Future<List<IoniaMerchant>> _getMerchants() async { return await ioniaService.getMerchants(); } + + void setScrollOffsetFromTop(double scrollOffset) { + scrollOffsetFromTop = scrollOffset; + } } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index c5cf06877..d90b75875 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -550,7 +550,7 @@ "purchase_gift_card": "Purchase Gift Card", "verification": "Verification", "fill_code": "Please fill in the verification code provided to your email", - "dont_get_code": "Don't get code", + "dont_get_code": "Don't get code?", "resend_code": "Please resend it", "debit_card": "Debit Card", "cakepay_prepaid_card": "CakePay Prepaid Debit Card",