From d99aac9d98085d1c449c3ab1844755a3fac12c38 Mon Sep 17 00:00:00 2001 From: mkyq <53115730+mkyq@users.noreply.github.com> Date: Tue, 8 Nov 2022 15:57:33 -0500 Subject: [PATCH 1/3] Cast rateId as optional String for calculateAmount for ChangeNow api. (#612) --- lib/exchange/changenow/changenow_exchange_provider.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/exchange/changenow/changenow_exchange_provider.dart b/lib/exchange/changenow/changenow_exchange_provider.dart index b663b697c..20f529733 100644 --- a/lib/exchange/changenow/changenow_exchange_provider.dart +++ b/lib/exchange/changenow/changenow_exchange_provider.dart @@ -232,7 +232,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider { final responseJSON = json.decode(response.body) as Map; final fromAmount = double.parse(responseJSON['fromAmount'].toString()); final toAmount = double.parse(responseJSON['toAmount'].toString()); - final rateId = responseJSON['rateId'] as String ?? ''; + final rateId = responseJSON['rateId'] as String? ?? ''; if (rateId.isNotEmpty) { _lastUsedRateId = rateId; From 7d49dc47616559b8e94f72c54abd50a6eb9ea341 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 10 Nov 2022 20:08:52 +0200 Subject: [PATCH 2/3] rework confirm sending screen for cake pay (#603) * rework confirm sending allert * remove confirm_modal.dart * fix text color and buttons size --- lib/di.dart | 1 + .../cards/ionia_buy_card_detail_page.dart | 84 +++------- .../screens/ionia/widgets/confirm_modal.dart | 149 ------------------ .../send/widgets/confirm_sending_alert.dart | 86 +++++++++- lib/src/widgets/base_alert_dialog.dart | 98 +++++++----- .../ionia_purchase_merch_view_model.dart | 4 + 6 files changed, 169 insertions(+), 253 deletions(-) delete mode 100644 lib/src/screens/ionia/widgets/confirm_modal.dart diff --git a/lib/di.dart b/lib/di.dart index 7ce2ff6d9..90549cf6f 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -701,6 +701,7 @@ Future setup( ioniaAnyPayService: getIt.get(), amount: amount, ioniaMerchant: merchant, + sendViewModel: getIt.get() ); }); diff --git a/lib/src/screens/ionia/cards/ionia_buy_card_detail_page.dart b/lib/src/screens/ionia/cards/ionia_buy_card_detail_page.dart index f3b12e65b..4b9f0a220 100644 --- a/lib/src/screens/ionia/cards/ionia_buy_card_detail_page.dart +++ b/lib/src/screens/ionia/cards/ionia_buy_card_detail_page.dart @@ -3,7 +3,6 @@ import 'package:cake_wallet/ionia/ionia_merchant.dart'; import 'package:cake_wallet/ionia/ionia_tip.dart'; import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/src/screens/ionia/widgets/confirm_modal.dart'; import 'package:cake_wallet/src/screens/ionia/widgets/ionia_alert_model.dart'; import 'package:cake_wallet/src/screens/ionia/widgets/text_icon_button.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; @@ -18,6 +17,7 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart'; class IoniaBuyGiftCardDetailPage extends BasePage { IoniaBuyGiftCardDetailPage(this.ioniaPurchaseViewModel); @@ -295,73 +295,35 @@ class IoniaBuyGiftCardDetailPage extends BasePage { final amount = ioniaPurchaseViewModel.invoice!.totalAmount; final addresses = ioniaPurchaseViewModel.invoice!.outAddresses; + ioniaPurchaseViewModel.sendViewModel.outputs.first.setCryptoAmount(amount); + ioniaPurchaseViewModel.sendViewModel.outputs.first.address = addresses.first; await showPopUp( context: context, builder: (_) { - return IoniaConfirmModal( + return ConfirmSendingAlert( alertTitle: S.of(context).confirm_sending, - alertContent: Container( - height: 200, - padding: EdgeInsets.all(15), - child: Column(children: [ - Row(children: [ - Text(S.of(context).payment_id, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: PaletteDark.pigeonBlue, - decoration: TextDecoration.none)), - Text(ioniaPurchaseViewModel.invoice!.paymentId, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: PaletteDark.pigeonBlue, - decoration: TextDecoration.none)) - ], mainAxisAlignment: MainAxisAlignment.spaceBetween), - SizedBox(height: 10), - Row(children: [ - Text(S.of(context).amount, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: PaletteDark.pigeonBlue, - decoration: TextDecoration.none)), - Text('$amount ${ioniaPurchaseViewModel.invoice!.chain}', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: PaletteDark.pigeonBlue, - decoration: TextDecoration.none)) - ], mainAxisAlignment: MainAxisAlignment.spaceBetween), - SizedBox(height: 25), - Row(children: [ - Text(S.of(context).recipient_address, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: PaletteDark.pigeonBlue, - decoration: TextDecoration.none)) - ], mainAxisAlignment: MainAxisAlignment.center), - Expanded( - child: ListView.builder( - itemBuilder: (_, int index) { - return Text(addresses[index], - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w400, - color: PaletteDark.pigeonBlue, - decoration: TextDecoration.none)); - }, - itemCount: addresses.length, - physics: NeverScrollableScrollPhysics())) - ])), + paymentId: S.of(context).payment_id, + paymentIdValue: ioniaPurchaseViewModel.invoice!.paymentId, + amount: S.of(context).send_amount, + amountValue: '$amount ${ioniaPurchaseViewModel.invoice!.chain}', + fiatAmountValue: + '~ ${ioniaPurchaseViewModel.sendViewModel.outputs.first.fiatAmount} ' + '${ioniaPurchaseViewModel.sendViewModel.fiat.title}', + fee: S.of(context).send_fee, + feeValue: + '${ioniaPurchaseViewModel.sendViewModel.outputs.first.estimatedFee} ' + '${ioniaPurchaseViewModel.invoice!.chain}', + feeFiatAmount: + '${ioniaPurchaseViewModel.sendViewModel.outputs.first.estimatedFeeFiatAmount} ' + '${ioniaPurchaseViewModel.sendViewModel.fiat.title}', + outputs: ioniaPurchaseViewModel.sendViewModel.outputs, rightButtonText: S.of(context).ok, leftButtonText: S.of(context).cancel, - leftActionColor: Color(0xffFF6600), - rightActionColor: Theme.of(context).accentTextTheme!.bodyText1!.color!, + alertLeftActionButtonTextColor: Colors.white, + alertRightActionButtonTextColor: Colors.white, + alertLeftActionButtonColor: Palette.brightOrange, + alertRightActionButtonColor: Theme.of(context).textTheme!.subtitle2!.color, actionRightButton: () async { Navigator.of(context).pop(); await ioniaPurchaseViewModel.commitPaymentInvoice(); diff --git a/lib/src/screens/ionia/widgets/confirm_modal.dart b/lib/src/screens/ionia/widgets/confirm_modal.dart deleted file mode 100644 index cfc9a1cf1..000000000 --- a/lib/src/screens/ionia/widgets/confirm_modal.dart +++ /dev/null @@ -1,149 +0,0 @@ -import 'dart:ui'; - -import 'package:cake_wallet/palette.dart'; -import 'package:flutter/material.dart'; - -class IoniaConfirmModal extends StatelessWidget { - IoniaConfirmModal({ - required this.alertTitle, - required this.alertContent, - required this.leftButtonText, - required this.rightButtonText, - required this.actionLeftButton, - required this.actionRightButton, - required this.leftActionColor, - required this.rightActionColor, - this.hideActions = false, - }); - - final String alertTitle; - final Widget alertContent; - final String leftButtonText; - final String rightButtonText; - final VoidCallback actionLeftButton; - final VoidCallback actionRightButton; - final Color leftActionColor; - final Color rightActionColor; - final bool hideActions; - - Widget actionButtons(BuildContext context) { - return Row( - mainAxisSize: MainAxisSize.max, - children: [ - IoniaActionButton( - buttonText: leftButtonText, - action: actionLeftButton, - backgoundColor: leftActionColor, - ), - Container( - width: 1, - height: 52, - color: Theme.of(context).dividerColor, - ), - IoniaActionButton( - buttonText: rightButtonText, - action: actionRightButton, - backgoundColor: rightActionColor, - ), - ], - ); - } - - Widget title(BuildContext context) { - return Text( - alertTitle, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 20, - fontFamily: 'Lato', - fontWeight: FontWeight.w600, - color: Theme.of(context).primaryTextTheme!.headline6!.color!, - decoration: TextDecoration.none, - ), - ); - } - - @override - Widget build(BuildContext context) { - return Container( - color: Colors.transparent, - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 3.0, sigmaY: 3.0), - child: Container( - decoration: BoxDecoration(color: PaletteDark.darkNightBlue.withOpacity(0.75)), - child: Center( - child: GestureDetector( - onTap: () => null, - child: ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(30)), - child: Container( - width: 327, - color: Theme.of(context).accentTextTheme!.headline6!.decorationColor!, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: EdgeInsets.fromLTRB(24, 20, 24, 0), - child: title(context), - ), - Padding( - padding: EdgeInsets.only(top: 16, bottom: 8), - child: Container( - height: 1, - color: Theme.of(context).dividerColor, - ), - ), - alertContent, - actionButtons(context), - ], - ), - ), - ), - ), - ), - ), - ), - ); - } -} - -class IoniaActionButton extends StatelessWidget { - const IoniaActionButton({ - required this.buttonText, - required this.action, - required this.backgoundColor, - }); - - final String buttonText; - final VoidCallback action; - final Color backgoundColor; - - @override - Widget build(BuildContext context) { - return Flexible( - child: Container( - height: 52, - padding: EdgeInsets.only(left: 6, right: 6), - color: backgoundColor, - child: ButtonTheme( - minWidth: double.infinity, - child: TextButton( - onPressed: action, - // FIX-ME: ignored highlightColor and splashColor - //highlightColor: Colors.transparent, - //splashColor: Colors.transparent, - child: Text( - buttonText, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 15, - fontFamily: 'Lato', - fontWeight: FontWeight.w600, - color: backgoundColor != null ? Colors.white : Theme.of(context).primaryTextTheme!.bodyText2!.backgroundColor!, - decoration: TextDecoration.none, - ), - )), - ), - )); - } -} diff --git a/lib/src/screens/send/widgets/confirm_sending_alert.dart b/lib/src/screens/send/widgets/confirm_sending_alert.dart index 317303442..a034d801e 100644 --- a/lib/src/screens/send/widgets/confirm_sending_alert.dart +++ b/lib/src/screens/send/widgets/confirm_sending_alert.dart @@ -4,10 +4,13 @@ import 'package:flutter/material.dart'; import 'package:cake_wallet/src/widgets/base_alert_dialog.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/cake_scrollbar.dart'; +import 'package:flutter/scheduler.dart'; class ConfirmSendingAlert extends BaseAlertDialog { ConfirmSendingAlert({ required this.alertTitle, + this.paymentId, + this.paymentIdValue, required this.amount, required this.amountValue, required this.fiatAmountValue, @@ -19,9 +22,15 @@ class ConfirmSendingAlert extends BaseAlertDialog { required this.rightButtonText, required this.actionLeftButton, required this.actionRightButton, - this.alertBarrierDismissible = true}); + this.alertBarrierDismissible = true, + this.alertLeftActionButtonTextColor, + this.alertRightActionButtonTextColor, + this.alertLeftActionButtonColor, + this.alertRightActionButtonColor}); final String alertTitle; + final String? paymentId; + final String? paymentIdValue; final String amount; final String amountValue; final String fiatAmountValue; @@ -34,6 +43,10 @@ class ConfirmSendingAlert extends BaseAlertDialog { final VoidCallback actionLeftButton; final VoidCallback actionRightButton; final bool alertBarrierDismissible; + final Color? alertLeftActionButtonTextColor; + final Color? alertRightActionButtonTextColor; + final Color? alertLeftActionButtonColor; + final Color? alertRightActionButtonColor; @override String get titleText => alertTitle; @@ -56,8 +69,22 @@ class ConfirmSendingAlert extends BaseAlertDialog { @override bool get barrierDismissible => alertBarrierDismissible; + @override + Color? get leftActionButtonTextColor => alertLeftActionButtonTextColor; + + @override + Color? get rightActionButtonTextColor => alertRightActionButtonTextColor; + + @override + Color? get leftActionButtonColor => alertLeftActionButtonColor; + + @override + Color? get rightActionButtonColor => alertRightActionButtonColor; + @override Widget content(BuildContext context) => ConfirmSendingAlertContent( + paymentId: paymentId, + paymentIdValue: paymentIdValue, amount: amount, amountValue: amountValue, fiatAmountValue: fiatAmountValue, @@ -70,6 +97,8 @@ class ConfirmSendingAlert extends BaseAlertDialog { class ConfirmSendingAlertContent extends StatefulWidget { ConfirmSendingAlertContent({ + this.paymentId, + this.paymentIdValue, required this.amount, required this.amountValue, required this.fiatAmountValue, @@ -78,6 +107,8 @@ class ConfirmSendingAlertContent extends StatefulWidget { required this.feeFiatAmount, required this.outputs}); + final String? paymentId; + final String? paymentIdValue; final String amount; final String amountValue; final String fiatAmountValue; @@ -88,6 +119,8 @@ class ConfirmSendingAlertContent extends StatefulWidget { @override ConfirmSendingAlertContentState createState() => ConfirmSendingAlertContentState( + paymentId: paymentId, + paymentIdValue: paymentIdValue, amount: amount, amountValue: amountValue, fiatAmountValue: fiatAmountValue, @@ -100,6 +133,8 @@ class ConfirmSendingAlertContent extends StatefulWidget { class ConfirmSendingAlertContentState extends State { ConfirmSendingAlertContentState({ + this.paymentId, + this.paymentIdValue, required this.amount, required this.amountValue, required this.fiatAmountValue, @@ -115,6 +150,8 @@ class ConfirmSendingAlertContentState extends State : S.current.recipient_address; } + final String? paymentId; + final String? paymentIdValue; final String amount; final String amountValue; final String fiatAmountValue; @@ -129,6 +166,7 @@ class ConfirmSendingAlertContentState extends State double fromTop = 0; String recipientTitle; int itemCount; + bool showScrollbar = false; @override Widget build(BuildContext context) { @@ -140,6 +178,12 @@ class ConfirmSendingAlertContentState extends State setState(() {}); }); + SchedulerBinding.instance.addPostFrameCallback((_) { + setState(() { + showScrollbar = controller.position.maxScrollExtent > 0; + }); + }); + return Stack( alignment: Alignment.center, clipBehavior: Clip.none, @@ -150,6 +194,44 @@ class ConfirmSendingAlertContentState extends State controller: controller, child: Column( children: [ + if (paymentIdValue != null && paymentId != null) + Padding( + padding: EdgeInsets.only(bottom: 32), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + paymentId!, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.normal, + fontFamily: 'Lato', + color: Theme.of(context).primaryTextTheme! + .headline6!.color!, + decoration: TextDecoration.none, + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + paymentIdValue!, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + fontFamily: 'Lato', + color: Theme.of(context).primaryTextTheme! + .headline6!.color!, + decoration: TextDecoration.none, + ), + ), + ], + ) + ], + ), + ), Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -365,7 +447,7 @@ class ConfirmSendingAlertContentState extends State ) ) ), - if (itemCount > 1) CakeScrollbar( + if (showScrollbar) CakeScrollbar( backgroundHeight: backgroundHeight, thumbHeight: thumbHeight, fromTop: fromTop, diff --git a/lib/src/widgets/base_alert_dialog.dart b/lib/src/widgets/base_alert_dialog.dart index 7713284f2..70370e227 100644 --- a/lib/src/widgets/base_alert_dialog.dart +++ b/lib/src/widgets/base_alert_dialog.dart @@ -11,6 +11,10 @@ class BaseAlertDialog extends StatelessWidget { VoidCallback get actionLeft => () {}; VoidCallback get actionRight => () {}; bool get barrierDismissible => true; + Color? get leftActionButtonTextColor => null; + Color? get rightActionButtonTextColor => null; + Color? get leftActionButtonColor => null; + Color? get rightActionButtonColor => null; Widget title(BuildContext context) { return Text( @@ -45,52 +49,64 @@ class BaseAlertDialog extends StatelessWidget { height: 52, child: Row( mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Flexible( - child: Container( - width: double.infinity, - color: Theme.of(context).accentTextTheme!.bodyText1!.decorationColor!, - child: TextButton( - onPressed: actionLeft, - child: Text( - leftActionButtonText, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 15, - fontFamily: 'Lato', - fontWeight: FontWeight.w600, - color: Theme.of(context).primaryTextTheme!.bodyText1!.backgroundColor!, - decoration: TextDecoration.none, - ), - )), - ), - ), + Expanded( + child: TextButton( + onPressed: actionLeft, + style: TextButton.styleFrom( + backgroundColor: leftActionButtonColor ?? + Theme.of(context) + .accentTextTheme! + .bodyText1! + .decorationColor!, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.zero))), + child: Text( + leftActionButtonText, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 15, + fontFamily: 'Lato', + fontWeight: FontWeight.w600, + color: leftActionButtonTextColor ?? + Theme.of(context).primaryTextTheme! + .bodyText1!.backgroundColor!, + decoration: TextDecoration.none, + ), + )), + ), Container( width: 1, color: Theme.of(context).dividerColor, ), - Flexible( - child: Container( - width: double.infinity, - color: Theme.of(context).accentTextTheme!.bodyText2!.backgroundColor!, - child: TextButton( - onPressed: actionRight, - child: Text( - rightActionButtonText, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 15, - fontFamily: 'Lato', - fontWeight: FontWeight.w600, - color: Theme.of(context).primaryTextTheme!.bodyText2!.backgroundColor!, - decoration: TextDecoration.none, - ), - )), - ), - ), - ], - )); + Expanded( + child: TextButton( + onPressed: actionRight, + style: TextButton.styleFrom( + backgroundColor: rightActionButtonColor ?? + Theme.of(context).accentTextTheme! + .bodyText2!.backgroundColor!, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.zero))), + child: Text( + rightActionButtonText, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 15, + fontFamily: 'Lato', + fontWeight: FontWeight.w600, + color: rightActionButtonTextColor ?? + Theme.of(context) + .primaryTextTheme! + .bodyText2! + .backgroundColor!, + decoration: TextDecoration.none, + ), + )), + ), + ], + )); } @override diff --git a/lib/view_model/ionia/ionia_purchase_merch_view_model.dart b/lib/view_model/ionia/ionia_purchase_merch_view_model.dart index da71f31fa..df6a23718 100644 --- a/lib/view_model/ionia/ionia_purchase_merch_view_model.dart +++ b/lib/view_model/ionia/ionia_purchase_merch_view_model.dart @@ -7,6 +7,7 @@ import 'package:cake_wallet/ionia/ionia_anypay.dart'; import 'package:cake_wallet/ionia/ionia_merchant.dart'; import 'package:cake_wallet/ionia/ionia_tip.dart'; import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart'; +import 'package:cake_wallet/view_model/send/send_view_model.dart'; part 'ionia_purchase_merch_view_model.g.dart'; @@ -17,6 +18,7 @@ abstract class IoniaMerchPurchaseViewModelBase with Store { required this.ioniaAnyPayService, required this.amount, required this.ioniaMerchant, + required this.sendViewModel, }) : tipAmount = 0.0, percentage = 0.0, invoiceCreationState = InitialExecutionState(), @@ -40,6 +42,8 @@ abstract class IoniaMerchPurchaseViewModelBase with Store { final IoniaMerchant ioniaMerchant; + final SendViewModel sendViewModel; + final IoniaAnyPay ioniaAnyPayService; IoniaAnyPayPaymentInfo? paymentInfo; From 1efced7607dea0679971ec95877cfdd7847121a4 Mon Sep 17 00:00:00 2001 From: M Date: Thu, 10 Nov 2022 13:11:10 -0500 Subject: [PATCH 3/3] Update build version for cake wallet to 132; monero.com 28 --- scripts/android/app_env.sh | 4 ++-- scripts/ios/app_env.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index b9ca9f98b..54ad0b4d4 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,13 +15,13 @@ APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" MONERO_COM_VERSION="1.2.0" -MONERO_COM_BUILD_NUMBER=26 +MONERO_COM_BUILD_NUMBER=28 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_VERSION="4.5.0" -CAKEWALLET_BUILD_NUMBER=130 +CAKEWALLET_BUILD_NUMBER=132 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index bab932345..c7ecaa60b 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -14,12 +14,12 @@ APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" MONERO_COM_VERSION="1.2.0" -MONERO_COM_BUILD_NUMBER=26 +MONERO_COM_BUILD_NUMBER=28 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_VERSION="4.5.0" -CAKEWALLET_BUILD_NUMBER=130 +CAKEWALLET_BUILD_NUMBER=132 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven"