CW-342 Enable Mac Layout on iPad (#958)

* Add iPad responsive layout * Set magic number to position input field on wider screens * Adjust screen resolution * Update target device family for ios * Add icons for iPad * Revert width adjustment for ipad * Fix overflowing balance * Fix overflowing balance * Fix PR issues * Remove unused icons [skip ci] --------- Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>

Godwin Asuquo committed Jun 14, 2023 at 02:04 UTC affc35f3355f20740f9ba47458ef93028ebda699
34 files changed +144 -110
ios/Podfile.lock
+11 -11
@@ -4,9 +4,9 @@ PODS:
4 - MTBBarcodeScanner
5 - SwiftProtobuf
6 - BigInt (5.2.0)
7 - - connectivity (0.0.1):
7 + - connectivity_plus (0.0.1):
8 - Flutter
9 - - Reachability
9 + - ReachabilitySwift
10 - CryptoSwift (1.6.0)
11 - cw_haven (0.0.1):
12 - cw_haven/Boost (= 0.0.1)
@@ -126,11 +126,11 @@ PODS:
126 - path_provider_foundation (0.0.1):
127 - Flutter
128 - FlutterMacOS
129 - - permission_handler_apple (9.0.4):
129 + - permission_handler_apple (9.1.0):
130 - Flutter
131 - platform_device_id (0.0.1):
132 - Flutter
133 - - Reachability (3.2)
133 + - ReachabilitySwift (5.0.0)
134 - SDWebImage (5.15.5):
135 - SDWebImage/Core (= 5.15.5)
136 - SDWebImage/Core (5.15.5)
@@ -153,7 +153,7 @@ PODS:
153
154 DEPENDENCIES:
155 - barcode_scan2 (from `.symlinks/plugins/barcode_scan2/ios`)
156 - - connectivity (from `.symlinks/plugins/connectivity/ios`)
156 + - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
157 - CryptoSwift
158 - cw_haven (from `.symlinks/plugins/cw_haven/ios`)
159 - cw_monero (from `.symlinks/plugins/cw_monero/ios`)
@@ -188,7 +188,7 @@ SPEC REPOS:
188 - DKPhotoGallery
189 - MTBBarcodeScanner
190 - OrderedSet
191 - - Reachability
191 + - ReachabilitySwift
192 - SDWebImage
193 - SwiftProtobuf
194 - SwiftyGif
@@ -197,8 +197,8 @@ SPEC REPOS:
197 EXTERNAL SOURCES:
198 barcode_scan2:
199 :path: ".symlinks/plugins/barcode_scan2/ios"
200 - connectivity:
201 - :path: ".symlinks/plugins/connectivity/ios"
200 + connectivity_plus:
201 + :path: ".symlinks/plugins/connectivity_plus/ios"
202 cw_haven:
203 :path: ".symlinks/plugins/cw_haven/ios"
204 cw_monero:
@@ -249,7 +249,7 @@ EXTERNAL SOURCES:
249 SPEC CHECKSUMS:
250 barcode_scan2: 0af2bb63c81b4565aab6cd78278e4c0fa136dbb0
251 BigInt: f668a80089607f521586bbe29513d708491ef2f7
252 - connectivity: c4130b2985d4ef6fd26f9702e886bd5260681467
252 + connectivity_plus: 413a8857dd5d9f1c399a39130850d02fe0feaf7e
253 CryptoSwift: 562f8eceb40e80796fffc668b0cad9313284cfa6
254 cw_haven: b3e54e1fbe7b8e6fda57a93206bc38f8e89b898a
255 cw_monero: 4cf3b96f2da8e95e2ef7d6703dd4d2c509127b7d
@@ -271,9 +271,9 @@ SPEC CHECKSUMS:
271 OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
272 package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
273 path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
274 - permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
274 + permission_handler_apple: 8f116445eff3c0e7c65ad60f5fef5490aa94b4e4
275 platform_device_id: 81b3e2993881f87d0c82ef151dc274df4869aef5
276 - Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
276 + ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
277 SDWebImage: fd7e1a22f00303e058058278639bf6196ee431fe
278 share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
279 shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c
ios/Runner.xcodeproj/project.pbxproj
+3 -3
@@ -390,7 +390,7 @@
390 PRODUCT_NAME = "$(TARGET_NAME)";
391 SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
392 SWIFT_VERSION = 5.0;
393 - TARGETED_DEVICE_FAMILY = 1;
393 + TARGETED_DEVICE_FAMILY = "1,2";
394 VALID_ARCHS = arm64;
395 VERSIONING_SYSTEM = "apple-generic";
396 };
@@ -537,7 +537,7 @@
537 SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
538 SWIFT_OPTIMIZATION_LEVEL = "-Onone";
539 SWIFT_VERSION = 5.0;
540 - TARGETED_DEVICE_FAMILY = 1;
540 + TARGETED_DEVICE_FAMILY = "1,2";
541 VALID_ARCHS = arm64;
542 VERSIONING_SYSTEM = "apple-generic";
543 };
@@ -574,7 +574,7 @@
574 PRODUCT_NAME = "$(TARGET_NAME)";
575 SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
576 SWIFT_VERSION = 5.0;
577 - TARGETED_DEVICE_FAMILY = 1;
577 + TARGETED_DEVICE_FAMILY = "1,2";
578 VALID_ARCHS = arm64;
579 VERSIONING_SYSTEM = "apple-generic";
580 };
ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
+13
@@ -1,21 +1,25 @@
1 {
2 "images" : [
3 {
4 + "filename" : "Icon-App-40x40@1x.png",
5 "idiom" : "iphone",
6 "scale" : "2x",
7 "size" : "20x20"
8 },
9 {
10 + "filename" : "Icon-App-20x20@3x.png",
11 "idiom" : "iphone",
12 "scale" : "3x",
13 "size" : "20x20"
14 },
15 {
16 + "filename" : "Icon-App-29x29@2x 1.png",
17 "idiom" : "iphone",
18 "scale" : "2x",
19 "size" : "29x29"
20 },
21 {
22 + "filename" : "Icon-App-29x29@3x.png",
23 "idiom" : "iphone",
24 "scale" : "3x",
25 "size" : "29x29"
@@ -26,6 +30,7 @@
30 "size" : "40x40"
31 },
32 {
33 + "filename" : "Icon-App-40x40@3x.png",
34 "idiom" : "iphone",
35 "scale" : "3x",
36 "size" : "40x40"
@@ -43,26 +48,31 @@
48 "size" : "60x60"
49 },
50 {
51 + "filename" : "Icon-App-20x20@1x.png",
52 "idiom" : "ipad",
53 "scale" : "1x",
54 "size" : "20x20"
55 },
56 {
57 + "filename" : "Icon-App-20x20@2x.png",
58 "idiom" : "ipad",
59 "scale" : "2x",
60 "size" : "20x20"
61 },
62 {
63 + "filename" : "Icon-App-29x29@1x.png",
64 "idiom" : "ipad",
65 "scale" : "1x",
66 "size" : "29x29"
67 },
68 {
69 + "filename" : "Icon-App-29x29@2x.png",
70 "idiom" : "ipad",
71 "scale" : "2x",
72 "size" : "29x29"
73 },
74 {
75 + "filename" : "Icon-App-40x40@1x 1.png",
76 "idiom" : "ipad",
77 "scale" : "1x",
78 "size" : "40x40"
@@ -73,16 +83,19 @@
83 "size" : "40x40"
84 },
85 {
86 + "filename" : "Icon-App-76x76@1x.png",
87 "idiom" : "ipad",
88 "scale" : "1x",
89 "size" : "76x76"
90 },
91 {
92 + "filename" : "Icon-App-76x76@2x.png",
93 "idiom" : "ipad",
94 "scale" : "2x",
95 "size" : "76x76"
96 },
97 {
98 + "filename" : "Icon-App-83.5x83.5@2x.png",
99 "idiom" : "ipad",
100 "scale" : "2x",
101 "size" : "83.5x83.5"
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x 1.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x 1.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x 1.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x 1.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ
lib/di.dart
+2 -1
@@ -36,6 +36,7 @@ import 'package:cake_wallet/themes/theme_list.dart';
36 import 'package:cake_wallet/utils/device_info.dart';
37 import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.dart';
38 import 'package:cake_wallet/utils/payment_request.dart';
39 +import 'package:cake_wallet/utils/responsive_layout_util.dart';
40 import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart';
41 import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart';
42 import 'package:cake_wallet/view_model/anonpay_details_view_model.dart';
@@ -244,7 +245,7 @@ Future setup({
245 nodeSource: _nodeSource,
246 isBitcoinBuyEnabled: isBitcoinBuyEnabled,
247 // Enforce darkTheme on platforms other than mobile till the design for other themes is completed
247 - initialTheme: DeviceInfo.instance.isMobile ? null : ThemeList.darkTheme,
248 + initialTheme: ResponsiveLayoutUtil.instance.isMobile && DeviceInfo.instance.isMobile ? null : ThemeList.darkTheme,
249 );
250
251 if (_isSetupFinished) {
lib/entities/main_actions.dart
+1
@@ -6,6 +6,7 @@ import 'package:cake_wallet/generated/i18n.dart';
6 import 'package:cake_wallet/routes.dart';
7 import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
8 import 'package:cake_wallet/utils/device_info.dart';
9 +import 'package:cake_wallet/utils/responsive_layout_util.dart';
10 import 'package:cake_wallet/utils/show_pop_up.dart';
11 import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
12 import 'package:cw_core/wallet_type.dart';
lib/main.dart
+4 -1
@@ -6,6 +6,7 @@ import 'package:cake_wallet/buy/order.dart';
6 import 'package:cake_wallet/locales/locale.dart';
7 import 'package:cake_wallet/store/yat/yat_store.dart';
8 import 'package:cake_wallet/utils/exception_handler.dart';
9 +import 'package:cake_wallet/utils/responsive_layout_util.dart';
10 import 'package:flutter/foundation.dart';
11 import 'package:flutter/material.dart';
12 import 'package:flutter/services.dart';
@@ -194,7 +195,9 @@ class App extends StatefulWidget {
195 class AppState extends State<App> with SingleTickerProviderStateMixin {
196 AppState() : yatStore = getIt.get<YatStore>() {
197 SystemChrome.setPreferredOrientations(
197 - [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
198 + ResponsiveLayoutUtil.instance.isIpad ?
199 + [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight] :
200 + [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
201 }
202
203 YatStore yatStore;
lib/src/screens/dashboard/dashboard_page.dart
+1 -1
@@ -43,7 +43,7 @@ class DashboardPage extends StatelessWidget {
43 @override
44 Widget build(BuildContext context) {
45 return Scaffold(
46 - body: ResponsiveLayoutUtil.instance.isMobile(context)
46 + body: ResponsiveLayoutUtil.instance.isMobile
47 ? _DashboardPageView(
48 balancePage: balancePage,
49 dashboardViewModel: dashboardViewModel,
lib/src/screens/dashboard/widgets/address_page.dart
+1 -1
@@ -73,7 +73,7 @@ class AddressPage extends BasePage {
73 ? closeButtonImageDarkTheme
74 : closeButtonImage;
75
76 - bool isMobileView = ResponsiveLayoutUtil.instance.isMobile(context);
76 + bool isMobileView = ResponsiveLayoutUtil.instance.isMobile;
77
78 return MergeSemantics(
79 child: SizedBox(
lib/src/screens/dashboard/widgets/balance_page.dart
+16 -13
@@ -120,19 +120,22 @@ class BalancePage extends StatelessWidget {
120 .backgroundColor!,
121 height: 1)),
122 SizedBox(height: 5),
123 - Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
124 - AutoSizeText(availableBalance,
125 - style: TextStyle(
126 - fontSize: 24,
127 - fontFamily: 'Lato',
128 - fontWeight: FontWeight.w900,
129 - color: Theme.of(context)
130 - .accentTextTheme!
131 - .displayMedium!
132 - .backgroundColor!,
133 - height: 1),
134 - maxLines: 1,
135 - textAlign: TextAlign.center),
123 + Row(
124 + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
125 + Expanded(
126 + child: AutoSizeText(availableBalance,
127 + style: TextStyle(
128 + fontSize: 24,
129 + fontFamily: 'Lato',
130 + fontWeight: FontWeight.w900,
131 + color: Theme.of(context)
132 + .accentTextTheme!
133 + .displayMedium!
134 + .backgroundColor!,
135 + height: 1),
136 + maxLines: 1,
137 + textAlign: TextAlign.start),
138 + ),
139 Text(currency,
140 style: TextStyle(
141 fontSize: 28,
lib/src/screens/dashboard/widgets/transactions_page.dart
+1 -1
@@ -31,7 +31,7 @@ class TransactionsPage extends StatelessWidget {
31 onLongPressUp: () => dashboardViewModel.balanceViewModel.isReversing =
32 !dashboardViewModel.balanceViewModel.isReversing,
33 child: Container(
34 - color: ResponsiveLayoutUtil.instance.isMobile(context)
34 + color: ResponsiveLayoutUtil.instance.isMobile
35 ? null
36 : Theme.of(context).colorScheme.background,
37 padding: EdgeInsets.only(top: 24, bottom: 24),
lib/src/screens/exchange/exchange_page.dart
+2 -2
@@ -117,7 +117,7 @@ class ExchangePage extends BasePage {
117 final _closeButton = currentTheme.type == ThemeType.dark
118 ? closeButtonImageDarkTheme : closeButtonImage;
119
120 - bool isMobileView = ResponsiveLayoutUtil.instance.isMobile(context);
120 + bool isMobileView = ResponsiveLayoutUtil.instance.isMobile;
121
122 return MergeSemantics(
123 child: SizedBox(
@@ -731,7 +731,7 @@ class ExchangePage extends BasePage {
731 },
732 ));
733
734 - if (ResponsiveLayoutUtil.instance.isMobile(context)) {
734 + if (ResponsiveLayoutUtil.instance.isMobile) {
735 return MobileExchangeCardsSection(
736 firstExchangeCard: firstExchangeCard,
737 secondExchangeCard: secondExchangeCard,
lib/src/screens/receive/anonpay_invoice_page.dart
+24 -25
@@ -9,6 +9,7 @@ import 'package:cake_wallet/src/screens/receive/widgets/anonpay_input_form.dart'
9 import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
10 import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
11 import 'package:cake_wallet/utils/device_info.dart';
12 +import 'package:cake_wallet/utils/responsive_layout_util.dart';
13 import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart';
14 import 'package:cake_wallet/view_model/dashboard/receive_option_view_model.dart';
15 import 'package:flutter/material.dart';
@@ -88,32 +89,30 @@ class AnonPayInvoicePage extends BasePage {
89 .accentTextTheme!
90 .bodyLarge!
91 .backgroundColor!,
91 - nextFocus: false,
92 - actions: [
93 - KeyboardActionsItem(
94 - focusNode: _amountFocusNode,
95 - toolbarButtons: [(_) => KeyboardDoneButton()],
92 + nextFocus: false,
93 + actions: [
94 + KeyboardActionsItem(
95 + focusNode: _amountFocusNode,
96 + toolbarButtons: [(_) => KeyboardDoneButton()],
97 + ),
98 + ]),
99 + child: Container(
100 + color: Theme.of(context).colorScheme.background,
101 + child: ScrollableWithBottomSection(
102 + contentPadding: EdgeInsets.only(bottom: 24),
103 + content: Container(
104 + decoration: ResponsiveLayoutUtil.instance.isMobile ? BoxDecoration(
105 + borderRadius: BorderRadius.only(
106 + bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
107 + gradient: LinearGradient(
108 + colors: [
109 + Theme.of(context).primaryTextTheme!.titleSmall!.color!,
110 + Theme.of(context).primaryTextTheme!.titleSmall!.decorationColor!,
111 + ],
112 + begin: Alignment.topLeft,
113 + end: Alignment.bottomRight,
114 ),
97 - ]),
98 - child: Container(
99 - color: Theme.of(context).colorScheme.background,
100 - child: ScrollableWithBottomSection(
101 - contentPadding: EdgeInsets.only(bottom: 24),
102 - content: Container(
103 - decoration: DeviceInfo.instance.isMobile
104 - ? BoxDecoration(
105 - borderRadius: BorderRadius.only(
106 - bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
107 - gradient: LinearGradient(
108 - colors: [
109 - Theme.of(context).primaryTextTheme!.titleSmall!.color!,
110 - Theme.of(context).primaryTextTheme!.titleSmall!.decorationColor!,
111 - ],
112 - begin: Alignment.topLeft,
113 - end: Alignment.bottomRight,
114 - ),
115 - )
116 - : null,
115 + ) : null,
116 child: Observer(builder: (_) {
117 return Padding(
118 padding: EdgeInsets.fromLTRB(24, 120, 24, 0),
lib/src/screens/receive/widgets/currency_input_field.dart
+21 -13
@@ -1,4 +1,5 @@
1 import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
2 +import 'package:cake_wallet/utils/responsive_layout_util.dart';
3 import 'package:cw_core/currency.dart';
4 import 'package:flutter/material.dart';
5 import 'package:flutter/services.dart';
@@ -9,7 +10,8 @@ class CurrencyInputField extends StatelessWidget {
10 required this.onTapPicker,
11 required this.selectedCurrency,
12 this.focusNode,
12 - required this.controller, required this.isLight,
13 + required this.controller,
14 + required this.isLight,
15 });
16
17 final Function() onTapPicker;
@@ -22,13 +24,12 @@ class CurrencyInputField extends StatelessWidget {
24 Widget build(BuildContext context) {
25 final arrowBottomPurple = Image.asset(
26 'assets/images/arrow_bottom_purple_icon.png',
25 - color: Theme.of(context)
26 - .accentTextTheme!
27 - .displayMedium!
28 - .backgroundColor!,
27 + color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!,
28 height: 8,
29 );
31 - final _width = MediaQuery.of(context).size.width;
30 + // This magic number for wider screen sets the text input focus at center of the inputfield
31 + final _width =
32 + ResponsiveLayoutUtil.instance.isMobile ? MediaQuery.of(context).size.width : 500;
33
34 return Column(
35 children: [
@@ -42,10 +43,12 @@ class CurrencyInputField extends StatelessWidget {
43 keyboardType: TextInputType.numberWithOptions(signed: false, decimal: true),
44 inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'^\d+(\.|\,)?\d{0,8}'))],
45 hintText: '0.000',
45 - placeholderTextStyle: isLight ? null : TextStyle(
46 - color: Theme.of(context).primaryTextTheme!.headlineSmall!.color!,
47 - fontWeight: FontWeight.w600,
48 - ),
46 + placeholderTextStyle: isLight
47 + ? null
48 + : TextStyle(
49 + color: Theme.of(context).primaryTextTheme!.headlineSmall!.color!,
50 + fontWeight: FontWeight.w600,
51 + ),
52 borderColor: Theme.of(context).accentTextTheme!.titleLarge!.backgroundColor!,
53 textColor: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!,
54 textStyle: TextStyle(
@@ -72,7 +75,10 @@ class CurrencyInputField extends StatelessWidget {
75 style: TextStyle(
76 fontWeight: FontWeight.w600,
77 fontSize: 16,
75 - color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!,
78 + color: Theme.of(context)
79 + .accentTextTheme!
80 + .displayMedium!
81 + .backgroundColor!,
82 ),
83 ),
84 if (selectedCurrency.tag != null)
@@ -107,8 +113,10 @@ class CurrencyInputField extends StatelessWidget {
113 style: TextStyle(
114 fontWeight: FontWeight.w600,
115 fontSize: 20,
110 - color:
111 - Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!,
116 + color: Theme.of(context)
117 + .accentTextTheme!
118 + .displayMedium!
119 + .backgroundColor!,
120 ),
121 ),
122 ),
lib/src/screens/send/send_page.dart
+2 -2
@@ -62,7 +62,7 @@ class SendPage extends BasePage {
62 final _closeButton = currentTheme.type == ThemeType.dark
63 ? closeButtonImageDarkTheme : closeButtonImage;
64
65 - bool isMobileView = ResponsiveLayoutUtil.instance.isMobile(context);
65 + bool isMobileView = ResponsiveLayoutUtil.instance.isMobile;
66
67 return MergeSemantics(
68 child: SizedBox(
@@ -92,7 +92,7 @@ class SendPage extends BasePage {
92 double _sendCardHeight(BuildContext context) {
93 final double initialHeight = sendViewModel.isElectrumWallet ? 490 : 465;
94
95 - if (!ResponsiveLayoutUtil.instance.isMobile(context)) {
95 + if (!ResponsiveLayoutUtil.instance.isMobile) {
96 return initialHeight - 66;
97 }
98 return initialHeight;
lib/src/screens/send/widgets/send_card.dart
+3 -3
@@ -122,7 +122,7 @@ class SendCardState extends State<SendCard>
122 color: Colors.transparent,
123 )),
124 Container(
125 - decoration: ResponsiveLayoutUtil.instance.isMobile(context) ? BoxDecoration(
125 + decoration: ResponsiveLayoutUtil.instance.isMobile ? BoxDecoration(
126 borderRadius: BorderRadius.only(
127 bottomLeft: Radius.circular(24),
128 bottomRight: Radius.circular(24)),
@@ -137,9 +137,9 @@ class SendCardState extends State<SendCard>
137 child: Padding(
138 padding: EdgeInsets.fromLTRB(
139 24,
140 - ResponsiveLayoutUtil.instance.isMobile(context) ? 100 : 55,
140 + ResponsiveLayoutUtil.instance.isMobile ? 100 : 55,
141 24,
142 - ResponsiveLayoutUtil.instance.isMobile(context) ? 32 : 0,
142 + ResponsiveLayoutUtil.instance.isMobile ? 32 : 0,
143 ),
144 child: SingleChildScrollView(
145 child: Observer(builder: (_) => Column(
lib/src/screens/settings/display_settings_page.dart
+15 -10
@@ -8,6 +8,7 @@ import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.
8 import 'package:cake_wallet/themes/theme_base.dart';
9 import 'package:cake_wallet/themes/theme_list.dart';
10 import 'package:cake_wallet/utils/device_info.dart';
11 +import 'package:cake_wallet/utils/responsive_layout_util.dart';
12 import 'package:cake_wallet/view_model/settings/choices_list_item.dart';
13 import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart';
14 import 'package:flutter/material.dart';
@@ -29,11 +30,11 @@ class DisplaySettingsPage extends BasePage {
30 child: Column(
31 children: [
32 SettingsSwitcherCell(
32 - title: S.current.settings_display_balance,
33 - value: _displaySettingsViewModel.shouldDisplayBalance,
34 - onValueChange: (_, bool value) {
35 - _displaySettingsViewModel.setShouldDisplayBalance(value);
36 - }),
33 + title: S.current.settings_display_balance,
34 + value: _displaySettingsViewModel.shouldDisplayBalance,
35 + onValueChange: (_, bool value) {
36 + _displaySettingsViewModel.setShouldDisplayBalance(value);
37 + }),
38 SettingsSwitcherCell(
39 title: S.current.show_market_place,
40 value: _displaySettingsViewModel.shouldShowMarketPlaceInDashboard,
@@ -42,14 +43,17 @@ class DisplaySettingsPage extends BasePage {
43 },
44 ),
45 //if (!isHaven) it does not work correctly
45 - if(!_displaySettingsViewModel.disabledFiatApiMode)
46 + if (!_displaySettingsViewModel.disabledFiatApiMode)
47 SettingsPickerCell<FiatCurrency>(
48 title: S.current.settings_currency,
49 searchHintText: S.current.search_currency,
50 items: FiatCurrency.all,
51 selectedItem: _displaySettingsViewModel.fiatCurrency,
51 - onItemSelected: (FiatCurrency currency) => _displaySettingsViewModel.setFiatCurrency(currency),
52 - images: FiatCurrency.all.map((e) => Image.asset("assets/images/flags/${e.countryCode}.png")).toList(),
52 + onItemSelected: (FiatCurrency currency) =>
53 + _displaySettingsViewModel.setFiatCurrency(currency),
54 + images: FiatCurrency.all
55 + .map((e) => Image.asset("assets/images/flags/${e.countryCode}.png"))
56 + .toList(),
57 isGridView: true,
58 matchingCriteria: (FiatCurrency currency, String searchText) {
59 return currency.title.toLowerCase().contains(searchText) ||
@@ -66,13 +70,14 @@ class DisplaySettingsPage extends BasePage {
70 selectedItem: _displaySettingsViewModel.languageCode,
71 onItemSelected: _displaySettingsViewModel.onLanguageSelected,
72 images: LanguageService.list.keys
69 - .map((e) => Image.asset("assets/images/flags/${LanguageService.localeCountryCode[e]}.png"))
73 + .map((e) => Image.asset(
74 + "assets/images/flags/${LanguageService.localeCountryCode[e]}.png"))
75 .toList(),
76 matchingCriteria: (String code, String searchText) {
77 return LanguageService.list[code]?.toLowerCase().contains(searchText) ?? false;
78 },
79 ),
75 - if (DeviceInfo.instance.isMobile)
80 + if (ResponsiveLayoutUtil.instance.isMobile && DeviceInfo.instance.isMobile)
81 SettingsChoicesCell(
82 ChoicesListItem<ThemeBase>(
83 title: S.current.color_theme,
lib/src/screens/wallet_list/wallet_list_page.dart
+2 -2
@@ -1,6 +1,6 @@
1 import 'package:cake_wallet/core/auth_service.dart';
2 import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
3 -import 'package:cake_wallet/utils/device_info.dart';
3 +import 'package:cake_wallet/utils/responsive_layout_util.dart';
4 import 'package:cake_wallet/utils/show_bar.dart';
5 import 'package:cake_wallet/utils/show_pop_up.dart';
6 import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
@@ -229,7 +229,7 @@ class WalletListBodyState extends State<WalletListBody> {
229 await hideProgressText();
230 // only pop the wallets route in mobile as it will go back to dashboard page
231 // in desktop platforms the navigation tree is different
232 - if (DeviceInfo.instance.isMobile) {
232 + if (ResponsiveLayoutUtil.instance.isMobile) {
233 WidgetsBinding.instance.addPostFrameCallback((_) {
234 Navigator.of(context).pop();
235 });
lib/src/widgets/add_template_button.dart
+1 -1
@@ -26,7 +26,7 @@ class AddTemplateButton extends StatelessWidget {
26 child: Container(
27 height: 34,
28 padding: EdgeInsets.symmetric(
29 - horizontal: ResponsiveLayoutUtil.instance.isMobile(context) ? 10 : 30),
29 + horizontal: ResponsiveLayoutUtil.instance.isMobile ? 10 : 30),
30 alignment: Alignment.center,
31 decoration: BoxDecoration(
32 borderRadius: BorderRadius.all(Radius.circular(20)),
lib/src/widgets/address_text_field.dart
+2 -2
@@ -1,6 +1,6 @@
1 -import 'dart:io';
1
2 import 'package:cake_wallet/utils/device_info.dart';
3 +import 'package:cake_wallet/utils/responsive_layout_util.dart';
4 import 'package:flutter/services.dart';
5 import 'package:flutter/material.dart';
6 import 'package:cake_wallet/routes.dart';
@@ -105,7 +105,7 @@ class AddressTextField extends StatelessWidget {
105 width: prefixIconWidth * options.length +
106 (spaceBetweenPrefixIcons * options.length),
107 child: Row(
108 - mainAxisAlignment: DeviceInfo.instance.isMobile
108 + mainAxisAlignment: ResponsiveLayoutUtil.instance.isMobile
109 ? MainAxisAlignment.spaceBetween : MainAxisAlignment.end,
110 children: [
111 SizedBox(width: 5),
lib/utils/exception_handler.dart
+10 -11
@@ -130,17 +130,16 @@ class ExceptionHandler {
130 _ignoredErrors.any((element) => error.contains(element));
131
132 static const List<String> _ignoredErrors = const [
133 - "errno = 9", // SocketException: Bad file descriptor
134 - "errno = 28", // OS Error: No space left on device
135 - "errno = 32", // SocketException: Write failed (OS Error: Broken pipe)
136 - "errno = 49", // SocketException: Can't assign requested address
137 - "errno = 54", // SocketException: Connection reset by peer
138 - "errno = 57", // SocketException: Read failed (OS Error: Socket is not connected)
139 - "errno = 60", // SocketException: Operation timed out
140 - "errno = 65", // SocketException: No route to host
141 - "errno = 103", // SocketException: Software caused connection abort
142 - "errno = 104", // SocketException: Connection reset by peer
143 - "errno = 110", // SocketException: Connection timed out
133 + "Bad file descriptor",
134 + "No space left on device",
135 + "Write failed (OS Error: Broken pipe)",
136 + "Can't assign requested address",
137 + "Read failed (OS Error: Socket is not connected)",
138 + "Operation timed out",
139 + "No route to host",
140 + "Software caused connection abort",
141 + "Connection reset by peer",
142 + "Connection timed out",
143 "Connection reset by peer",
144 "Connection closed before full header was received",
145 "Connection terminated during handshake",
lib/utils/responsive_layout_util.dart
+9 -7
@@ -1,33 +1,35 @@
1 import 'package:flutter/material.dart';
2
3 class ResponsiveLayoutUtil {
4 - static const double _kMobileThreshold = 900;
4 + static const double _kMobileThreshold = 768;
5 static const double kDesktopMaxWidthConstraint = 400;
6 static const double kPopupWidth = 400;
7 static const double kPopupSpaceHeight = 100;
8 -
8 + static const _kIpadMaxWidth = 2560.0;
9
10 const ResponsiveLayoutUtil._();
11
12 static final instance = ResponsiveLayoutUtil._();
13
14 - bool isMobile(BuildContext context) {
15 - final MediaQueryData mediaQueryData = MediaQuery.of(context);
16 - return mediaQueryData.size.width < _kMobileThreshold;
14 + bool get isMobile =>
15 + WidgetsBinding.instance.platformDispatcher.views.first.physicalSize.width < _kMobileThreshold;
16 +
17 + bool get isIpad {
18 + final width = WidgetsBinding.instance.platformDispatcher.views.first.physicalSize.width;
19 + return width >= _kMobileThreshold && !(width > _kIpadMaxWidth);
20 }
21
22 /// Returns dynamic size.
23 ///
24 /// If screen size is mobile, it returns 66% ([scale]) of the [originalValue].
25 double getDynamicSize(
23 - BuildContext context,
26 double originalValue, {
27 double? mobileSize,
28 double? scale,
29 }) {
30 scale ??= 2 / 3;
31 mobileSize ??= originalValue * scale;
30 - final value = isMobile(context) ? mobileSize : originalValue;
32 + final value = isMobile ? mobileSize : originalValue;
33
34 return value.roundToDouble();
35 }