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>
This commit is contained in:
Godwin Asuquo 2023-06-14 02:04:52 +03:00 committed by GitHub
parent e84d02f661
commit affc35f335
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
34 changed files with 144 additions and 110 deletions

View file

@ -4,9 +4,9 @@ PODS:
- MTBBarcodeScanner - MTBBarcodeScanner
- SwiftProtobuf - SwiftProtobuf
- BigInt (5.2.0) - BigInt (5.2.0)
- connectivity (0.0.1): - connectivity_plus (0.0.1):
- Flutter - Flutter
- Reachability - ReachabilitySwift
- CryptoSwift (1.6.0) - CryptoSwift (1.6.0)
- cw_haven (0.0.1): - cw_haven (0.0.1):
- cw_haven/Boost (= 0.0.1) - cw_haven/Boost (= 0.0.1)
@ -126,11 +126,11 @@ PODS:
- path_provider_foundation (0.0.1): - path_provider_foundation (0.0.1):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
- permission_handler_apple (9.0.4): - permission_handler_apple (9.1.0):
- Flutter - Flutter
- platform_device_id (0.0.1): - platform_device_id (0.0.1):
- Flutter - Flutter
- Reachability (3.2) - ReachabilitySwift (5.0.0)
- SDWebImage (5.15.5): - SDWebImage (5.15.5):
- SDWebImage/Core (= 5.15.5) - SDWebImage/Core (= 5.15.5)
- SDWebImage/Core (5.15.5) - SDWebImage/Core (5.15.5)
@ -153,7 +153,7 @@ PODS:
DEPENDENCIES: DEPENDENCIES:
- barcode_scan2 (from `.symlinks/plugins/barcode_scan2/ios`) - barcode_scan2 (from `.symlinks/plugins/barcode_scan2/ios`)
- connectivity (from `.symlinks/plugins/connectivity/ios`) - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
- CryptoSwift - CryptoSwift
- cw_haven (from `.symlinks/plugins/cw_haven/ios`) - cw_haven (from `.symlinks/plugins/cw_haven/ios`)
- cw_monero (from `.symlinks/plugins/cw_monero/ios`) - cw_monero (from `.symlinks/plugins/cw_monero/ios`)
@ -188,7 +188,7 @@ SPEC REPOS:
- DKPhotoGallery - DKPhotoGallery
- MTBBarcodeScanner - MTBBarcodeScanner
- OrderedSet - OrderedSet
- Reachability - ReachabilitySwift
- SDWebImage - SDWebImage
- SwiftProtobuf - SwiftProtobuf
- SwiftyGif - SwiftyGif
@ -197,8 +197,8 @@ SPEC REPOS:
EXTERNAL SOURCES: EXTERNAL SOURCES:
barcode_scan2: barcode_scan2:
:path: ".symlinks/plugins/barcode_scan2/ios" :path: ".symlinks/plugins/barcode_scan2/ios"
connectivity: connectivity_plus:
:path: ".symlinks/plugins/connectivity/ios" :path: ".symlinks/plugins/connectivity_plus/ios"
cw_haven: cw_haven:
:path: ".symlinks/plugins/cw_haven/ios" :path: ".symlinks/plugins/cw_haven/ios"
cw_monero: cw_monero:
@ -249,7 +249,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS: SPEC CHECKSUMS:
barcode_scan2: 0af2bb63c81b4565aab6cd78278e4c0fa136dbb0 barcode_scan2: 0af2bb63c81b4565aab6cd78278e4c0fa136dbb0
BigInt: f668a80089607f521586bbe29513d708491ef2f7 BigInt: f668a80089607f521586bbe29513d708491ef2f7
connectivity: c4130b2985d4ef6fd26f9702e886bd5260681467 connectivity_plus: 413a8857dd5d9f1c399a39130850d02fe0feaf7e
CryptoSwift: 562f8eceb40e80796fffc668b0cad9313284cfa6 CryptoSwift: 562f8eceb40e80796fffc668b0cad9313284cfa6
cw_haven: b3e54e1fbe7b8e6fda57a93206bc38f8e89b898a cw_haven: b3e54e1fbe7b8e6fda57a93206bc38f8e89b898a
cw_monero: 4cf3b96f2da8e95e2ef7d6703dd4d2c509127b7d cw_monero: 4cf3b96f2da8e95e2ef7d6703dd4d2c509127b7d
@ -271,9 +271,9 @@ SPEC CHECKSUMS:
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62 package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8 path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce permission_handler_apple: 8f116445eff3c0e7c65ad60f5fef5490aa94b4e4
platform_device_id: 81b3e2993881f87d0c82ef151dc274df4869aef5 platform_device_id: 81b3e2993881f87d0c82ef151dc274df4869aef5
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
SDWebImage: fd7e1a22f00303e058058278639bf6196ee431fe SDWebImage: fd7e1a22f00303e058058278639bf6196ee431fe
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68 share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c

