From f353442a2a298aaa45a184b768d4d1daca19afad Mon Sep 17 00:00:00 2001 From: OleksandrSobol Date: Fri, 1 Oct 2021 18:13:10 +0300 Subject: [PATCH] CAKE-360 | merged all yat branches into current; saving information about yat to connected wallet; fixed qr widget; applied yat, unstoppable domains and open alias to contact book --- assets/images/emoji_popup.png | Bin 0 -> 5390 bytes lib/di.dart | 10 +- lib/entities/parse_address_from_domain.dart | 2 +- lib/entities/wallet_info.dart | 20 +- lib/main.dart | 20 +- lib/src/screens/contact/contact_page.dart | 6 +- lib/src/screens/dashboard/dashboard_page.dart | 12 +- lib/src/screens/exchange/exchange_page.dart | 18 ++ .../exchange/widgets/exchange_card.dart | 7 +- .../screens/receive/widgets/qr_widget.dart | 4 +- lib/src/screens/send/widgets/send_card.dart | 6 +- .../yat/widgets/first_introduction.dart | 90 +++++++++ .../yat/widgets/second_introduction.dart | 89 +++++++++ .../yat/widgets/third_introduction.dart | 109 +++++++++++ .../yat/widgets/yat_page_indicator.dart | 33 ++++ lib/src/screens/yat/yat_alert.dart | 58 ++---- lib/src/screens/yat/yat_popup.dart | 178 ++++++++++++++++++ lib/{ => store}/yat/yat_exception.dart | 0 lib/store/yat/yat_store.dart | 166 ++++++++++++++++ lib/store/yat_store.dart | 12 -- .../dashboard/dashboard_view_model.dart | 16 ++ .../settings/settings_view_model.dart | 5 +- .../wallet_address_list_view_model.dart | 2 +- lib/yat/yat_record.dart | 31 --- pubspec.lock | 7 + pubspec.yaml | 1 + 26 files changed, 789 insertions(+), 113 deletions(-) create mode 100644 assets/images/emoji_popup.png create mode 100644 lib/src/screens/yat/widgets/first_introduction.dart create mode 100644 lib/src/screens/yat/widgets/second_introduction.dart create mode 100644 lib/src/screens/yat/widgets/third_introduction.dart create mode 100644 lib/src/screens/yat/widgets/yat_page_indicator.dart create mode 100644 lib/src/screens/yat/yat_popup.dart rename lib/{ => store}/yat/yat_exception.dart (100%) create mode 100644 lib/store/yat/yat_store.dart delete mode 100644 lib/store/yat_store.dart delete mode 100644 lib/yat/yat_record.dart diff --git a/assets/images/emoji_popup.png b/assets/images/emoji_popup.png new file mode 100644 index 0000000000000000000000000000000000000000..5fa494bb645c0018db19537b497a4007c8d6b900 GIT binary patch literal 5390 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 literal 0 HcmV?d00001 diff --git a/lib/di.dart b/lib/di.dart index 6377e65f3..31baa3f6b 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -62,7 +62,7 @@ import 'package:cake_wallet/src/screens/send/send_page.dart'; import 'package:cake_wallet/src/screens/subaddress/address_edit_or_create_page.dart'; import 'package:cake_wallet/src/screens/wallet_list/wallet_list_page.dart'; import 'package:cake_wallet/store/wallet_list_store.dart'; -import 'package:cake_wallet/store/yat_store.dart'; +import 'package:cake_wallet/store/yat/yat_store.dart'; import 'package:cake_wallet/view_model/backup_view_model.dart'; import 'package:cake_wallet/view_model/buy/buy_amount_view_model.dart'; import 'package:cake_wallet/view_model/buy/buy_view_model.dart'; @@ -193,7 +193,9 @@ Future setup( SendTemplateStore(templateSource: _templates)); getIt.registerSingleton( ExchangeTemplateStore(templateSource: _exchangeTemplates)); - getIt.registerSingleton(YatStore()); + getIt.registerSingleton(YatStore( + appStore: getIt.get() + )); final secretStore = await SecretStoreBase.load(getIt.get()); @@ -254,6 +256,7 @@ Future setup( tradeFilterStore: getIt.get(), transactionFilterStore: getIt.get(), settingsStore: settingsStore, + yatStore: getIt.get(), ordersStore: getIt.get())); getIt.registerFactory(() => AuthService( @@ -391,7 +394,8 @@ Future setup( getIt.registerFactory(() { final appStore = getIt.get(); - return SettingsViewModel(appStore.settingsStore, appStore.wallet); + final yatStore = getIt.get(); + return SettingsViewModel(appStore.settingsStore, yatStore, appStore.wallet); }); getIt.registerFactory(() => SettingsPage(getIt.get())); diff --git a/lib/entities/parse_address_from_domain.dart b/lib/entities/parse_address_from_domain.dart index 3041c4709..851251df6 100644 --- a/lib/entities/parse_address_from_domain.dart +++ b/lib/entities/parse_address_from_domain.dart @@ -1,7 +1,7 @@ import 'package:cake_wallet/entities/openalias_record.dart'; import 'package:cake_wallet/entities/parsed_address.dart'; import 'package:cake_wallet/entities/unstoppable_domain_address.dart'; -import 'package:cake_wallet/yat/yat_record.dart'; +import 'package:cake_wallet/store/yat/yat_store.dart'; const unstoppableDomains = [ 'crypto', diff --git a/lib/entities/wallet_info.dart b/lib/entities/wallet_info.dart index 9dfb2011b..85a9af470 100644 --- a/lib/entities/wallet_info.dart +++ b/lib/entities/wallet_info.dart @@ -7,7 +7,8 @@ part 'wallet_info.g.dart'; @HiveType(typeId: WalletInfo.typeId) class WalletInfo extends HiveObject { WalletInfo(this.id, this.name, this.type, this.isRecovery, this.restoreHeight, - this.timestamp, this.dirPath, this.path, this.address); + this.timestamp, this.dirPath, this.path, this.address, this.yatEid, + this.yatRefreshToken); factory WalletInfo.external( {@required String id, @@ -18,9 +19,12 @@ class WalletInfo extends HiveObject { @required DateTime date, @required String dirPath, @required String path, - @required String address}) { + @required String address, + String yatEid ='', + String yatRefreshToken = ''}) { return WalletInfo(id, name, type, isRecovery, restoreHeight, - date.millisecondsSinceEpoch ?? 0, dirPath, path, address); + date.millisecondsSinceEpoch ?? 0, dirPath, path, address, + yatEid, yatRefreshToken); } static const typeId = 4; @@ -56,5 +60,15 @@ class WalletInfo extends HiveObject { @HiveField(10) Map addresses; + @HiveField(11) + String yatEid; + + @HiveField(12) + String yatRefreshToken; + + String get yatEmojiId => yatEid ?? ''; + + String get yatToken => yatRefreshToken ?? ''; + DateTime get date => DateTime.fromMillisecondsSinceEpoch(timestamp); } diff --git a/lib/main.dart b/lib/main.dart index e71a6c198..fd22b9fae 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'package:cake_wallet/bitcoin/unspent_coins_info.dart'; import 'package:cake_wallet/entities/language_service.dart'; import 'package:cake_wallet/buy/order.dart'; -import 'package:cake_wallet/store/yat_store.dart'; +import 'package:cake_wallet/store/yat/yat_store.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -190,8 +190,8 @@ class AppState extends State with SingleTickerProviderStateMixin { @override void initState() { super.initState(); - _handleIncomingLinks(yatStore); - _handleInitialUri(yatStore); + _handleIncomingLinks(); + _handleInitialUri(); } @override @@ -200,25 +200,25 @@ class AppState extends State with SingleTickerProviderStateMixin { super.dispose(); } - Future _handleInitialUri(YatStore yatStore) async { + Future _handleInitialUri() async { try { final uri = await getInitialUri(); if (uri == null) { return; } if (!mounted) return; - _fetchEmojiFromUri(uri, yatStore); + _fetchEmojiFromUri(uri); } catch (e) { if (!mounted) return; print(e.toString()); } } - void _handleIncomingLinks(YatStore yatStore) { + void _handleIncomingLinks() { if (!kIsWeb) { stream = getUriLinksStream().listen((Uri uri) { if (!mounted) return; - _fetchEmojiFromUri(uri, yatStore); + _fetchEmojiFromUri(uri); }, onError: (Object error) { if (!mounted) return; print('Error: $error'); @@ -226,16 +226,18 @@ class AppState extends State with SingleTickerProviderStateMixin { } } - void _fetchEmojiFromUri(Uri uri, YatStore yatStore) { + void _fetchEmojiFromUri(Uri uri) { final queryParameters = uri.queryParameters; if (queryParameters?.isEmpty ?? true) { return; } final emoji = queryParameters['eid']; - if (emoji?.isEmpty ?? true) { + final refreshToken = queryParameters['refresh_token']; + if ((emoji?.isEmpty ?? true)||(refreshToken?.isEmpty ?? true)) { return; } yatStore.emoji = emoji; + yatStore.refreshToken = refreshToken; } @override diff --git a/lib/src/screens/contact/contact_page.dart b/lib/src/screens/contact/contact_page.dart index a65a86e29..be8ac900d 100644 --- a/lib/src/screens/contact/contact_page.dart +++ b/lib/src/screens/contact/contact_page.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/core/validator.dart'; import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; @@ -97,8 +98,9 @@ class ContactPage extends BasePage { buttonColor: Theme.of(context).accentTextTheme.display2.color, iconColor: PaletteDark.gray, borderColor: Theme.of(context).primaryTextTheme.title.backgroundColor, - validator: AddressValidator( - type: contactViewModel.currency), + validator: TextValidator() + // AddressValidator( + // type: contactViewModel.currency), )), ) ], diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index 9ec03ea19..a7070f5ce 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/entities/wallet_type.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/yat/yat_popup.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; @@ -145,7 +146,7 @@ class DashboardPage extends BasePage { )); } - void _setEffects(BuildContext context) { + void _setEffects(BuildContext context) async { if (_isEffectsInstalled) { return; } @@ -155,6 +156,15 @@ class DashboardPage extends BasePage { pages.add(BalancePage(dashboardViewModel: walletViewModel)); pages.add(TransactionsPage(dashboardViewModel: walletViewModel)); + await Future.delayed(Duration(seconds: 1)); + await showPopUp( + context: context, + builder: (BuildContext context) { + return YatPopup( + dashboardViewModel: walletViewModel, + onClose: () => Navigator.of(context).pop()); + }); + autorun((_) async { if (!walletViewModel.isOutdatedElectrumWallet) { return; diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 9af3d1fa5..ca8ef2af6 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -235,6 +235,15 @@ class ExchangePage extends BasePage { await fetchParsedAddress( context, domain, ticker); }, + onPushAddressBookButton: (context) async { + final domain = + exchangeViewModel.depositAddress; + final ticker = exchangeViewModel + .depositCurrency.title.toLowerCase(); + exchangeViewModel.depositAddress = + await fetchParsedAddress( + context, domain, ticker); + }, ), ), ), @@ -291,6 +300,15 @@ class ExchangePage extends BasePage { await fetchParsedAddress( context, domain, ticker); }, + onPushAddressBookButton: (context) async { + final domain = + exchangeViewModel.receiveAddress; + final ticker = exchangeViewModel + .receiveCurrency.title.toLowerCase(); + exchangeViewModel.receiveAddress = + await fetchParsedAddress( + context, domain, ticker); + }, )), ) ], diff --git a/lib/src/screens/exchange/widgets/exchange_card.dart b/lib/src/screens/exchange/widgets/exchange_card.dart index 23f235c65..727d6808f 100644 --- a/lib/src/screens/exchange/widgets/exchange_card.dart +++ b/lib/src/screens/exchange/widgets/exchange_card.dart @@ -34,7 +34,8 @@ class ExchangeCard extends StatefulWidget { this.addressFocusNode, this.hasAllAmount = false, this.allAmount, - this.onPushPasteButton}) + this.onPushPasteButton, + this.onPushAddressBookButton}) : super(key: key); final List currencies; @@ -59,6 +60,7 @@ class ExchangeCard extends StatefulWidget { final bool hasAllAmount; final Function allAmount; final Function(BuildContext context) onPushPasteButton; + final Function(BuildContext context) onPushAddressBookButton; @override ExchangeCardState createState() => ExchangeCardState(); @@ -321,6 +323,7 @@ class ExchangeCardState extends State { buttonColor: widget.addressButtonsColor, validator: widget.addressTextFieldValidator, onPushPasteButton: widget.onPushPasteButton, + onPushAddressBookButton: widget.onPushAddressBookButton ), ) : Padding( @@ -366,6 +369,8 @@ class ExchangeCardState extends State { setState(() => addressController.text = contact.address); + widget.onPushAddressBookButton + ?.call(context); } }, child: Container( diff --git a/lib/src/screens/receive/widgets/qr_widget.dart b/lib/src/screens/receive/widgets/qr_widget.dart index 0fcfe62c9..7406b131c 100644 --- a/lib/src/screens/receive/widgets/qr_widget.dart +++ b/lib/src/screens/receive/widgets/qr_widget.dart @@ -101,7 +101,7 @@ class QRWidget extends StatelessWidget { ), ), Padding( - padding: EdgeInsets.only(top: 16, bottom: 16), + padding: EdgeInsets.only(top: 10, bottom: 10), child: Builder( builder: (context) => Observer( builder: (context) => GestureDetector( @@ -164,7 +164,7 @@ class QRWidget extends StatelessWidget { addressListViewModel.emoji, textAlign: TextAlign.center, style: TextStyle( - fontSize: 13, + fontSize: 26, ), ) ) diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 2f08cc143..17e5df519 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -156,8 +156,10 @@ class SendCardState extends State output.resetParsedAddress(); await output.fetchParsedAddress(context); }, - onPushAddressBookButton: (context) => - output.resetParsedAddress(), + onPushAddressBookButton: (context) async { + output.resetParsedAddress(); + await output.fetchParsedAddress(context); + }, validator: validator, ); }), diff --git a/lib/src/screens/yat/widgets/first_introduction.dart b/lib/src/screens/yat/widgets/first_introduction.dart new file mode 100644 index 000000000..0e045b113 --- /dev/null +++ b/lib/src/screens/yat/widgets/first_introduction.dart @@ -0,0 +1,90 @@ +import 'package:cake_wallet/src/screens/yat/widgets/yat_bar.dart'; +import 'package:cake_wallet/src/screens/yat/widgets/yat_page_indicator.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:lottie/lottie.dart'; + +class FirstIntroduction extends StatelessWidget { + FirstIntroduction({this.onClose, this.onNext}); + + static const aspectRatioImage = 1.133; + final VoidCallback onClose; + final VoidCallback onNext; + final animation = Lottie.asset('assets/animation/anim1.json'); + + @override + Widget build(BuildContext context) { + final screenHeight = MediaQuery.of(context).size.height; + final screenWidth = MediaQuery.of(context).size.width; + + return Container( + height: screenHeight, + width: screenWidth, + color: Colors.white, + child: ScrollableWithBottomSection( + contentPadding: EdgeInsets.only(top: 40, bottom: 40), + content: Column( + children: [ + Container( + height: 45, + padding: EdgeInsets.only(left: 24, right: 24), + child: YatBar(onClose: () => Navigator.of(context).pop()) + ), + animation, + Container( + padding: EdgeInsets.only(left: 30, right: 30), + child: Column( + children: [ + Text( + 'Send and receive crypto more easily with Yat', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + fontFamily: 'Lato', + color: Colors.black, + decoration: TextDecoration.none, + ) + ), + Padding( + padding: EdgeInsets.only(top: 20), + child: Text( + 'Cake Wallet users can now send and receive all their favorite currencies with a one-of-a-kind emoji-based username.', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.normal, + fontFamily: 'Lato', + color: Colors.black, + decoration: TextDecoration.none, + ) + ) + ) + ] + ) + ) + ] + ), + bottomSectionPadding: EdgeInsets.fromLTRB(24, 0, 24, 24), + bottomSection: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + PrimaryButton( + text: 'Next', + textColor: Colors.white, + color: Palette.protectiveBlue, + onPressed: onNext + ), + Padding( + padding: EdgeInsets.only(top: 24), + child: YatPageIndicator(filled: 0) + ) + ] + ), + ) + ); + } +} \ No newline at end of file diff --git a/lib/src/screens/yat/widgets/second_introduction.dart b/lib/src/screens/yat/widgets/second_introduction.dart new file mode 100644 index 000000000..46c47876e --- /dev/null +++ b/lib/src/screens/yat/widgets/second_introduction.dart @@ -0,0 +1,89 @@ +import 'package:cake_wallet/src/screens/yat/widgets/yat_bar.dart'; +import 'package:cake_wallet/src/screens/yat/widgets/yat_page_indicator.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:lottie/lottie.dart'; + +class SecondIntroduction extends StatelessWidget { + SecondIntroduction({this.onClose, this.onNext}); + + final VoidCallback onClose; + final VoidCallback onNext; + final animation = Lottie.asset('assets/animation/anim2.json'); + + @override + Widget build(BuildContext context) { + final screenHeight = MediaQuery.of(context).size.height; + final screenWidth = MediaQuery.of(context).size.width; + + return Container( + height: screenHeight, + width: screenWidth, + color: Colors.white, + child: ScrollableWithBottomSection( + contentPadding: EdgeInsets.only(top: 40, bottom: 40), + content: Column( + children: [ + Container( + height: 45, + padding: EdgeInsets.only(left: 24, right: 24), + child: YatBar(onClose: onClose) + ), + animation, + Padding( + padding: EdgeInsets.only(top: 40, left: 30, right: 30), + child: Column( + children: [ + Text( + 'One emoji address to rule them all', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + fontFamily: 'Lato', + color: Colors.black, + decoration: TextDecoration.none, + ) + ), + Padding( + padding: EdgeInsets.only(top: 20), + child: Text( + 'Your Yat is a single unique emoji address that replaces all of your long hexadecimal addresses for all of your currencies.', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.normal, + fontFamily: 'Lato', + color: Colors.black, + decoration: TextDecoration.none, + ) + ) + ) + ] + ), + ), + ], + ), + bottomSectionPadding: EdgeInsets.fromLTRB(24, 0, 24, 24), + bottomSection: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + PrimaryButton( + text: 'Next', + textColor: Colors.white, + color: Palette.protectiveBlue, + onPressed: onNext + ), + Padding( + padding: EdgeInsets.only(top: 24), + child: YatPageIndicator(filled: 1) + ) + ] + ), + ) + ); + } +} \ No newline at end of file diff --git a/lib/src/screens/yat/widgets/third_introduction.dart b/lib/src/screens/yat/widgets/third_introduction.dart new file mode 100644 index 000000000..0b4bce169 --- /dev/null +++ b/lib/src/screens/yat/widgets/third_introduction.dart @@ -0,0 +1,109 @@ +import 'package:cake_wallet/src/screens/yat/widgets/yat_bar.dart'; +import 'package:cake_wallet/src/screens/yat/widgets/yat_page_indicator.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:lottie/lottie.dart'; + +class ThirdIntroduction extends StatelessWidget { + ThirdIntroduction({this.onClose, this.onGet, this.onConnect}); + + final VoidCallback onClose; + final VoidCallback onGet; + final VoidCallback onConnect; + final animation = Lottie.asset('assets/animation/anim3.json'); + + @override + Widget build(BuildContext context) { + final screenHeight = MediaQuery.of(context).size.height; + final screenWidth = MediaQuery.of(context).size.width; + + return Container( + height: screenHeight, + width: screenWidth, + color: Colors.white, + child: ScrollableWithBottomSection( + contentPadding: EdgeInsets.only(top: 40, bottom: 40), + content: Column( + children: [ + Container( + height: 90, + padding: EdgeInsets.only(left: 24, right: 24), + child: YatBar(onClose: onClose) + ), + animation, + Padding( + padding: EdgeInsets.only(top: 40, left: 30, right: 30), + child: Column( + children: [ + Text( + 'Yat plays nicely with others', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + fontFamily: 'Lato', + color: Colors.black, + decoration: TextDecoration.none, + ) + ), + Padding( + padding: EdgeInsets.only(top: 20), + child: Text( + 'Yats live outside of Cake Wallet, too. Any wallet address on earth can be replaced with a Yat!', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.normal, + fontFamily: 'Lato', + color: Colors.black, + decoration: TextDecoration.none, + ) + ) + ) + ] + ) + ), + ], + ), + bottomSectionPadding: EdgeInsets.fromLTRB(24, 0, 24, 24), + bottomSection: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + PrimaryIconButton( + text: 'Get your Yat', + textColor: Colors.white, + color: Palette.protectiveBlue, + borderColor: Palette.protectiveBlue, + iconColor: Colors.white, + iconBackgroundColor: Colors.transparent, + iconData: CupertinoIcons + .arrow_up_right_square, + mainAxisAlignment: MainAxisAlignment.end, + onPressed: onGet), + Padding( + padding: EdgeInsets.only(top: 12), + child: PrimaryIconButton( + text: 'Connect an existing Yat', + textColor: Colors.black, + color: Palette.blueAlice, + borderColor: Palette.blueAlice, + iconColor: Colors.black, + iconBackgroundColor: Colors.transparent, + iconData: CupertinoIcons + .arrow_up_right_square, + mainAxisAlignment: MainAxisAlignment.end, + onPressed: onConnect) + ), + Padding( + padding: EdgeInsets.only(top: 24), + child: YatPageIndicator(filled: 2) + ) + ] + ), + ) + ); + } +} \ No newline at end of file diff --git a/lib/src/screens/yat/widgets/yat_page_indicator.dart b/lib/src/screens/yat/widgets/yat_page_indicator.dart new file mode 100644 index 000000000..856dc3b32 --- /dev/null +++ b/lib/src/screens/yat/widgets/yat_page_indicator.dart @@ -0,0 +1,33 @@ +import 'package:flutter/material.dart'; +import 'package:cake_wallet/palette.dart'; + +class YatPageIndicator extends StatelessWidget { + YatPageIndicator({this.filled}); + + final int filled; + + @override + Widget build(BuildContext context) { + return Container( + width: 44, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: List.generate(3, (index) { + final size = 8.0; + final isFilled = index == filled; + + return Container( + height: size, + width: size, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: isFilled + ? Palette.frostySky + : Palette.stateGray.withOpacity(0.1) + ) + ); + }) + ) + ); + } +} \ No newline at end of file diff --git a/lib/src/screens/yat/yat_alert.dart b/lib/src/screens/yat/yat_alert.dart index 12c30c60f..7c97e6c22 100644 --- a/lib/src/screens/yat/yat_alert.dart +++ b/lib/src/screens/yat/yat_alert.dart @@ -1,8 +1,7 @@ -import 'package:cake_wallet/core/wallet_base.dart'; -import 'package:cake_wallet/entities/wallet_type.dart'; import 'package:cake_wallet/src/screens/yat/widgets/yat_bar.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/store/yat/yat_store.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/palette.dart'; @@ -11,22 +10,13 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:lottie/lottie.dart'; class YatAlert extends StatelessWidget { - YatAlert({@required this.wallet, this.isYatDevMode = false}) - : baseUrl = isYatDevMode ? _baseDevUrl : _baseReleaseUrl, - address = wallet.walletAddresses.address; + YatAlert(this.yatStore) + : baseUrl = isYatDevMode ? baseDevUrl : baseReleaseUrl; - final WalletBase wallet; - final bool isYatDevMode; - final String address; + final YatStore yatStore; final String baseUrl; static const aspectRatioImage = 1.133; - static const _baseDevUrl = 'https://yat.fyi'; - static const _baseReleaseUrl = 'https://y.at'; - static const _signInSuffix = '/partner/CW/link-email'; - static const _createSuffix = '/create'; - static const _queryParameter = '?addresses='; - final image = Image.asset('assets/images/yat_crypto.png'); - final anim = Lottie.asset('assets/animation/anim1.json'); + final animation = Lottie.asset('assets/animation/anim1.json'); @override Widget build(BuildContext context) { @@ -42,15 +32,11 @@ class YatAlert extends StatelessWidget { content: Column( children: [ Container( - height: 45, // 90 + height: 45, padding: EdgeInsets.only(left: 24, right: 24), child: YatBar(onClose: () => Navigator.of(context).pop()) ), - anim, - // AspectRatio( - // aspectRatio: aspectRatioImage, - // child: FittedBox(child: image, fit: BoxFit.fill) - // ), + animation, Container( padding: EdgeInsets.only(left: 30, right: 30), child: Column( @@ -100,7 +86,7 @@ class YatAlert extends StatelessWidget { .arrow_up_right_square, mainAxisAlignment: MainAxisAlignment.end, onPressed: () { - final url = baseUrl + _createSuffix; + final url = baseUrl + createSuffix; launch(url); }), Padding( @@ -116,8 +102,12 @@ class YatAlert extends StatelessWidget { .arrow_up_right_square, mainAxisAlignment: MainAxisAlignment.end, onPressed: () { - final url = baseUrl + _signInSuffix + _queryParameter + - _defineTag() + '%3D' + address; + String url = baseUrl + signInSuffix; + final parameters = + yatStore.defineQueryParameters(); + if (parameters.isNotEmpty) { + url += queryParameter + parameters; + } launch(url); }) ) @@ -126,24 +116,4 @@ class YatAlert extends StatelessWidget { ) ); } - - String _defineTag() { - String tag; - switch (wallet.type) { - case WalletType.monero: - tag = address.startsWith('4') - ? '0x1001' - : '0x1002'; - break; - case WalletType.bitcoin: - tag = '0x1003'; - break; - case WalletType.litecoin: - tag = '0x3fff'; - break; - default: - tag = '0x3fff'; - } - return tag; - } } \ No newline at end of file diff --git a/lib/src/screens/yat/yat_popup.dart b/lib/src/screens/yat/yat_popup.dart new file mode 100644 index 000000000..05d0c8dad --- /dev/null +++ b/lib/src/screens/yat/yat_popup.dart @@ -0,0 +1,178 @@ +import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/src/screens/yat/widgets/first_introduction.dart'; +import 'package:cake_wallet/src/screens/yat/widgets/second_introduction.dart'; +import 'package:cake_wallet/src/screens/yat/widgets/third_introduction.dart'; +import 'package:cake_wallet/src/screens/yat/widgets/yat_close_button.dart'; +import 'package:cake_wallet/src/widgets/alert_background.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/store/yat/yat_store.dart'; +import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:animate_do/animate_do.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class YatPopup extends StatelessWidget { + YatPopup({this.dashboardViewModel, this.onClose}) + : baseUrl = isYatDevMode ? baseDevUrl : baseReleaseUrl; + + static const durationInMilliseconds = 250; + + final DashboardViewModel dashboardViewModel; + final VoidCallback onClose; + final String baseUrl; + final image = Image.asset('assets/images/emoji_popup.png'); + + @override + Widget build(BuildContext context) { + final screenWidth = MediaQuery.of(context).size.width; + + return Stack( + clipBehavior: Clip.none, + alignment: Alignment.bottomCenter, + children: [ + AlertBackground( + child: Container() + ), + SlideInUp( + from: 420, + duration: Duration(milliseconds: durationInMilliseconds), + child: ClipRRect( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(24), + topRight: Radius.circular(24)), + child: Container( + height: 420, + color: Colors.white, + padding: EdgeInsets.fromLTRB(24, 15, 24, 24), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + children: [ + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + YatCloseButton(onClose: onClose) + ] + ), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + height: 64, + width: 165, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius + .all(Radius.circular(32)), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.05), + blurRadius: 15, + offset: Offset(0, 5) + ) + ] + ), + child: image + ) + ] + ) + ] + ), + Container( + padding: EdgeInsets.only(left: 6, right: 6), + child: Column( + children: [ + Text( + 'Your wallet address can be emojified.', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + fontFamily: 'Lato', + color: Colors.black, + decoration: TextDecoration.none, + ) + ), + Padding( + padding: EdgeInsets.only(top: 20), + child: Text( + 'You can now send and receive crypto in Cake Wallet with your Yat - a short, emoji-based username. Manage Yats at any time on the settings screen', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.normal, + fontFamily: 'Lato', + color: Colors.black, + decoration: TextDecoration.none, + ) + ) + ) + ] + ) + ), + PrimaryButton( + text: 'Learn More', + textColor: Colors.white, + color: Palette.protectiveBlue, + onPressed: () => dashboardViewModel + .isShowFirstYatIntroduction = true + ) + ], + ) + ) + ), + ), + Observer(builder: (_) => dashboardViewModel.isShowFirstYatIntroduction + ? SlideInRight( + from: screenWidth, + duration: Duration(milliseconds: durationInMilliseconds), + child: FirstIntroduction( + onClose: onClose, + onNext: () => dashboardViewModel + .isShowSecondYatIntroduction = true + )) + : Container() + ), + Observer(builder: (_) => dashboardViewModel.isShowSecondYatIntroduction + ? SlideInRight( + from: screenWidth, + duration: Duration(milliseconds: durationInMilliseconds), + child: SecondIntroduction( + onClose: onClose, + onNext: () => dashboardViewModel + .isShowThirdYatIntroduction = true + )) + : Container() + ), + Observer(builder: (_) => dashboardViewModel.isShowThirdYatIntroduction + ? SlideInRight( + from: screenWidth, + duration: Duration(milliseconds: durationInMilliseconds), + child: ThirdIntroduction( + onClose: onClose, + onGet: () { + final url = baseUrl + createSuffix; + launch(url); + }, + onConnect: () { + String url = baseUrl + signInSuffix; + final parameters = dashboardViewModel + .yatStore.defineQueryParameters(); + if (parameters.isNotEmpty) { + url += queryParameter + parameters; + } + launch(url); + } + )) + : Container() + ) + ], + ); + } +} \ No newline at end of file diff --git a/lib/yat/yat_exception.dart b/lib/store/yat/yat_exception.dart similarity index 100% rename from lib/yat/yat_exception.dart rename to lib/store/yat/yat_exception.dart diff --git a/lib/store/yat/yat_store.dart b/lib/store/yat/yat_store.dart new file mode 100644 index 000000000..5c66c2937 --- /dev/null +++ b/lib/store/yat/yat_store.dart @@ -0,0 +1,166 @@ +import 'package:cake_wallet/core/transaction_history.dart'; +import 'package:cake_wallet/core/wallet_base.dart'; +import 'package:cake_wallet/entities/balance.dart'; +import 'package:cake_wallet/entities/transaction_info.dart'; +import 'package:cake_wallet/store/app_store.dart'; +import 'package:flutter/foundation.dart'; +import 'package:mobx/mobx.dart'; +import 'package:cake_wallet/bitcoin/electrum_wallet.dart'; +import 'package:cake_wallet/entities/wallet_type.dart'; +import 'package:cake_wallet/monero/monero_subaddress_list.dart'; +import 'package:cake_wallet/monero/monero_wallet.dart'; +import 'dart:convert'; +import 'package:cake_wallet/store/yat/yat_exception.dart'; +import 'package:http/http.dart'; + +part 'yat_store.g.dart'; + +const baseDevUrl = 'https://yat.fyi'; +const baseReleaseUrl = 'https://y.at'; +const signInSuffix = '/partner/CW/link-email'; +const createSuffix = '/create'; +const queryParameter = '?addresses='; +const requestDevUrl = 'https://a.yat.fyi/emoji_id/'; +const requestReleaseUrl = 'https://a.y.at/emoji_id/'; +const isYatDevMode = true; + +Future> fetchYatAddress(String emojiId, String ticker) async { + final requestURL = isYatDevMode ? requestDevUrl : requestReleaseUrl; + final url = requestURL + emojiId + '/' + ticker.toUpperCase(); + final response = await get(url); + + if (response.statusCode != 200) { + throw YatException(text: response.body.toString()); + } + + final responseJSON = json.decode(response.body) as Map; + final result = responseJSON['result'] as List; + + if (result?.isEmpty ?? true) { + return []; + } + + final List addresses = []; + + for (var elem in result) { + final yatAddress = elem['data'] as String; + if (yatAddress?.isNotEmpty ?? false) { + addresses.add(yatAddress); + } + } + + return addresses; +} + +class YatStore = YatStoreBase with _$YatStore; + +abstract class YatStoreBase with Store { + YatStoreBase({@required this.appStore}) { + _wallet ??= appStore.wallet; + emoji = _wallet?.walletInfo?.yatEmojiId ?? ''; + refreshToken = _wallet?.walletInfo?.yatToken ?? ''; + reaction((_) => appStore.wallet, _onWalletChange); + reaction((_) => emoji, (String emoji) => _onEmojiChange()); + } + + AppStore appStore; + + @observable + String emoji; + + @observable + String refreshToken; + + @observable + WalletBase, TransactionInfo> + _wallet; + + @action + void _onWalletChange( + WalletBase, + TransactionInfo> + wallet) { + this._wallet = wallet; + emoji = wallet?.walletInfo?.yatEmojiId ?? ''; + refreshToken = wallet?.walletInfo?.yatToken ?? ''; + } + + @action + void _onEmojiChange() { + try { + final walletInfo = _wallet.walletInfo; + + if (walletInfo == null) { + return; + } + + walletInfo.yatEid = emoji; + walletInfo.yatRefreshToken = refreshToken; + + if (walletInfo.isInBox) { + walletInfo.save(); + } + } catch (e) { + print(e.toString()); + } + } + + String defineQueryParameters() { + String parameters = ''; + switch (_wallet.type) { + case WalletType.monero: + final wallet = _wallet as MoneroWallet; + final subaddressList = MoneroSubaddressList(); + var isFirstAddress = true; + + wallet.walletAddresses.accountList.accounts.forEach((account) { + subaddressList.update(accountIndex: account.id); + subaddressList.subaddresses.forEach((subaddress) { + if (!isFirstAddress) { + parameters += '%7C'; + } else { + isFirstAddress = !isFirstAddress; + } + + parameters += subaddress.address.startsWith('4') + ? '0x1001%3D' + : '0x1002%3D'; + + parameters += subaddress.address; + }); + }); + break; + case WalletType.bitcoin: + final wallet = _wallet as ElectrumWallet; + var isFirstAddress = true; + + wallet.walletAddresses.addresses.forEach((record) { + if (!isFirstAddress) { + parameters += '%7C'; + } else { + isFirstAddress = !isFirstAddress; + } + + parameters += '0x1003%3D' + record.address; + }); + break; + case WalletType.litecoin: + final wallet = _wallet as ElectrumWallet; + var isFirstAddress = true; + + wallet.walletAddresses.addresses.forEach((record) { + if (!isFirstAddress) { + parameters += '%7C'; + } else { + isFirstAddress = !isFirstAddress; + } + + parameters += '0x3fff%3D' + record.address; + }); + break; + default: + parameters = ''; + } + return parameters; + } +} \ No newline at end of file diff --git a/lib/store/yat_store.dart b/lib/store/yat_store.dart deleted file mode 100644 index fdd107cf1..000000000 --- a/lib/store/yat_store.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:mobx/mobx.dart'; - -part 'yat_store.g.dart'; - -class YatStore = YatStoreBase with _$YatStore; - -abstract class YatStoreBase with Store { - YatStoreBase() : emoji = ''; - - @observable - String emoji; -} \ No newline at end of file diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 5f0f8fdd8..623a2af86 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -12,6 +12,7 @@ import 'package:cake_wallet/entities/transaction_info.dart'; import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/store/dashboard/orders_store.dart'; +import 'package:cake_wallet/store/yat/yat_store.dart'; import 'package:cake_wallet/utils/mobx.dart'; import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/filter_item.dart'; @@ -46,6 +47,7 @@ abstract class DashboardViewModelBase with Store { this.tradeFilterStore, this.transactionFilterStore, this.settingsStore, + this.yatStore, this.ordersStore}) { filterItems = { S.current.transactions: [ @@ -86,6 +88,9 @@ abstract class DashboardViewModelBase with Store { type = wallet.type; isOutdatedElectrumWallet = wallet.type == WalletType.bitcoin && wallet.seed.split(' ').length < 24; + isShowFirstYatIntroduction = false; + isShowSecondYatIntroduction = false; + isShowThirdYatIntroduction = false; final _wallet = wallet; if (_wallet is MoneroWallet) { @@ -147,6 +152,15 @@ abstract class DashboardViewModelBase with Store { @observable String subname; + @observable + bool isShowFirstYatIntroduction; + + @observable + bool isShowSecondYatIntroduction; + + @observable + bool isShowThirdYatIntroduction; + @computed String get address => wallet.walletAddresses.address; @@ -208,6 +222,8 @@ abstract class DashboardViewModelBase with Store { SettingsStore settingsStore; + YatStore yatStore; + TradesStore tradesStore; OrdersStore ordersStore; diff --git a/lib/view_model/settings/settings_view_model.dart b/lib/view_model/settings/settings_view_model.dart index f517ce644..35f6ef3aa 100644 --- a/lib/view_model/settings/settings_view_model.dart +++ b/lib/view_model/settings/settings_view_model.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/src/screens/yat/yat_alert.dart'; +import 'package:cake_wallet/store/yat/yat_store.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/cupertino.dart'; import 'package:mobx/mobx.dart'; @@ -50,6 +51,7 @@ List priorityForWalletType(WalletType type) { abstract class SettingsViewModelBase with Store { SettingsViewModelBase( this._settingsStore, + this._yatStore, WalletBase, TransactionInfo> wallet) @@ -162,7 +164,7 @@ abstract class SettingsViewModelBase with Store { await showPopUp( context: context, builder: (BuildContext context) { - return YatAlert(wallet: wallet, isYatDevMode: true); + return YatAlert(_yatStore); }); }, ), @@ -213,6 +215,7 @@ abstract class SettingsViewModelBase with Store { final Map itemHeaders; List> sections; final SettingsStore _settingsStore; + final YatStore _yatStore; final WalletType _walletType; final BiometricAuth _biometricAuth; diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart index e5ed063e9..879aae5c4 100644 --- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart @@ -1,4 +1,4 @@ -import 'package:cake_wallet/store/yat_store.dart'; +import 'package:cake_wallet/store/yat/yat_store.dart'; import 'package:flutter/foundation.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart'; diff --git a/lib/yat/yat_record.dart b/lib/yat/yat_record.dart deleted file mode 100644 index 5ea2dae2c..000000000 --- a/lib/yat/yat_record.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'dart:convert'; -import 'package:cake_wallet/yat/yat_exception.dart'; -import 'package:http/http.dart'; - -Future> fetchYatAddress(String emojiId, String ticker) async { - const _requestURL = 'https://a.y.at/emoji_id/'; - final url = _requestURL + emojiId + '/' + ticker.toUpperCase(); - final response = await get(url); - - if (response.statusCode != 200) { - throw YatException(text: response.body.toString()); - } - - final responseJSON = json.decode(response.body) as Map; - final result = responseJSON['result'] as List; - - if (result?.isEmpty ?? true) { - return []; - } - - final List addresses = []; - - for (var elem in result) { - final yatAddress = elem['data'] as String; - if (yatAddress?.isNotEmpty ?? false) { - addresses.add(yatAddress); - } - } - - return addresses; -} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 6f883d939..8ddc7c890 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -15,6 +15,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.41.2" + animate_do: + dependency: "direct main" + description: + name: animate_do + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" archive: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index d5cd3d882..0ee1aa1f4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -59,6 +59,7 @@ dependencies: flutter_spinkit: ^5.0.0 uni_links: ^0.4.0 lottie: ^0.7.0 + animate_do: ^2.0.0 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons.