V4.6.1 report fixes (#859)

* Add exception handler to anypay api response failure * Check if context is still mounted before fetching iPad position * Add user connection issue to ignored errors * Wrap launchURL in empty try catch to avoid package un-needed exceptions

Omar Hatem committed Mar 31, 2023 at 21:14 UTC 37ef63d09e5f530b8c598fbd26e350344a179c70
6 files changed +39 -16
lib/anypay/anypay_api.dart
+2
@@ -1,5 +1,6 @@
1 import 'dart:convert';
2 import 'package:cake_wallet/anypay/any_pay_payment_committed_info.dart';
3 +import 'package:cake_wallet/utils/exception_handler.dart';
4 import 'package:flutter/foundation.dart';
5 import 'package:http/http.dart';
6 import 'package:cw_core/crypto_currency.dart';
@@ -55,6 +56,7 @@ class AnyPayApi {
56 final response = await post(url, headers: headers, body: utf8.encode(json.encode(body)));
57
58 if (response.statusCode != 200) {
59 + ExceptionHandler.onError(FlutterErrorDetails(exception: response));
60 throw Exception('Unexpected response http code: ${response.statusCode}');
61 }
62
lib/utils/exception_handler.dart
+2
@@ -136,9 +136,11 @@ class ExceptionHandler {
136 "errno = 54", // SocketException: Connection reset by peer
137 "errno = 57", // SocketException: Read failed (OS Error: Socket is not connected)
138 "errno = 60", // SocketException: Operation timed out
139 + "errno = 65", // SocketException: No route to host
140 "errno = 103", // SocketException: Software caused connection abort
141 "errno = 104", // SocketException: Connection reset by peer
142 "errno = 110", // SocketException: Connection timed out
143 + "HttpException: Connection reset by peer",
144 "HttpException: Connection closed before full header was received",
145 "HandshakeException: Connection terminated during handshake",
146 "PERMISSION_NOT_GRANTED",
lib/utils/share_util.dart
+5 -1
@@ -28,7 +28,11 @@ class ShareUtil {
28 );
29 }
30
31 - static Rect? _sharePosition(BuildContext context) {
31 + static Rect _sharePosition(BuildContext context) {
32 + if (!context.mounted) {
33 + return Rect.zero;
34 + }
35 +
36 final box = context.findRenderObject() as RenderBox?;
37
38 return box!.localToGlobal(Offset.zero) & box.size;
lib/view_model/order_details_view_model.dart
+11 -9
@@ -81,21 +81,23 @@ abstract class OrderDetailsViewModelBase with Store {
81 : S.current.trade_details_fetching),
82 ]);
83
84 - if (order.provider != null) {
85 - items.add(
86 - StandartListItem(
87 - title: 'Buy provider',
88 - value: order.provider.title)
89 - );
90 - }
84 + items.add(
85 + StandartListItem(
86 + title: 'Buy provider',
87 + value: order.provider.title)
88 + );
89
92 - if (_provider!.trackUrl?.isNotEmpty ?? false) {
90 + if (_provider?.trackUrl.isNotEmpty ?? false) {
91 final buildURL = _provider!.trackUrl + '${order.transferId}';
92 items.add(
93 TrackTradeListItem(
94 title: 'Track',
95 value: buildURL,
98 - onTap: () => launch(buildURL)
96 + onTap: () {
97 + try {
98 + launch(buildURL);
99 + } catch (e) {}
100 + }
101 )
102 );
103 }
lib/view_model/trade_details_view_model.dart
+14 -4
@@ -21,6 +21,7 @@ import 'package:cake_wallet/src/screens/trade_details/track_trade_list_item.dart
21 import 'package:cake_wallet/src/screens/trade_details/trade_details_list_card.dart';
22 import 'package:cake_wallet/src/screens/trade_details/trade_details_status_item.dart';
23 import 'package:url_launcher/url_launcher.dart';
24 +
25 part 'trade_details_view_model.g.dart';
26
27 class TradeDetailsViewModel = TradeDetailsViewModelBase with _$TradeDetailsViewModel;
@@ -121,23 +122,26 @@ abstract class TradeDetailsViewModelBase with Store {
122 title: 'Track',
123 value: buildURL,
124 onTap: () {
124 - launch(buildURL);
125 + _launchUrl(buildURL);
126 }));
127 }
128
129 if (trade.provider == ExchangeProviderDescription.sideShift) {
130 final buildURL = 'https://sideshift.ai/orders/${trade.id.toString()}';
130 - items.add(TrackTradeListItem(title: 'Track', value: buildURL, onTap: () => launch(buildURL)));
131 + items.add(
132 + TrackTradeListItem(title: 'Track', value: buildURL, onTap: () => _launchUrl(buildURL)));
133 }
134
135 if (trade.provider == ExchangeProviderDescription.simpleSwap) {
136 final buildURL = 'https://simpleswap.io/exchange?id=${trade.id.toString()}';
135 - items.add(TrackTradeListItem(title: 'Track', value: buildURL, onTap: () => launch(buildURL)));
137 + items.add(
138 + TrackTradeListItem(title: 'Track', value: buildURL, onTap: () => _launchUrl(buildURL)));
139 }
140
141 if (trade.provider == ExchangeProviderDescription.trocador) {
142 final buildURL = 'https://trocador.app/en/checkout/${trade.id.toString()}';
140 - items.add(TrackTradeListItem(title: 'Track', value: buildURL, onTap: () => launch(buildURL)));
143 + items.add(
144 + TrackTradeListItem(title: 'Track', value: buildURL, onTap: () => _launchUrl(buildURL)));
145
146 items.add(StandartListItem(
147 title: '${trade.providerName} ${S.current.id.toUpperCase()}',
@@ -148,4 +152,10 @@ abstract class TradeDetailsViewModelBase with Store {
152 title: '${trade.providerName} ${S.current.password}', value: trade.password ?? ''));
153 }
154 }
155 +
156 + void _launchUrl(String url) {
157 + try {
158 + launch(url);
159 + } catch (e) {}
160 + }
161 }
lib/view_model/transaction_details_view_model.dart
+5 -2
@@ -14,7 +14,6 @@ import 'package:cake_wallet/store/settings_store.dart';
14 import 'package:cake_wallet/generated/i18n.dart';
15 import 'package:url_launcher/url_launcher.dart';
16 import 'package:cake_wallet/monero/monero.dart';
17 -import 'package:cake_wallet/haven/haven.dart';
17
18 part 'transaction_details_view_model.g.dart';
19
@@ -150,7 +149,11 @@ abstract class TransactionDetailsViewModelBase with Store {
149 items.add(BlockExplorerListItem(
150 title: S.current.view_in_block_explorer,
151 value: _explorerDescription(type),
153 - onTap: () => launch(_explorerUrl(type, tx.id))));
152 + onTap: () {
153 + try {
154 + launch(_explorerUrl(type, tx.id));
155 + } catch (e) {}
156 + }));
157
158 final description = transactionDescriptionBox.values.firstWhere(
159 (val) => val.id == transactionInfo.id,