View file

@ -390,7 +390,7 @@
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1; TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = arm64; VALID_ARCHS = arm64;
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
}; };
@ -537,7 +537,7 @@
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1; TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = arm64; VALID_ARCHS = arm64;
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
}; };
@ -574,7 +574,7 @@
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1; TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = arm64; VALID_ARCHS = arm64;
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
}; };

View file

@ -1,21 +1,25 @@
{ {
"images" : [ "images" : [
{ {
"filename" : "Icon-App-40x40@1x.png",
"idiom" : "iphone", "idiom" : "iphone",
"scale" : "2x", "scale" : "2x",
"size" : "20x20" "size" : "20x20"
}, },
{ {
"filename" : "Icon-App-20x20@3x.png",
"idiom" : "iphone", "idiom" : "iphone",
"scale" : "3x", "scale" : "3x",
"size" : "20x20" "size" : "20x20"
}, },
{ {
"filename" : "Icon-App-29x29@2x 1.png",
"idiom" : "iphone", "idiom" : "iphone",
"scale" : "2x", "scale" : "2x",
"size" : "29x29" "size" : "29x29"
}, },
{ {
"filename" : "Icon-App-29x29@3x.png",
"idiom" : "iphone", "idiom" : "iphone",
"scale" : "3x", "scale" : "3x",
"size" : "29x29" "size" : "29x29"
@ -26,6 +30,7 @@
"size" : "40x40" "size" : "40x40"
}, },
{ {
"filename" : "Icon-App-40x40@3x.png",
"idiom" : "iphone", "idiom" : "iphone",
"scale" : "3x", "scale" : "3x",
"size" : "40x40" "size" : "40x40"
@ -43,26 +48,31 @@
"size" : "60x60" "size" : "60x60"
}, },
{ {
"filename" : "Icon-App-20x20@1x.png",
"idiom" : "ipad", "idiom" : "ipad",
"scale" : "1x", "scale" : "1x",
"size" : "20x20" "size" : "20x20"
}, },
{ {
"filename" : "Icon-App-20x20@2x.png",
"idiom" : "ipad", "idiom" : "ipad",
"scale" : "2x", "scale" : "2x",
"size" : "20x20" "size" : "20x20"
}, },
{ {
"filename" : "Icon-App-29x29@1x.png",
"idiom" : "ipad", "idiom" : "ipad",
"scale" : "1x", "scale" : "1x",
"size" : "29x29" "size" : "29x29"
}, },
{ {
"filename" : "Icon-App-29x29@2x.png",
"idiom" : "ipad", "idiom" : "ipad",
"scale" : "2x", "scale" : "2x",
"size" : "29x29" "size" : "29x29"
}, },
{ {
"filename" : "Icon-App-40x40@1x 1.png",
"idiom" : "ipad", "idiom" : "ipad",
"scale" : "1x", "scale" : "1x",
"size" : "40x40" "size" : "40x40"
@ -73,16 +83,19 @@
"size" : "40x40" "size" : "40x40"
}, },
{ {
"filename" : "Icon-App-76x76@1x.png",
"idiom" : "ipad", "idiom" : "ipad",
"scale" : "1x", "scale" : "1x",
"size" : "76x76" "size" : "76x76"
}, },
{ {
"filename" : "Icon-App-76x76@2x.png",
"idiom" : "ipad", "idiom" : "ipad",
"scale" : "2x", "scale" : "2x",
"size" : "76x76" "size" : "76x76"
}, },
{ {
"filename" : "Icon-App-83.5x83.5@2x.png",
"idiom" : "ipad", "idiom" : "ipad",
"scale" : "2x", "scale" : "2x",
"size" : "83.5x83.5" "size" : "83.5x83.5"

Binary file not shown.

After

Width:  |  Height:  |  Size: 880 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -36,6 +36,7 @@ import 'package:cake_wallet/themes/theme_list.dart';
import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/device_info.dart';
import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.dart'; import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.dart';
import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/utils/payment_request.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart';
import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart'; import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart';
import 'package:cake_wallet/view_model/anonpay_details_view_model.dart'; import 'package:cake_wallet/view_model/anonpay_details_view_model.dart';
@ -244,7 +245,7 @@ Future setup({
nodeSource: _nodeSource, nodeSource: _nodeSource,
isBitcoinBuyEnabled: isBitcoinBuyEnabled, isBitcoinBuyEnabled: isBitcoinBuyEnabled,
// Enforce darkTheme on platforms other than mobile till the design for other themes is completed // Enforce darkTheme on platforms other than mobile till the design for other themes is completed
initialTheme: DeviceInfo.instance.isMobile ? null : ThemeList.darkTheme, initialTheme: ResponsiveLayoutUtil.instance.isMobile && DeviceInfo.instance.isMobile ? null : ThemeList.darkTheme,
); );
if (_isSetupFinished) { if (_isSetupFinished) {

View file

@ -6,6 +6,7 @@ import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/device_info.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';

View file

@ -6,6 +6,7 @@ import 'package:cake_wallet/buy/order.dart';
import 'package:cake_wallet/locales/locale.dart'; import 'package:cake_wallet/locales/locale.dart';
import 'package:cake_wallet/store/yat/yat_store.dart'; import 'package:cake_wallet/store/yat/yat_store.dart';
import 'package:cake_wallet/utils/exception_handler.dart'; import 'package:cake_wallet/utils/exception_handler.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@ -194,7 +195,9 @@ class App extends StatefulWidget {
class AppState extends State<App> with SingleTickerProviderStateMixin { class AppState extends State<App> with SingleTickerProviderStateMixin {
AppState() : yatStore = getIt.get<YatStore>() { AppState() : yatStore = getIt.get<YatStore>() {
SystemChrome.setPreferredOrientations( SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); ResponsiveLayoutUtil.instance.isIpad ?
[DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight] :
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
} }
YatStore yatStore; YatStore yatStore;

View file

@ -43,7 +43,7 @@ class DashboardPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
body: ResponsiveLayoutUtil.instance.isMobile(context) body: ResponsiveLayoutUtil.instance.isMobile
? _DashboardPageView( ? _DashboardPageView(
balancePage: balancePage, balancePage: balancePage,
dashboardViewModel: dashboardViewModel, dashboardViewModel: dashboardViewModel,

View file

@ -73,7 +73,7 @@ class AddressPage extends BasePage {
? closeButtonImageDarkTheme ? closeButtonImageDarkTheme
: closeButtonImage; : closeButtonImage;
bool isMobileView = ResponsiveLayoutUtil.instance.isMobile(context); bool isMobileView = ResponsiveLayoutUtil.instance.isMobile;
return MergeSemantics( return MergeSemantics(
child: SizedBox( child: SizedBox(

View file

@ -120,19 +120,22 @@ class BalancePage extends StatelessWidget {
.backgroundColor!, .backgroundColor!,
height: 1)), height: 1)),
SizedBox(height: 5), SizedBox(height: 5),
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row(
AutoSizeText(availableBalance, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
style: TextStyle( Expanded(
fontSize: 24, child: AutoSizeText(availableBalance,
fontFamily: 'Lato', style: TextStyle(
fontWeight: FontWeight.w900, fontSize: 24,
color: Theme.of(context) fontFamily: 'Lato',
.accentTextTheme! fontWeight: FontWeight.w900,
.displayMedium! color: Theme.of(context)
.backgroundColor!, .accentTextTheme!
height: 1), .displayMedium!
maxLines: 1, .backgroundColor!,
textAlign: TextAlign.center), height: 1),
maxLines: 1,
textAlign: TextAlign.start),
),
Text(currency, Text(currency,
style: TextStyle( style: TextStyle(
fontSize: 28, fontSize: 28,

View file

@ -31,7 +31,7 @@ class TransactionsPage extends StatelessWidget {
onLongPressUp: () => dashboardViewModel.balanceViewModel.isReversing = onLongPressUp: () => dashboardViewModel.balanceViewModel.isReversing =
!dashboardViewModel.balanceViewModel.isReversing, !dashboardViewModel.balanceViewModel.isReversing,
child: Container( child: Container(
color: ResponsiveLayoutUtil.instance.isMobile(context) color: ResponsiveLayoutUtil.instance.isMobile
? null ? null
: Theme.of(context).colorScheme.background, : Theme.of(context).colorScheme.background,
padding: EdgeInsets.only(top: 24, bottom: 24), padding: EdgeInsets.only(top: 24, bottom: 24),

View file

@ -117,7 +117,7 @@ class ExchangePage extends BasePage {
final _closeButton = currentTheme.type == ThemeType.dark final _closeButton = currentTheme.type == ThemeType.dark
? closeButtonImageDarkTheme : closeButtonImage; ? closeButtonImageDarkTheme : closeButtonImage;
bool isMobileView = ResponsiveLayoutUtil.instance.isMobile(context); bool isMobileView = ResponsiveLayoutUtil.instance.isMobile;
return MergeSemantics( return MergeSemantics(
child: SizedBox( child: SizedBox(
@ -731,7 +731,7 @@ class ExchangePage extends BasePage {
}, },
)); ));
if (ResponsiveLayoutUtil.instance.isMobile(context)) { if (ResponsiveLayoutUtil.instance.isMobile) {
return MobileExchangeCardsSection( return MobileExchangeCardsSection(
firstExchangeCard: firstExchangeCard, firstExchangeCard: firstExchangeCard,
secondExchangeCard: secondExchangeCard, secondExchangeCard: secondExchangeCard,

View file

@ -9,6 +9,7 @@ import 'package:cake_wallet/src/screens/receive/widgets/anonpay_input_form.dart'
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/device_info.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart'; import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart';
import 'package:cake_wallet/view_model/dashboard/receive_option_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/receive_option_view_model.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -88,32 +89,30 @@ class AnonPayInvoicePage extends BasePage {
.accentTextTheme! .accentTextTheme!
.bodyLarge! .bodyLarge!
.backgroundColor!, .backgroundColor!,
nextFocus: false, nextFocus: false,
actions: [ actions: [
KeyboardActionsItem( KeyboardActionsItem(
focusNode: _amountFocusNode, focusNode: _amountFocusNode,
toolbarButtons: [(_) => KeyboardDoneButton()], toolbarButtons: [(_) => KeyboardDoneButton()],
),
]),
child: Container(
color: Theme.of(context).colorScheme.background,
child: ScrollableWithBottomSection(
contentPadding: EdgeInsets.only(bottom: 24),
content: Container(
decoration: ResponsiveLayoutUtil.instance.isMobile ? BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
gradient: LinearGradient(
colors: [
Theme.of(context).primaryTextTheme!.titleSmall!.color!,
Theme.of(context).primaryTextTheme!.titleSmall!.decorationColor!,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
), ),
]), ) : null,
child: Container(
color: Theme.of(context).colorScheme.background,
child: ScrollableWithBottomSection(
contentPadding: EdgeInsets.only(bottom: 24),
content: Container(
decoration: DeviceInfo.instance.isMobile
? BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
gradient: LinearGradient(
colors: [
Theme.of(context).primaryTextTheme!.titleSmall!.color!,
Theme.of(context).primaryTextTheme!.titleSmall!.decorationColor!,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
)
: null,
child: Observer(builder: (_) { child: Observer(builder: (_) {
return Padding( return Padding(
padding: EdgeInsets.fromLTRB(24, 120, 24, 0), padding: EdgeInsets.fromLTRB(24, 120, 24, 0),

View file

@ -1,4 +1,5 @@
import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cw_core/currency.dart'; import 'package:cw_core/currency.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@ -9,7 +10,8 @@ class CurrencyInputField extends StatelessWidget {
required this.onTapPicker, required this.onTapPicker,
required this.selectedCurrency, required this.selectedCurrency,
this.focusNode, this.focusNode,
required this.controller, required this.isLight, required this.controller,
required this.isLight,
}); });
final Function() onTapPicker; final Function() onTapPicker;
@ -22,13 +24,12 @@ class CurrencyInputField extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final arrowBottomPurple = Image.asset( final arrowBottomPurple = Image.asset(
'assets/images/arrow_bottom_purple_icon.png', 'assets/images/arrow_bottom_purple_icon.png',
color: Theme.of(context) color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!,
.accentTextTheme!
.displayMedium!
.backgroundColor!,
height: 8, height: 8,
); );
final _width = MediaQuery.of(context).size.width; // This magic number for wider screen sets the text input focus at center of the inputfield
final _width =
ResponsiveLayoutUtil.instance.isMobile ? MediaQuery.of(context).size.width : 500;
return Column( return Column(
children: [ children: [
@ -42,10 +43,12 @@ class CurrencyInputField extends StatelessWidget {
keyboardType: TextInputType.numberWithOptions(signed: false, decimal: true), keyboardType: TextInputType.numberWithOptions(signed: false, decimal: true),
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'^\d+(\.|\,)?\d{0,8}'))], inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'^\d+(\.|\,)?\d{0,8}'))],
hintText: '0.000', hintText: '0.000',
placeholderTextStyle: isLight ? null : TextStyle( placeholderTextStyle: isLight
color: Theme.of(context).primaryTextTheme!.headlineSmall!.color!, ? null
fontWeight: FontWeight.w600, : TextStyle(
), color: Theme.of(context).primaryTextTheme!.headlineSmall!.color!,
fontWeight: FontWeight.w600,
),
borderColor: Theme.of(context).accentTextTheme!.titleLarge!.backgroundColor!, borderColor: Theme.of(context).accentTextTheme!.titleLarge!.backgroundColor!,
textColor: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!, textColor: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!,
textStyle: TextStyle( textStyle: TextStyle(
@ -72,7 +75,10 @@ class CurrencyInputField extends StatelessWidget {
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 16, fontSize: 16,
color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!, color: Theme.of(context)
.accentTextTheme!
.displayMedium!
.backgroundColor!,
), ),
), ),
if (selectedCurrency.tag != null) if (selectedCurrency.tag != null)
@ -107,8 +113,10 @@ class CurrencyInputField extends StatelessWidget {
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 20, fontSize: 20,
color: color: Theme.of(context)
Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!, .accentTextTheme!
.displayMedium!
.backgroundColor!,
), ),
), ),
), ),

View file

@ -62,7 +62,7 @@ class SendPage extends BasePage {
final _closeButton = currentTheme.type == ThemeType.dark final _closeButton = currentTheme.type == ThemeType.dark
? closeButtonImageDarkTheme : closeButtonImage; ? closeButtonImageDarkTheme : closeButtonImage;
bool isMobileView = ResponsiveLayoutUtil.instance.isMobile(context); bool isMobileView = ResponsiveLayoutUtil.instance.isMobile;
return MergeSemantics( return MergeSemantics(
child: SizedBox( child: SizedBox(
@ -92,7 +92,7 @@ class SendPage extends BasePage {
double _sendCardHeight(BuildContext context) { double _sendCardHeight(BuildContext context) {
final double initialHeight = sendViewModel.isElectrumWallet ? 490 : 465; final double initialHeight = sendViewModel.isElectrumWallet ? 490 : 465;
if (!ResponsiveLayoutUtil.instance.isMobile(context)) { if (!ResponsiveLayoutUtil.instance.isMobile) {
return initialHeight - 66; return initialHeight - 66;
} }
return initialHeight; return initialHeight;

View file

@ -122,7 +122,7 @@ class SendCardState extends State<SendCard>
color: Colors.transparent, color: Colors.transparent,
)), )),
Container( Container(
decoration: ResponsiveLayoutUtil.instance.isMobile(context) ? BoxDecoration( decoration: ResponsiveLayoutUtil.instance.isMobile ? BoxDecoration(
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(24), bottomLeft: Radius.circular(24),
bottomRight: Radius.circular(24)), bottomRight: Radius.circular(24)),
@ -137,9 +137,9 @@ class SendCardState extends State<SendCard>
child: Padding( child: Padding(
padding: EdgeInsets.fromLTRB( padding: EdgeInsets.fromLTRB(
24, 24,
ResponsiveLayoutUtil.instance.isMobile(context) ? 100 : 55, ResponsiveLayoutUtil.instance.isMobile ? 100 : 55,
24, 24,
ResponsiveLayoutUtil.instance.isMobile(context) ? 32 : 0, ResponsiveLayoutUtil.instance.isMobile ? 32 : 0,
), ),
child: SingleChildScrollView( child: SingleChildScrollView(
child: Observer(builder: (_) => Column( child: Observer(builder: (_) => Column(

View file

@ -8,6 +8,7 @@ import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.
import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/themes/theme_base.dart';
import 'package:cake_wallet/themes/theme_list.dart'; import 'package:cake_wallet/themes/theme_list.dart';
import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/device_info.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cake_wallet/view_model/settings/choices_list_item.dart'; import 'package:cake_wallet/view_model/settings/choices_list_item.dart';
import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart'; import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -29,11 +30,11 @@ class DisplaySettingsPage extends BasePage {
child: Column( child: Column(
children: [ children: [
SettingsSwitcherCell( SettingsSwitcherCell(
title: S.current.settings_display_balance, title: S.current.settings_display_balance,
value: _displaySettingsViewModel.shouldDisplayBalance, value: _displaySettingsViewModel.shouldDisplayBalance,
onValueChange: (_, bool value) { onValueChange: (_, bool value) {
_displaySettingsViewModel.setShouldDisplayBalance(value); _displaySettingsViewModel.setShouldDisplayBalance(value);
}), }),
SettingsSwitcherCell( SettingsSwitcherCell(
title: S.current.show_market_place, title: S.current.show_market_place,
value: _displaySettingsViewModel.shouldShowMarketPlaceInDashboard, value: _displaySettingsViewModel.shouldShowMarketPlaceInDashboard,
@ -42,14 +43,17 @@ class DisplaySettingsPage extends BasePage {
}, },
), ),
//if (!isHaven) it does not work correctly //if (!isHaven) it does not work correctly
if(!_displaySettingsViewModel.disabledFiatApiMode) if (!_displaySettingsViewModel.disabledFiatApiMode)
SettingsPickerCell<FiatCurrency>( SettingsPickerCell<FiatCurrency>(
title: S.current.settings_currency, title: S.current.settings_currency,
searchHintText: S.current.search_currency, searchHintText: S.current.search_currency,
items: FiatCurrency.all, items: FiatCurrency.all,
selectedItem: _displaySettingsViewModel.fiatCurrency, selectedItem: _displaySettingsViewModel.fiatCurrency,
onItemSelected: (FiatCurrency currency) => _displaySettingsViewModel.setFiatCurrency(currency), onItemSelected: (FiatCurrency currency) =>
images: FiatCurrency.all.map((e) => Image.asset("assets/images/flags/${e.countryCode}.png")).toList(), _displaySettingsViewModel.setFiatCurrency(currency),
images: FiatCurrency.all
.map((e) => Image.asset("assets/images/flags/${e.countryCode}.png"))
.toList(),
isGridView: true, isGridView: true,
matchingCriteria: (FiatCurrency currency, String searchText) { matchingCriteria: (FiatCurrency currency, String searchText) {
return currency.title.toLowerCase().contains(searchText) || return currency.title.toLowerCase().contains(searchText) ||
@ -66,13 +70,14 @@ class DisplaySettingsPage extends BasePage {
selectedItem: _displaySettingsViewModel.languageCode, selectedItem: _displaySettingsViewModel.languageCode,
onItemSelected: _displaySettingsViewModel.onLanguageSelected, onItemSelected: _displaySettingsViewModel.onLanguageSelected,
images: LanguageService.list.keys images: LanguageService.list.keys
.map((e) => Image.asset("assets/images/flags/${LanguageService.localeCountryCode[e]}.png")) .map((e) => Image.asset(
"assets/images/flags/${LanguageService.localeCountryCode[e]}.png"))
.toList(), .toList(),
matchingCriteria: (String code, String searchText) { matchingCriteria: (String code, String searchText) {
return LanguageService.list[code]?.toLowerCase().contains(searchText) ?? false; return LanguageService.list[code]?.toLowerCase().contains(searchText) ?? false;
}, },
), ),
if (DeviceInfo.instance.isMobile) if (ResponsiveLayoutUtil.instance.isMobile && DeviceInfo.instance.isMobile)
SettingsChoicesCell( SettingsChoicesCell(
ChoicesListItem<ThemeBase>( ChoicesListItem<ThemeBase>(
title: S.current.color_theme, title: S.current.color_theme,

View file

@ -1,6 +1,6 @@
import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/core/auth_service.dart';
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_bar.dart';
import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart'; import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
@ -229,7 +229,7 @@ class WalletListBodyState extends State<WalletListBody> {
await hideProgressText(); await hideProgressText();
// only pop the wallets route in mobile as it will go back to dashboard page // only pop the wallets route in mobile as it will go back to dashboard page
// in desktop platforms the navigation tree is different // in desktop platforms the navigation tree is different
if (DeviceInfo.instance.isMobile) { if (ResponsiveLayoutUtil.instance.isMobile) {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
Navigator.of(context).pop(); Navigator.of(context).pop();
}); });

View file

@ -26,7 +26,7 @@ class AddTemplateButton extends StatelessWidget {
child: Container( child: Container(
height: 34, height: 34,
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: ResponsiveLayoutUtil.instance.isMobile(context) ? 10 : 30), horizontal: ResponsiveLayoutUtil.instance.isMobile ? 10 : 30),
alignment: Alignment.center, alignment: Alignment.center,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20)), borderRadius: BorderRadius.all(Radius.circular(20)),

View file

@ -1,6 +1,6 @@
import 'dart:io';
import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/device_info.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/routes.dart';
@ -105,7 +105,7 @@ class AddressTextField extends StatelessWidget {
width: prefixIconWidth * options.length + width: prefixIconWidth * options.length +
(spaceBetweenPrefixIcons * options.length), (spaceBetweenPrefixIcons * options.length),
child: Row( child: Row(
mainAxisAlignment: DeviceInfo.instance.isMobile mainAxisAlignment: ResponsiveLayoutUtil.instance.isMobile
? MainAxisAlignment.spaceBetween : MainAxisAlignment.end, ? MainAxisAlignment.spaceBetween : MainAxisAlignment.end,
children: [ children: [
SizedBox(width: 5), SizedBox(width: 5),

View file

@ -130,17 +130,16 @@ class ExceptionHandler {
_ignoredErrors.any((element) => error.contains(element)); _ignoredErrors.any((element) => error.contains(element));
static const List<String> _ignoredErrors = const [ static const List<String> _ignoredErrors = const [
"errno = 9", // SocketException: Bad file descriptor "Bad file descriptor",
"errno = 28", // OS Error: No space left on device "No space left on device",
"errno = 32", // SocketException: Write failed (OS Error: Broken pipe) "Write failed (OS Error: Broken pipe)",
"errno = 49", // SocketException: Can't assign requested address "Can't assign requested address",
"errno = 54", // SocketException: Connection reset by peer "Read failed (OS Error: Socket is not connected)",
"errno = 57", // SocketException: Read failed (OS Error: Socket is not connected) "Operation timed out",
"errno = 60", // SocketException: Operation timed out "No route to host",
"errno = 65", // SocketException: No route to host "Software caused connection abort",
"errno = 103", // SocketException: Software caused connection abort "Connection reset by peer",
"errno = 104", // SocketException: Connection reset by peer "Connection timed out",
"errno = 110", // SocketException: Connection timed out
"Connection reset by peer", "Connection reset by peer",
"Connection closed before full header was received", "Connection closed before full header was received",
"Connection terminated during handshake", "Connection terminated during handshake",

View file

@ -1,33 +1,35 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class ResponsiveLayoutUtil { class ResponsiveLayoutUtil {
static const double _kMobileThreshold = 900; static const double _kMobileThreshold = 768;
static const double kDesktopMaxWidthConstraint = 400; static const double kDesktopMaxWidthConstraint = 400;
static const double kPopupWidth = 400; static const double kPopupWidth = 400;
static const double kPopupSpaceHeight = 100; static const double kPopupSpaceHeight = 100;
static const _kIpadMaxWidth = 2560.0;
const ResponsiveLayoutUtil._(); const ResponsiveLayoutUtil._();
static final instance = ResponsiveLayoutUtil._(); static final instance = ResponsiveLayoutUtil._();
bool isMobile(BuildContext context) { bool get isMobile =>
final MediaQueryData mediaQueryData = MediaQuery.of(context); WidgetsBinding.instance.platformDispatcher.views.first.physicalSize.width < _kMobileThreshold;
return mediaQueryData.size.width < _kMobileThreshold;
bool get isIpad {
final width = WidgetsBinding.instance.platformDispatcher.views.first.physicalSize.width;
return width >= _kMobileThreshold && !(width > _kIpadMaxWidth);
} }
/// Returns dynamic size. /// Returns dynamic size.
/// ///
/// If screen size is mobile, it returns 66% ([scale]) of the [originalValue]. /// If screen size is mobile, it returns 66% ([scale]) of the [originalValue].
double getDynamicSize( double getDynamicSize(
BuildContext context,
double originalValue, { double originalValue, {
double? mobileSize, double? mobileSize,
double? scale, double? scale,
}) { }) {
scale ??= 2 / 3; scale ??= 2 / 3;
mobileSize ??= originalValue * scale; mobileSize ??= originalValue * scale;
final value = isMobile(context) ? mobileSize : originalValue; final value = isMobile ? mobileSize : originalValue;
return value.roundToDouble(); return value.roundToDouble();
} }