This commit is contained in:
M 2020-11-06 20:54:00 +02:00
parent 8a55d566c6
commit b17e7744c6
12 changed files with 273 additions and 197 deletions

View file

@ -212,13 +212,14 @@ String getPublicSpendKey() =>
convertUTF8ToString(pointer: getPublicSpendKeyNative()); convertUTF8ToString(pointer: getPublicSpendKeyNative());
class SyncListener { class SyncListener {
SyncListener({this.onNewBlock}) { SyncListener(this.onNewBlock, this.onNewTransaction) {
_cachedBlockchainHeight = 0; _cachedBlockchainHeight = 0;
_lastKnownBlockHeight = 0; _lastKnownBlockHeight = 0;
_initialSyncHeight = 0; _initialSyncHeight = 0;
} }
void Function(int, int, double) onNewBlock; void Function(int, int, double) onNewBlock;
void Function() onNewTransaction;
Timer _updateSyncInfoTimer; Timer _updateSyncInfoTimer;
int _cachedBlockchainHeight; int _cachedBlockchainHeight;
@ -239,6 +240,10 @@ class SyncListener {
_initialSyncHeight = 0; _initialSyncHeight = 0;
_updateSyncInfoTimer ??= _updateSyncInfoTimer ??=
Timer.periodic(Duration(milliseconds: 1200), (_) async { Timer.periodic(Duration(milliseconds: 1200), (_) async {
if (isNewTransactionExist() ?? false) {
onNewTransaction?.call();
}
var syncHeight = getSyncingHeight(); var syncHeight = getSyncingHeight();
if (syncHeight <= 0) { if (syncHeight <= 0) {
@ -273,8 +278,9 @@ class SyncListener {
void stop() => _updateSyncInfoTimer?.cancel(); void stop() => _updateSyncInfoTimer?.cancel();
} }
SyncListener setListeners(void Function(int, int, double) onNewBlock) { SyncListener setListeners(void Function(int, int, double) onNewBlock,
final listener = SyncListener(onNewBlock: onNewBlock); void Function() onNewTransaction) {
final listener = SyncListener(onNewBlock, onNewTransaction);
setListenerNative(); setListenerNative();
return listener; return listener;
} }

View file

@ -354,7 +354,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 17; CURRENT_PROJECT_VERSION = 2;
DEVELOPMENT_TEAM = 32J6BB6VUS; DEVELOPMENT_TEAM = 32J6BB6VUS;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
@ -371,7 +371,7 @@
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Flutter", "$(PROJECT_DIR)/Flutter",
); );
MARKETING_VERSION = 4.0.0; MARKETING_VERSION = 4.0.1;
PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet; PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet;
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";
@ -494,7 +494,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 17; CURRENT_PROJECT_VERSION = 2;
DEVELOPMENT_TEAM = 32J6BB6VUS; DEVELOPMENT_TEAM = 32J6BB6VUS;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
@ -511,7 +511,7 @@
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Flutter", "$(PROJECT_DIR)/Flutter",
); );
MARKETING_VERSION = 4.0.0; MARKETING_VERSION = 4.0.1;
PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet; PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet;
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";
@ -528,7 +528,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 17; CURRENT_PROJECT_VERSION = 2;
DEVELOPMENT_TEAM = 32J6BB6VUS; DEVELOPMENT_TEAM = 32J6BB6VUS;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
@ -545,7 +545,7 @@
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Flutter", "$(PROJECT_DIR)/Flutter",
); );
MARKETING_VERSION = 4.0.0; MARKETING_VERSION = 4.0.1;
PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet; PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet;
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";

View file

@ -1,4 +1,5 @@
mixin PendingTransaction { mixin PendingTransaction {
String get id;
String get amountFormatted; String get amountFormatted;
String get feeFormatted; String get feeFormatted;

View file

@ -1,8 +1,9 @@
import 'package:cake_wallet/bitcoin/bitcoin_wallet_service.dart'; import 'package:cake_wallet/bitcoin/bitcoin_wallet_service.dart';
import 'package:cake_wallet/core/wallet_service.dart'; import 'package:cake_wallet/core/wallet_service.dart';
import 'package:cake_wallet/entities/biometric_auth.dart'; import 'package:cake_wallet/entities/biometric_auth.dart';
import 'package:cake_wallet/entities/contact_record.dart'; import 'package:cake_wallet/entities/contact_record.dart';
import 'package:cake_wallet/entities/transaction_description.dart';
import 'package:cake_wallet/entities/transaction_info.dart';
import 'package:cake_wallet/monero/monero_wallet_service.dart'; import 'package:cake_wallet/monero/monero_wallet_service.dart';
import 'package:cake_wallet/entities/contact.dart'; import 'package:cake_wallet/entities/contact.dart';
import 'package:cake_wallet/entities/node.dart'; import 'package:cake_wallet/entities/node.dart';
@ -23,6 +24,7 @@ import 'package:cake_wallet/src/screens/send/send_template_page.dart';
import 'package:cake_wallet/src/screens/settings/change_language.dart'; import 'package:cake_wallet/src/screens/settings/change_language.dart';
import 'package:cake_wallet/src/screens/settings/settings.dart'; import 'package:cake_wallet/src/screens/settings/settings.dart';
import 'package:cake_wallet/src/screens/setup_pin_code/setup_pin_code.dart'; import 'package:cake_wallet/src/screens/setup_pin_code/setup_pin_code.dart';
import 'package:cake_wallet/src/screens/transaction_details/transaction_details_page.dart';
import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart'; import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart';
import 'package:cake_wallet/src/screens/exchange/exchange_page.dart'; import 'package:cake_wallet/src/screens/exchange/exchange_page.dart';
import 'package:cake_wallet/src/screens/exchange/exchange_template_page.dart'; import 'package:cake_wallet/src/screens/exchange/exchange_template_page.dart';
@ -92,7 +94,8 @@ Future setup(
Box<Contact> contactSource, Box<Contact> contactSource,
Box<Trade> tradesSource, Box<Trade> tradesSource,
Box<Template> templates, Box<Template> templates,
Box<ExchangeTemplate> exchangeTemplates}) async { Box<ExchangeTemplate> exchangeTemplates,
Box<TransactionDescription> transactionDescriptionBox}) async {
getIt.registerSingletonAsync<SharedPreferences>( getIt.registerSingletonAsync<SharedPreferences>(
() => SharedPreferences.getInstance()); () => SharedPreferences.getInstance());
@ -230,7 +233,8 @@ Future setup(
getIt.get<AppStore>().wallet, getIt.get<AppStore>().wallet,
getIt.get<AppStore>().settingsStore, getIt.get<AppStore>().settingsStore,
getIt.get<SendTemplateStore>(), getIt.get<SendTemplateStore>(),
getIt.get<FiatConversionStore>())); getIt.get<FiatConversionStore>(),
transactionDescriptionBox));
getIt.registerFactory( getIt.registerFactory(
() => SendPage(sendViewModel: getIt.get<SendViewModel>())); () => SendPage(sendViewModel: getIt.get<SendViewModel>()));
@ -387,4 +391,10 @@ Future setup(
getIt.registerFactoryParam<WalletRestorePage, WalletType, void>((type, _) => getIt.registerFactoryParam<WalletRestorePage, WalletType, void>((type, _) =>
WalletRestorePage(getIt.get<WalletRestoreViewModel>(param1: type))); WalletRestorePage(getIt.get<WalletRestoreViewModel>(param1: type)));
getIt.registerFactoryParam<TransactionDetailsPage, TransactionInfo, void>(
(TransactionInfo transactionInfo, _) => TransactionDetailsPage(
transactionInfo,
getIt.get<SettingsStore>().shouldSaveRecipientAddress,
transactionDescriptionBox));
} }

View file

@ -67,6 +67,7 @@ void main() async {
// fiatConvertationService: fiatConvertationService, // fiatConvertationService: fiatConvertationService,
templates: templates, templates: templates,
exchangeTemplates: exchangeTemplates, exchangeTemplates: exchangeTemplates,
transactionDescriptions: transactionDescriptions,
initialMigrationVersion: 4); initialMigrationVersion: 4);
runApp(App()); runApp(App());
} }
@ -80,6 +81,7 @@ Future<void> initialSetup(
// @required FiatConvertationService fiatConvertationService, // @required FiatConvertationService fiatConvertationService,
@required Box<Template> templates, @required Box<Template> templates,
@required Box<ExchangeTemplate> exchangeTemplates, @required Box<ExchangeTemplate> exchangeTemplates,
@required Box<TransactionDescription> transactionDescriptions,
int initialMigrationVersion = 5}) async { int initialMigrationVersion = 5}) async {
await defaultSettingsMigration( await defaultSettingsMigration(
version: initialMigrationVersion, version: initialMigrationVersion,
@ -94,7 +96,8 @@ Future<void> initialSetup(
contactSource: contactSource, contactSource: contactSource,
tradesSource: tradesSource, tradesSource: tradesSource,
templates: templates, templates: templates,
exchangeTemplates: exchangeTemplates); exchangeTemplates: exchangeTemplates,
transactionDescriptionBox: transactionDescriptions);
bootstrap(navigatorKey); bootstrap(navigatorKey);
monero_wallet.onStartup(); monero_wallet.onStartup();
} }

