CAKE-360 | added shouldShowYatPopup parameter to settings_store.dart and applied this parameter to dashboard_view_model.dart and dashboard_page.dart; added scrollbar to choose_yat_address_alert.dart; changed yat logo; fixed fetchYatAddress() method in the yat_store.dart; created class YatLink

OleksandrSobol committed Oct 4, 2021 at 16:03 UTC c728931b705b61cc9727fa7689a6dd26fab178cd
10 files changed +167 -79
assets/images/yat_logo.png
Binary files a/assets/images/yat_logo.png and b/assets/images/yat_logo.png differ
lib/entities/preferences_key.dart
+1
@@ -20,4 +20,5 @@ class PreferencesKey {
20 static const moneroTransactionPriority = 'current_fee_priority_monero';
21 static const bitcoinTransactionPriority = 'current_fee_priority_bitcoin';
22 static const shouldShowReceiveWarning = 'should_show_receive_warning';
23 + static const shouldShowYatPopup = 'should_show_yat_popup';
24 }
lib/src/screens/dashboard/dashboard_page.dart
+11 -8
@@ -156,14 +156,17 @@ class DashboardPage extends BasePage {
156 pages.add(BalancePage(dashboardViewModel: walletViewModel));
157 pages.add(TransactionsPage(dashboardViewModel: walletViewModel));
158
159 - await Future<void>.delayed(Duration(seconds: 1));
160 - await showPopUp<void>(
161 - context: context,
162 - builder: (BuildContext context) {
163 - return YatPopup(
164 - dashboardViewModel: walletViewModel,
165 - onClose: () => Navigator.of(context).pop());
166 - });
159 + if (walletViewModel.shouldShowYatPopup) {
160 + await Future<void>.delayed(Duration(seconds: 1));
161 + await showPopUp<void>(
162 + context: context,
163 + builder: (BuildContext context) {
164 + return YatPopup(
165 + dashboardViewModel: walletViewModel,
166 + onClose: () => Navigator.of(context).pop());
167 + });
168 + walletViewModel.furtherShowYatPopup(false);
169 + }
170
171 autorun((_) async {
172 if (!walletViewModel.isOutdatedElectrumWallet) {
lib/src/screens/send/widgets/choose_yat_address_alert.dart
+92 -44
@@ -1,3 +1,4 @@
1 +import 'package:cake_wallet/src/widgets/cake_scrollbar.dart';
2 import 'package:flutter/material.dart';
3 import 'package:cake_wallet/src/widgets/base_alert_dialog.dart';
4
@@ -22,51 +23,98 @@ class ChooseYatAddressAlert extends BaseAlertDialog {
23 bool get barrierDismissible => false;
24
25 @override
25 - Widget actionButtons(BuildContext context) {
26 - return Container(
27 - width: 300,
28 - height: 105,
29 - color: Theme.of(context).accentTextTheme.body1.backgroundColor,
30 - child: ListView.separated(
31 - padding: EdgeInsets.all(0),
32 - itemCount: addresses.length,
33 - separatorBuilder: (_, __) => Container(
34 - height: 1,
35 - color: Theme.of(context).dividerColor,
36 - ),
37 - itemBuilder: (context, index) {
38 - final address = addresses[index];
26 + Widget actionButtons(BuildContext context) =>
27 + ChooseYatAddressButtons(addresses);
28 +}
29
40 - return GestureDetector(
41 - onTap: () => Navigator.of(context).pop<String>(address),
42 - child: Container(
43 - width: 300,
44 - height: 52,
45 - padding: EdgeInsets.only(left: 24, right: 24),
46 - child: Row(
47 - mainAxisAlignment: MainAxisAlignment.center,
48 - crossAxisAlignment: CrossAxisAlignment.center,
49 - children: [
50 - Expanded(
51 - child: Text(
52 - address,
53 - textAlign: TextAlign.center,
54 - maxLines: 1,
55 - overflow: TextOverflow.ellipsis,
56 - style: TextStyle(
57 - fontSize: 15,
58 - fontWeight: FontWeight.w600,
59 - fontFamily: 'Lato',
60 - color: Theme.of(context).primaryTextTheme.title.color,
61 - decoration: TextDecoration.none,
62 - ),
63 - )
64 - )
65 - ],
66 - )
67 - ),
68 - );
69 - })
30 +class ChooseYatAddressButtons extends StatefulWidget {
31 + ChooseYatAddressButtons(this.addresses);
32 +
33 + final List<String> addresses;
34 +
35 + @override
36 + ChooseYatAddressButtonsState createState() =>
37 + ChooseYatAddressButtonsState(addresses);
38 +}
39 +
40 +class ChooseYatAddressButtonsState extends State<ChooseYatAddressButtons> {
41 + ChooseYatAddressButtonsState(this.addresses)
42 + : itemCount = addresses?.length ?? 0;
43 +
44 + final List<String> addresses;
45 + final int itemCount;
46 + final double backgroundHeight = 118;
47 + final double thumbHeight = 72;
48 + ScrollController controller = ScrollController();
49 + double fromTop = 0;
50 +
51 + @override
52 + Widget build(BuildContext context) {
53 + controller.addListener(() {
54 + fromTop = controller.hasClients
55 + ? (controller.offset / controller.position.maxScrollExtent *
56 + (backgroundHeight - thumbHeight))
57 + : 0;
58 + setState(() {});
59 + });
60 +
61 + return Stack(
62 + alignment: Alignment.center,
63 + clipBehavior: Clip.none,
64 + children: [
65 + Container(
66 + width: 300,
67 + height: 158,
68 + color: Theme.of(context).accentTextTheme.body1.backgroundColor,
69 + child: ListView.separated(
70 + controller: controller,
71 + padding: EdgeInsets.all(0),
72 + itemCount: itemCount,
73 + separatorBuilder: (_, __) => Container(
74 + height: 1,
75 + color: Theme.of(context).dividerColor,
76 + ),
77 + itemBuilder: (context, index) {
78 + final address = addresses[index];
79 +
80 + return GestureDetector(
81 + onTap: () => Navigator.of(context).pop<String>(address),
82 + child: Container(
83 + width: 300,
84 + height: 52,
85 + padding: EdgeInsets.only(left: 24, right: 24),
86 + child: Row(
87 + mainAxisAlignment: MainAxisAlignment.center,
88 + crossAxisAlignment: CrossAxisAlignment.center,
89 + children: [
90 + Expanded(
91 + child: Text(
92 + address,
93 + textAlign: TextAlign.center,
94 + maxLines: 1,
95 + overflow: TextOverflow.ellipsis,
96 + style: TextStyle(
97 + fontSize: 15,
98 + fontWeight: FontWeight.w600,
99 + fontFamily: 'Lato',
100 + color: Theme.of(context).primaryTextTheme.title.color,
101 + decoration: TextDecoration.none,
102 + ),
103 + )
104 + )
105 + ],
106 + )
107 + ),
108 + );
109 + })
110 + ),
111 + if (itemCount > 3) CakeScrollbar(
112 + backgroundHeight: backgroundHeight,
113 + thumbHeight: thumbHeight,
114 + fromTop: fromTop,
115 + //rightOffset: -15
116 + )
117 + ]
118 );
119 }
120 }
\ No newline at end of file
lib/src/screens/yat/widgets/yat_bar.dart
+1 -1
@@ -5,7 +5,7 @@ class YatBar extends StatelessWidget {
5 YatBar({this.onClose});
6
7 final VoidCallback onClose;
8 - final image = Image.asset('assets/images/yat_logo.png');
8 + final image = Image.asset('assets/images/yat_logo.png', width: 81, height: 28);
9
10 @override
11 Widget build(BuildContext context) {
lib/src/screens/yat/yat_alert.dart
+6 -4
@@ -11,7 +11,9 @@ import 'package:lottie/lottie.dart';
11
12 class YatAlert extends StatelessWidget {
13 YatAlert(this.yatStore)
14 - : baseUrl = isYatDevMode ? baseDevUrl : baseReleaseUrl;
14 + : baseUrl = YatLink.isDevMode
15 + ? YatLink.baseDevUrl
16 + : YatLink.baseReleaseUrl;
17
18 final YatStore yatStore;
19 final String baseUrl;
@@ -86,7 +88,7 @@ class YatAlert extends StatelessWidget {
88 .arrow_up_right_square,
89 mainAxisAlignment: MainAxisAlignment.end,
90 onPressed: () {
89 - final url = baseUrl + createSuffix;
91 + final url = baseUrl + YatLink.createSuffix;
92 launch(url);
93 }),
94 Padding(
@@ -102,11 +104,11 @@ class YatAlert extends StatelessWidget {
104 .arrow_up_right_square,
105 mainAxisAlignment: MainAxisAlignment.end,
106 onPressed: () {
105 - String url = baseUrl + signInSuffix;
107 + String url = baseUrl + YatLink.signInSuffix;
108 final parameters =
109 yatStore.defineQueryParameters();
110 if (parameters.isNotEmpty) {
109 - url += queryParameter + parameters;
111 + url += YatLink.queryParameter + parameters;
112 }
113 launch(url);
114 })
lib/src/screens/yat/yat_popup.dart
+6 -4
@@ -14,7 +14,9 @@ import 'package:url_launcher/url_launcher.dart';
14
15 class YatPopup extends StatelessWidget {
16 YatPopup({this.dashboardViewModel, this.onClose})
17 - : baseUrl = isYatDevMode ? baseDevUrl : baseReleaseUrl;
17 + : baseUrl = YatLink.isDevMode
18 + ? YatLink.baseDevUrl
19 + : YatLink.baseReleaseUrl;
20
21 static const durationInMilliseconds = 250;
22
@@ -157,15 +159,15 @@ class YatPopup extends StatelessWidget {
159 child: ThirdIntroduction(
160 onClose: onClose,
161 onGet: () {
160 - final url = baseUrl + createSuffix;
162 + final url = baseUrl + YatLink.createSuffix;
163 launch(url);
164 },
165 onConnect: () {
164 - String url = baseUrl + signInSuffix;
166 + String url = baseUrl + YatLink.signInSuffix;
167 final parameters = dashboardViewModel
168 .yatStore.defineQueryParameters();
169 if (parameters.isNotEmpty) {
168 - url += queryParameter + parameters;
170 + url += YatLink.queryParameter + parameters;
171 }
172 launch(url);
173 }
lib/store/settings_store.dart
+14 -1
@@ -38,6 +38,7 @@ abstract class SettingsStoreBase with Store {
38 @required Map<WalletType, Node> nodes,
39 @required TransactionPriority initialBitcoinTransactionPriority,
40 @required TransactionPriority initialMoneroTransactionPriority,
41 + @required this.shouldShowYatPopup,
42 @required this.isBitcoinBuyEnabled,
43 this.actionlistDisplayMode}) {
44 fiatCurrency = initialFiatCurrency;
@@ -59,6 +60,11 @@ abstract class SettingsStoreBase with Store {
60 (FiatCurrency fiatCurrency) => sharedPreferences.setString(
61 PreferencesKey.currentFiatCurrencyKey, fiatCurrency.serialize()));
62
63 + reaction(
64 + (_) => shouldShowYatPopup,
65 + (bool shouldShowYatPopup) => sharedPreferences
66 + .setBool(PreferencesKey.shouldShowYatPopup, shouldShowYatPopup));
67 +
68 priority.observe((change) {
69 final key = change.key == WalletType.monero
70 ? PreferencesKey.moneroTransactionPriority
@@ -110,6 +116,9 @@ abstract class SettingsStoreBase with Store {
116 @observable
117 FiatCurrency fiatCurrency;
118
119 + @observable
120 + bool shouldShowYatPopup;
121 +
122 @observable
123 ObservableList<ActionListDisplayMode> actionlistDisplayMode;
124
@@ -217,6 +226,8 @@ abstract class SettingsStoreBase with Store {
226 final bitcoinElectrumServer = nodeSource.get(bitcoinElectrumServerId);
227 final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId);
228 final packageInfo = await PackageInfo.fromPlatform();
229 + final shouldShowYatPopup =
230 + sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true;
231
232 return SettingsStore(
233 sharedPreferences: sharedPreferences,
@@ -236,7 +247,8 @@ abstract class SettingsStoreBase with Store {
247 initialPinLength: pinLength,
248 initialLanguageCode: savedLanguageCode,
249 initialMoneroTransactionPriority: moneroTransactionPriority,
239 - initialBitcoinTransactionPriority: bitcoinTransactionPriority);
250 + initialBitcoinTransactionPriority: bitcoinTransactionPriority,
251 + shouldShowYatPopup: shouldShowYatPopup);
252 }
253
254 Future<void> reload(
@@ -270,6 +282,7 @@ abstract class SettingsStoreBase with Store {
282 pinCodeLength = settings.pinCodeLength;
283 languageCode = settings.languageCode;
284 appVersion = settings.appVersion;
285 + shouldShowYatPopup = settings.shouldShowYatPopup;
286 }
287
288 Future<void> _saveCurrentNode(Node node, WalletType walletType) async {
lib/store/yat/yat_store.dart
+30 -17
@@ -15,18 +15,24 @@ import 'package:http/http.dart';
15
16 part 'yat_store.g.dart';
17
18 -const baseDevUrl = 'https://yat.fyi';
19 -const baseReleaseUrl = 'https://y.at';
20 -const signInSuffix = '/partner/CW/link-email';
21 -const createSuffix = '/create';
22 -const queryParameter = '?addresses=';
23 -const requestDevUrl = 'https://a.yat.fyi/emoji_id/';
24 -const requestReleaseUrl = 'https://a.y.at/emoji_id/';
25 -const isYatDevMode = true;
18 +class YatLink {
19 + static const baseDevUrl = 'https://yat.fyi';
20 + static const baseReleaseUrl = 'https://y.at';
21 + static const signInSuffix = '/partner/CW/link-email';
22 + static const createSuffix = '/create';
23 + static const queryParameter = '?addresses=';
24 + static const requestDevUrl = 'https://a.yat.fyi/emoji_id/';
25 + static const requestReleaseUrl = 'https://a.y.at/emoji_id/';
26 + static const isDevMode = true;
27 + static const tags = <String, List<String>>{"XMR" : ['0x1001', '0x1002'],
28 + "BTC" : ['0x1003'], "LTC" : ['0x3fff']};
29 +}
30
31 Future<List<String>> fetchYatAddress(String emojiId, String ticker) async {
28 - final requestURL = isYatDevMode ? requestDevUrl : requestReleaseUrl;
29 - final url = requestURL + emojiId + '/' + ticker.toUpperCase();
32 + final requestURL = YatLink.isDevMode
33 + ? YatLink.requestDevUrl
34 + : YatLink.requestReleaseUrl;
35 + final url = requestURL + emojiId;
36 final response = await get(url);
37
38 if (response.statusCode != 200) {
@@ -41,11 +47,18 @@ Future<List<String>> fetchYatAddress(String emojiId, String ticker) async {
47 }
48
49 final List<String> addresses = [];
50 + final currency = ticker.toUpperCase();
51
52 for (var elem in result) {
46 - final yatAddress = elem['data'] as String;
47 - if (yatAddress?.isNotEmpty ?? false) {
48 - addresses.add(yatAddress);
53 + final tag = elem['tag'] as String;
54 + if (tag?.isEmpty ?? true) {
55 + continue;
56 + }
57 + if (YatLink.tags[currency]?.contains(tag) ?? false) {
58 + final yatAddress = elem['data'] as String;
59 + if (yatAddress?.isNotEmpty ?? false) {
60 + addresses.add(yatAddress);
61 + }
62 }
63 }
64
@@ -123,8 +136,8 @@ abstract class YatStoreBase with Store {
136 }
137
138 parameters += subaddress.address.startsWith('4')
126 - ? '0x1001%3D'
127 - : '0x1002%3D';
139 + ? YatLink.tags["XMR"].first + '%3D'
140 + : YatLink.tags["XMR"].last + '%3D';
141
142 parameters += subaddress.address;
143 });
@@ -141,7 +154,7 @@ abstract class YatStoreBase with Store {
154 isFirstAddress = !isFirstAddress;
155 }
156
144 - parameters += '0x1003%3D' + record.address;
157 + parameters += YatLink.tags["BTC"].first + '%3D' + record.address;
158 });
159 break;
160 case WalletType.litecoin:
@@ -155,7 +168,7 @@ abstract class YatStoreBase with Store {
168 isFirstAddress = !isFirstAddress;
169 }
170
158 - parameters += '0x3fff%3D' + record.address;
171 + parameters += YatLink.tags["LTC"].first + '%3D' + record.address;
172 });
173 break;
174 default:
lib/view_model/dashboard/dashboard_view_model.dart
+6
@@ -236,6 +236,12 @@ abstract class DashboardViewModelBase with Store {
236
237 bool get isBuyEnabled => settingsStore.isBitcoinBuyEnabled;
238
239 + bool get shouldShowYatPopup => settingsStore.shouldShowYatPopup;
240 +
241 + @action
242 + void furtherShowYatPopup(bool shouldShow) =>
243 + settingsStore.shouldShowYatPopup = shouldShow;
244 +
245 ReactionDisposer _onMoneroAccountChangeReaction;
246
247 ReactionDisposer _onMoneroBalanceChangeReaction;