View file

@ -52,5 +52,6 @@ class MoneroTransactionInfo extends TransactionInfo {
@override @override
String fiatAmount() => _fiatAmount ?? ''; String fiatAmount() => _fiatAmount ?? '';
@override
void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount); void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount);
} }

View file

@ -237,7 +237,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
void _setListeners() { void _setListeners() {
_listener?.stop(); _listener?.stop();
_listener = monero_wallet.setListeners(_onNewBlock); _listener = monero_wallet.setListeners(_onNewBlock, _onNewTransaction);
} }
void _setInitialHeight() { void _setInitialHeight() {
@ -308,14 +308,23 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
} }
void _onNewBlock(int height, int blocksLeft, double ptc) async { void _onNewBlock(int height, int blocksLeft, double ptc) async {
_askForUpdateTransactionHistory(); if (walletInfo.isRecovery) {
_askForUpdateTransactionHistory();
}
_askForUpdateBalance(); _askForUpdateBalance();
if (blocksLeft < moneroBlockSize) { if (blocksLeft < 100) {
syncStatus = SyncedSyncStatus(); syncStatus = SyncedSyncStatus();
await _afterSyncSave(); await _afterSyncSave();
} else { } else {
syncStatus = SyncingSyncStatus(blocksLeft, ptc); syncStatus = SyncingSyncStatus(blocksLeft, ptc);
} }
} }
void _onNewTransaction() {
_askForUpdateTransactionHistory();
_askForUpdateBalance();
_afterSyncSave();
}
} }

View file

@ -10,6 +10,9 @@ class PendingMoneroTransaction with PendingTransaction {
final PendingTransactionDescription pendingTransactionDescription; final PendingTransactionDescription pendingTransactionDescription;
@override
String get id => pendingTransactionDescription.hash;
@override @override
String get amountFormatted => AmountConverter.amountIntToString( String get amountFormatted => AmountConverter.amountIntToString(
CryptoCurrency.xmr, pendingTransactionDescription.amount); CryptoCurrency.xmr, pendingTransactionDescription.amount);

View file

@ -1,6 +1,8 @@
import 'package:cake_wallet/entities/contact_record.dart'; import 'package:cake_wallet/entities/contact_record.dart';
import 'package:cake_wallet/entities/transaction_description.dart';
import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart'; import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/routes.dart';
@ -49,6 +51,7 @@ import 'package:cake_wallet/src/screens/send/send_template_page.dart';
import 'package:cake_wallet/src/screens/exchange/exchange_template_page.dart'; import 'package:cake_wallet/src/screens/exchange/exchange_template_page.dart';
import 'package:cake_wallet/src/screens/exchange_trade/exchange_confirm_page.dart'; import 'package:cake_wallet/src/screens/exchange_trade/exchange_confirm_page.dart';
import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_page.dart'; import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_page.dart';
import 'package:hive/hive.dart';
Route<dynamic> createRoute(RouteSettings settings) { Route<dynamic> createRoute(RouteSettings settings) {
switch (settings.name) { switch (settings.name) {
@ -57,15 +60,19 @@ Route<dynamic> createRoute(RouteSettings settings) {
case Routes.newWalletFromWelcome: case Routes.newWalletFromWelcome:
return CupertinoPageRoute<void>( return CupertinoPageRoute<void>(
builder: (_) => getIt.get<SetupPinCodePage>( builder: (_) => getIt.get<SetupPinCodePage>(param1:
param1: (PinCodeState<PinCodeWidget> context, dynamic _) async { (PinCodeState<PinCodeWidget> context, dynamic _) async {
try { try {
context.changeProcessText('Creating new wallet'); // FIXME: Unnamed constant context.changeProcessText(
final newWalletVM = getIt.get<WalletNewVM>(param1: WalletType.monero); 'Creating new wallet'); // FIXME: Unnamed constant
await newWalletVM.create(options: 'English'); // FIXME: Unnamed constant final newWalletVM =
getIt.get<WalletNewVM>(param1: WalletType.monero);
await newWalletVM.create(
options: 'English'); // FIXME: Unnamed constant
context.hideProgressText(); context.hideProgressText();
await Navigator.of(context.context).pushNamed(Routes.seed, arguments: true); await Navigator.of(context.context)
} catch(e) { .pushNamed(Routes.seed, arguments: true);
} catch (e) {
context.changeProcessText('Error: ${e.toString()}'); context.changeProcessText('Error: ${e.toString()}');
} }
}), }),
@ -88,7 +95,8 @@ Route<dynamic> createRoute(RouteSettings settings) {
Function(PinCodeState<PinCodeWidget>, String) callback; Function(PinCodeState<PinCodeWidget>, String) callback;
if (settings.arguments is Function(PinCodeState<PinCodeWidget>, String)) { if (settings.arguments is Function(PinCodeState<PinCodeWidget>, String)) {
callback = settings.arguments as Function(PinCodeState<PinCodeWidget>, String); callback =
settings.arguments as Function(PinCodeState<PinCodeWidget>, String);
} }
return CupertinoPageRoute<void>( return CupertinoPageRoute<void>(
@ -194,8 +202,8 @@ Route<dynamic> createRoute(RouteSettings settings) {
case Routes.transactionDetails: case Routes.transactionDetails:
return CupertinoPageRoute<void>( return CupertinoPageRoute<void>(
fullscreenDialog: true, fullscreenDialog: true,
builder: (_) => builder: (_) => getIt.get<TransactionDetailsPage>(
TransactionDetailsPage(settings.arguments as TransactionInfo)); param1: settings.arguments as TransactionInfo));
case Routes.newSubaddress: case Routes.newSubaddress:
return CupertinoPageRoute<void>( return CupertinoPageRoute<void>(
@ -320,4 +328,4 @@ Route<dynamic> createRoute(RouteSettings settings) {
body: Center( body: Center(
child: Text(S.current.router_no_route(settings.name))))); child: Text(S.current.router_no_route(settings.name)))));
} }
} }

View file

@ -70,10 +70,11 @@ class SendPage extends BasePage {
@override @override
Widget trailing(context) => TrailButton( Widget trailing(context) => TrailButton(
caption: S.of(context).clear, onPressed: () { caption: S.of(context).clear,
_formKey.currentState.reset(); onPressed: () {
sendViewModel.reset(); _formKey.currentState.reset();
}); sendViewModel.reset();
});
@override @override
Widget body(BuildContext context) { Widget body(BuildContext context) {
@ -166,72 +167,75 @@ class SendPage extends BasePage {
.decorationColor), .decorationColor),
validator: sendViewModel.addressValidator, validator: sendViewModel.addressValidator,
), ),
Observer(builder: (_) => Padding( Observer(
padding: const EdgeInsets.only(top: 20), builder: (_) => Padding(
child: BaseTextFormField( padding: const EdgeInsets.only(top: 20),
focusNode: _cryptoAmountFocus, child: BaseTextFormField(
controller: _cryptoAmountController, focusNode: _cryptoAmountFocus,
keyboardType: controller: _cryptoAmountController,
TextInputType.numberWithOptions( keyboardType:
signed: false, decimal: true), TextInputType.numberWithOptions(
prefixIcon: Padding( signed: false, decimal: true),
padding: EdgeInsets.only(top: 9), prefixIcon: Padding(
child: Text( padding: EdgeInsets.only(top: 9),
sendViewModel.currency.title + ':', child: Text(
style: TextStyle( sendViewModel.currency.title +
fontSize: 16, ':',
fontWeight: FontWeight.w600,
color: Colors.white,
)),
),
suffixIcon: Container(
height: 32,
width: 32,
margin: EdgeInsets.only(
left: 14, top: 4, bottom: 10),
decoration: BoxDecoration(
color: Theme.of(context)
.primaryTextTheme
.display1
.color,
borderRadius: BorderRadius.all(
Radius.circular(6))),
child: InkWell(
onTap: () =>
sendViewModel.setSendAll(),
child: Center(
child: Text(S.of(context).all,
textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontSize: 12, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.w600,
color: Theme.of(context) color: Colors.white,
.primaryTextTheme )),
.display1
.decorationColor)),
), ),
), suffixIcon: Container(
), height: 32,
hintText: '0.0000', width: 32,
borderColor: Theme.of(context) margin: EdgeInsets.only(
.primaryTextTheme left: 14, top: 4, bottom: 10),
.headline decoration: BoxDecoration(
.color, color: Theme.of(context)
textStyle: TextStyle( .primaryTextTheme
fontSize: 14, .display1
fontWeight: FontWeight.w500, .color,
color: Colors.white), borderRadius: BorderRadius.all(
placeholderTextStyle: TextStyle( Radius.circular(6))),
color: Theme.of(context) child: InkWell(
onTap: () =>
sendViewModel.setSendAll(),
child: Center(
child: Text(S.of(context).all,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
fontWeight:
FontWeight.bold,
color: Theme.of(context)
.primaryTextTheme
.display1
.decorationColor)),
),
),
),
hintText: '0.0000',
borderColor: Theme.of(context)
.primaryTextTheme .primaryTextTheme
.headline .headline
.decorationColor, .color,
fontWeight: FontWeight.w500, textStyle: TextStyle(
fontSize: 14), fontSize: 14,
validator: fontWeight: FontWeight.w500,
sendViewModel.sendAll color: Colors.white),
? sendViewModel.allAmountValidator placeholderTextStyle: TextStyle(
: sendViewModel.amountValidator))), color: Theme.of(context)
.primaryTextTheme
.headline
.decorationColor,
fontWeight: FontWeight.w500,
fontSize: 14),
validator: sendViewModel.sendAll
? sendViewModel.allAmountValidator
: sendViewModel
.amountValidator))),
Observer( Observer(
builder: (_) => Padding( builder: (_) => Padding(
padding: EdgeInsets.only(top: 10), padding: EdgeInsets.only(top: 10),
@ -423,53 +427,60 @@ class SendPage extends BasePage {
)), )),
), ),
), ),
Observer( Observer(builder: (_) {
builder: (_) { final templates = sendViewModel.templates;
final templates = sendViewModel.templates; final itemCount = templates.length;
final itemCount = templates.length;
return ListView.builder( return ListView.builder(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
shrinkWrap: true, shrinkWrap: true,
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
itemCount: itemCount, itemCount: itemCount,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final template = templates[index]; final template = templates[index];
return TemplateTile( return TemplateTile(
key: UniqueKey(), key: UniqueKey(),
to: template.name, to: template.name,
amount: template.amount, amount: template.amount,
from: template.cryptoCurrency, from: template.cryptoCurrency,
onTap: () { onTap: () {
_addressController.text = template.address; _addressController.text =
_cryptoAmountController.text = template.amount; template.address;
getOpenaliasRecord(context); _cryptoAmountController.text =
}, template.amount;
onRemove: () { getOpenaliasRecord(context);
showPopUp<void>( },
context: context, onRemove: () {
builder: (dialogContext) { showPopUp<void>(
return AlertWithTwoActions( context: context,
alertTitle: S.of(context).template, builder: (dialogContext) {
alertContent: S.of(context).confirm_delete_template, return AlertWithTwoActions(
rightButtonText: S.of(context).delete, alertTitle:
leftButtonText: S.of(context).cancel, S.of(context).template,
actionRightButton: () { alertContent: S
Navigator.of(dialogContext).pop(); .of(context)
sendViewModel.removeTemplate(template: template); .confirm_delete_template,
sendViewModel.updateTemplate(); rightButtonText:
}, S.of(context).delete,
actionLeftButton: () => Navigator.of(dialogContext).pop() leftButtonText:
); S.of(context).cancel,
} actionRightButton: () {
); Navigator.of(dialogContext)
}, .pop();
); sendViewModel.removeTemplate(
} template: template);
); sendViewModel
} .updateTemplate();
) },
actionLeftButton: () =>
Navigator.of(dialogContext)
.pop());
});
},
);
});
})
], ],
), ),
), ),
@ -486,13 +497,11 @@ class SendPage extends BasePage {
} }
}, },
text: S.of(context).send, text: S.of(context).send,
color: Theme color: Theme.of(context)
.of(context)
.accentTextTheme .accentTextTheme
.subtitle .subtitle
.decorationColor, .decorationColor,
textColor: Theme textColor: Theme.of(context)
.of(context)
.accentTextTheme .accentTextTheme
.headline .headline
.decorationColor, .decorationColor,
@ -606,6 +615,10 @@ class SendPage extends BasePage {
return Observer(builder: (_) { return Observer(builder: (_) {
final state = sendViewModel.state; final state = sendViewModel.state;
if (state is FailureState) {
Navigator.of(context).pop();
}
if (state is TransactionCommitted) { if (state is TransactionCommitted) {
return Stack( return Stack(
children: <Widget>[ children: <Widget>[
@ -652,45 +665,49 @@ class SendPage extends BasePage {
); );
} }
return Stack( if (state is TransactionCommitting) {
children: <Widget>[ return Stack(
Container( children: <Widget>[
color: Theme.of(context).backgroundColor, Container(
child: Center( color: Theme.of(context).backgroundColor,
child: Image.asset(
'assets/images/birthday_cake.png'),
),
),
BackdropFilter(
filter: ImageFilter.blur(
sigmaX: 3.0, sigmaY: 3.0),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context)
.backgroundColor
.withOpacity(0.25)),
child: Center( child: Center(
child: Padding( child: Image.asset(
padding: EdgeInsets.only(top: 220), 'assets/images/birthday_cake.png'),
child: Text( ),
S.of(context).send_sending, ),
textAlign: TextAlign.center, BackdropFilter(
style: TextStyle( filter: ImageFilter.blur(
fontSize: 22, sigmaX: 3.0, sigmaY: 3.0),
fontWeight: FontWeight.bold, child: Container(
color: Theme.of(context) decoration: BoxDecoration(
.primaryTextTheme color: Theme.of(context)
.title .backgroundColor
.color, .withOpacity(0.25)),
decoration: TextDecoration.none, child: Center(
child: Padding(
padding: EdgeInsets.only(top: 220),
child: Text(
S.of(context).send_sending,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: Theme.of(context)
.primaryTextTheme
.title
.color,
decoration: TextDecoration.none,
),
), ),
), ),
), ),
), ),
), )
) ],
], );
); }
return Container();
}); });
}); });
}, },

View file

@ -1,3 +1,4 @@
import 'package:cake_wallet/entities/transaction_description.dart';
import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_bar.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@ -9,9 +10,11 @@ import 'package:cake_wallet/src/widgets/standart_list_row.dart';
import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart'; import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart';
import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/utils/date_formatter.dart'; import 'package:cake_wallet/utils/date_formatter.dart';
import 'package:hive/hive.dart';
class TransactionDetailsPage extends BasePage { class TransactionDetailsPage extends BasePage {
TransactionDetailsPage(this.transactionInfo) : _items = [] { TransactionDetailsPage(this.transactionInfo, bool showRecipientAddress, Box<TransactionDescription> transactionDescriptionBox)
: _items = [] {
final dateFormat = DateFormatter.withCurrentLocal(); final dateFormat = DateFormatter.withCurrentLocal();
final tx = transactionInfo; final tx = transactionInfo;
@ -28,15 +31,18 @@ class TransactionDetailsPage extends BasePage {
title: S.current.transaction_details_amount, title: S.current.transaction_details_amount,
value: tx.amountFormatted()) value: tx.amountFormatted())
]; ];
// FIXME
// if (widget.settingsStore.shouldSaveRecipientAddress &&
// tx.recipientAddress != null) {
// items.add(StandartListItem(
// title: S.current.transaction_details_recipient_address,
// value: tx.recipientAddress));
// }
if (tx.key?.isNotEmpty) { if (showRecipientAddress) {
final recipientAddress = transactionDescriptionBox.values.firstWhere((val) => val.id == transactionInfo.id, orElse: () => null)?.recipientAddress;
if (recipientAddress?.isNotEmpty ?? false) {
items.add(StandartListItem(
title: S.current.transaction_details_recipient_address,
value: recipientAddress));
}
}
if (tx.key?.isNotEmpty ?? null) {
// FIXME: add translation // FIXME: add translation
items.add(StandartListItem(title: 'Transaction Key', value: tx.key)); items.add(StandartListItem(title: 'Transaction Key', value: tx.key));
} }

View file

@ -1,3 +1,5 @@
import 'package:cake_wallet/entities/transaction_description.dart';
import 'package:hive/hive.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:cake_wallet/entities/openalias_record.dart'; import 'package:cake_wallet/entities/openalias_record.dart';
@ -30,9 +32,8 @@ part 'send_view_model.g.dart';
class SendViewModel = SendViewModelBase with _$SendViewModel; class SendViewModel = SendViewModelBase with _$SendViewModel;
abstract class SendViewModelBase with Store { abstract class SendViewModelBase with Store {
SendViewModelBase( SendViewModelBase(this._wallet, this._settingsStore, this._sendTemplateStore,
this._wallet, this._settingsStore, this._sendTemplateStore, this._fiatConversationStore, this.transactionDescriptionBox)
this._fiatConversationStore)
: state = InitialExecutionState(), : state = InitialExecutionState(),
_cryptoNumberFormat = NumberFormat(), _cryptoNumberFormat = NumberFormat(),
sendAll = false { sendAll = false {
@ -101,6 +102,7 @@ abstract class SendViewModelBase with Store {
final SendTemplateStore _sendTemplateStore; final SendTemplateStore _sendTemplateStore;
final FiatConversionStore _fiatConversationStore; final FiatConversionStore _fiatConversationStore;
final NumberFormat _cryptoNumberFormat; final NumberFormat _cryptoNumberFormat;
final Box<TransactionDescription> transactionDescriptionBox;
@action @action
void setSendAll() => sendAll = true; void setSendAll() => sendAll = true;
@ -129,6 +131,13 @@ abstract class SendViewModelBase with Store {
try { try {
state = TransactionCommitting(); state = TransactionCommitting();
await pendingTransaction.commit(); await pendingTransaction.commit();
if (_settingsStore.shouldSaveRecipientAddress &&
(pendingTransaction.id?.isNotEmpty ?? false)) {
await transactionDescriptionBox.add(TransactionDescription(
id: pendingTransaction.id, recipientAddress: address));
}
state = TransactionCommitted(); state = TransactionCommitted();
} catch (e) { } catch (e) {
state = FailureState(e.toString()); state = FailureState(e.toString());
@ -156,8 +165,8 @@ abstract class SendViewModelBase with Store {
_settingsStore.transactionPriority = priority; _settingsStore.transactionPriority = priority;
Future<OpenaliasRecord> decodeOpenaliasRecord(String name) async { Future<OpenaliasRecord> decodeOpenaliasRecord(String name) async {
final record = await OpenaliasRecord final record = await OpenaliasRecord.fetchAddressAndName(
.fetchAddressAndName(OpenaliasRecord.formatDomainName(name)); OpenaliasRecord.formatDomainName(name));
return record.name != name ? record : null; return record.name != name ? record : null;
} }
@ -232,13 +241,16 @@ abstract class SendViewModelBase with Store {
void updateTemplate() => _sendTemplateStore.update(); void updateTemplate() => _sendTemplateStore.update();
void addTemplate({String name, String address, String cryptoCurrency, void addTemplate(
String amount}) => _sendTemplateStore {String name,
.addTemplate( String address,
name: name, String cryptoCurrency,
address: address, String amount}) =>
cryptoCurrency: cryptoCurrency, _sendTemplateStore.addTemplate(
amount: amount); name: name,
address: address,
cryptoCurrency: cryptoCurrency,
amount: amount);
void removeTemplate({Template template}) => void removeTemplate({Template template}) =>
_sendTemplateStore.remove(template: template); _sendTemplateStore.remove(template: template);