mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-20 06:08:34 +02:00
TMP 4
This commit is contained in:
@@ -1 +1,3 @@
|
||||
abstract class Balance {}
|
||||
abstract class Balance {
|
||||
const Balance();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
class MnemonicItem {
|
||||
MnemonicItem({String text}) : _text = text;
|
||||
|
||||
String get text => _text;
|
||||
String _text;
|
||||
|
||||
void changeText(String text) => _text = text;
|
||||
|
||||
@override
|
||||
String toString() => text;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
class MnemoticItem {
|
||||
MnemoticItem({String text, this.dic}) : _text = text;
|
||||
|
||||
String get text => _text;
|
||||
final List<String> dic;
|
||||
|
||||
String _text;
|
||||
|
||||
bool isCorrect() => dic.contains(text);
|
||||
|
||||
void changeText(String text) {
|
||||
_text = text;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => text;
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_wallet.manager.dart';
|
||||
import 'package:cake_wallet/bitcoin/key.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet_info.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
@@ -119,7 +118,7 @@ class WalletListService {
|
||||
MoneroWalletsManager(walletInfoSource: walletInfoSource);
|
||||
break;
|
||||
case WalletType.bitcoin:
|
||||
walletsManager = BitcoinWalletManager();
|
||||
// walletsManager = BitcoinWalletManager();
|
||||
break;
|
||||
case WalletType.none:
|
||||
walletsManager = null;
|
||||
|
||||
@@ -35,10 +35,10 @@ void setReactions(
|
||||
settingsStore: settingsStore,
|
||||
priceStore: priceStore);
|
||||
autorun((_) async {
|
||||
if (authenticationStore.state == AuthenticationState.allowed) {
|
||||
await loginStore.loadCurrentWallet();
|
||||
authenticationStore.state = AuthenticationState.readyToLogin;
|
||||
}
|
||||
// if (authenticationStore.state == AuthenticationState.allowed) {
|
||||
// await loginStore.loadCurrentWallet();
|
||||
// authenticationStore.state = AuthenticationState.readyToLogin;
|
||||
// }
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/stores/auth/auth_state.dart';
|
||||
import 'package:cake_wallet/src/stores/auth/auth_store.dart';
|
||||
import 'package:cake_wallet/view_model/auth_state.dart';
|
||||
import 'package:cake_wallet/view_model/auth_view_model.dart';
|
||||
import 'package:cake_wallet/src/screens/pin_code/pin_code.dart';
|
||||
import 'package:cake_wallet/src/stores/settings/settings_store.dart';
|
||||
import 'package:cake_wallet/src/domain/common/biometric_auth.dart';
|
||||
@@ -12,8 +11,12 @@ import 'package:cake_wallet/src/domain/common/biometric_auth.dart';
|
||||
typedef OnAuthenticationFinished = void Function(bool, AuthPageState);
|
||||
|
||||
class AuthPage extends StatefulWidget {
|
||||
AuthPage({this.onAuthenticationFinished, this.closable = true});
|
||||
AuthPage(
|
||||
{this.onAuthenticationFinished,
|
||||
this.authViewModel,
|
||||
this.closable = true});
|
||||
|
||||
final AuthViewModel authViewModel;
|
||||
final OnAuthenticationFinished onAuthenticationFinished;
|
||||
final bool closable;
|
||||
|
||||
@@ -25,40 +28,13 @@ class AuthPageState extends State<AuthPage> {
|
||||
final _key = GlobalKey<ScaffoldState>();
|
||||
final _pinCodeKey = GlobalKey<PinCodeState>();
|
||||
final _backArrowImageDarkTheme =
|
||||
Image.asset('assets/images/back_arrow_dark_theme.png');
|
||||
|
||||
void changeProcessText(String text) {
|
||||
_key.currentState.showSnackBar(
|
||||
SnackBar(content: Text(text), backgroundColor: Colors.green));
|
||||
}
|
||||
|
||||
void close() => Navigator.of(_key.currentContext).pop();
|
||||
Image.asset('assets/images/back_arrow_dark_theme.png');
|
||||
ReactionDisposer _reaction;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final authStore = Provider.of<AuthStore>(context);
|
||||
final settingsStore = Provider.of<SettingsStore>(context);
|
||||
|
||||
if (settingsStore.allowBiometricalAuthentication) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
final biometricAuth = BiometricAuth();
|
||||
biometricAuth.isAuthenticated().then(
|
||||
(isAuth) {
|
||||
if (isAuth) {
|
||||
authStore.biometricAuth();
|
||||
_key.currentState.showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(S.of(context).authenticated),
|
||||
backgroundColor: Colors.green,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
reaction((_) => authStore.state, (AuthState state) {
|
||||
void initState() {
|
||||
_reaction ??=
|
||||
reaction((_) => widget.authViewModel.state, (AuthState state) {
|
||||
if (state is AuthenticatedSuccessfully) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (widget.onAuthenticationFinished != null) {
|
||||
@@ -119,32 +95,69 @@ class AuthPageState extends State<AuthPage> {
|
||||
});
|
||||
}
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_reaction.reaction.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void changeProcessText(String text) => _key.currentState.showSnackBar(
|
||||
SnackBar(content: Text(text), backgroundColor: Colors.green));
|
||||
|
||||
void close() => Navigator.of(_key.currentContext).pop();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// final authStore = Provider.of<AuthStore>(context);
|
||||
// final settingsStore = Provider.of<SettingsStore>(context);
|
||||
|
||||
// if (settingsStore.allowBiometricalAuthentication) {
|
||||
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
// final biometricAuth = BiometricAuth();
|
||||
// biometricAuth.isAuthenticated().then(
|
||||
// (isAuth) {
|
||||
// if (isAuth) {
|
||||
// authStore.biometricAuth();
|
||||
// _key.currentState.showSnackBar(
|
||||
// SnackBar(
|
||||
// content: Text(S.of(context).authenticated),
|
||||
// backgroundColor: Colors.green,
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
// });
|
||||
// }
|
||||
|
||||
return Scaffold(
|
||||
key: _key,
|
||||
appBar: CupertinoNavigationBar(
|
||||
leading: widget.closable
|
||||
? SizedBox(
|
||||
height: 37,
|
||||
width: 20,
|
||||
child: ButtonTheme(
|
||||
minWidth: double.minPositive,
|
||||
child: FlatButton(
|
||||
highlightColor: Colors.transparent,
|
||||
splashColor: Colors.transparent,
|
||||
padding: EdgeInsets.all(0),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: _backArrowImageDarkTheme),
|
||||
),
|
||||
)
|
||||
: Container(),
|
||||
? SizedBox(
|
||||
height: 37,
|
||||
width: 20,
|
||||
child: ButtonTheme(
|
||||
minWidth: double.minPositive,
|
||||
child: FlatButton(
|
||||
highlightColor: Colors.transparent,
|
||||
splashColor: Colors.transparent,
|
||||
padding: EdgeInsets.all(0),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: _backArrowImageDarkTheme),
|
||||
),
|
||||
)
|
||||
: Container(),
|
||||
backgroundColor: Theme.of(context).backgroundColor,
|
||||
border: null,
|
||||
),
|
||||
resizeToAvoidBottomPadding: false,
|
||||
body: PinCode(
|
||||
(pin, _) => authStore.auth(
|
||||
password: pin.fold('', (ac, val) => ac + '$val')),
|
||||
(pin, _) => widget.authViewModel
|
||||
.auth(password: pin.fold('', (ac, val) => ac + '$val')),
|
||||
false,
|
||||
_pinCodeKey));
|
||||
}
|
||||
|
||||
@@ -14,15 +14,16 @@ Widget createLoginPage(
|
||||
@required WalletService walletService,
|
||||
@required WalletListService walletListService,
|
||||
@required AuthenticationStore authenticationStore}) =>
|
||||
Provider(
|
||||
create: (_) => AuthStore(
|
||||
sharedPreferences: sharedPreferences,
|
||||
userService: userService,
|
||||
walletService: walletService),
|
||||
child: AuthPage(
|
||||
onAuthenticationFinished: (isAuthenticated, state) {
|
||||
if (isAuthenticated) {
|
||||
authenticationStore.loggedIn();
|
||||
}
|
||||
},
|
||||
closable: false));
|
||||
null;
|
||||
// Provider(
|
||||
// create: (_) => AuthStore(
|
||||
// sharedPreferences: sharedPreferences,
|
||||
// userService: userService,
|
||||
// walletService: walletService),
|
||||
// child: AuthPage(
|
||||
// onAuthenticationFinished: (isAuthenticated, state) {
|
||||
// if (isAuthenticated) {
|
||||
// authenticationStore.loggedIn();
|
||||
// }
|
||||
// },
|
||||
// closable: false));
|
||||
|
||||
@@ -11,13 +11,14 @@ Widget createUnlockPage(
|
||||
@required UserService userService,
|
||||
@required WalletService walletService,
|
||||
@required Function(bool, AuthPageState) onAuthenticationFinished}) =>
|
||||
WillPopScope(
|
||||
onWillPop: () async => false,
|
||||
child: Provider(
|
||||
create: (_) => AuthStore(
|
||||
sharedPreferences: sharedPreferences,
|
||||
userService: userService,
|
||||
walletService: walletService),
|
||||
child: AuthPage(
|
||||
onAuthenticationFinished: onAuthenticationFinished,
|
||||
closable: false)));
|
||||
null;
|
||||
// WillPopScope(
|
||||
// onWillPop: () async => false,
|
||||
// child: Provider(
|
||||
// create: (_) => AuthStore(
|
||||
// sharedPreferences: sharedPreferences,
|
||||
// userService: userService,
|
||||
// walletService: walletService),
|
||||
// child: AuthPage(
|
||||
// onAuthenticationFinished: onAuthenticationFinished,
|
||||
// closable: false)));
|
||||
@@ -10,12 +10,19 @@ enum AppBarStyle { regular, withShadow }
|
||||
|
||||
abstract class BasePage extends StatelessWidget {
|
||||
String get title => null;
|
||||
|
||||
bool get isModalBackButton => false;
|
||||
|
||||
Color get backgroundLightColor => Colors.white;
|
||||
|
||||
Color get backgroundDarkColor => PaletteDark.darkNightBlue;
|
||||
|
||||
bool get resizeToAvoidBottomPadding => true;
|
||||
|
||||
AppBarStyle get appBarStyle => AppBarStyle.regular;
|
||||
|
||||
Widget Function(BuildContext, Widget) get rootWrapper => null;
|
||||
|
||||
final _backArrowImage = Image.asset('assets/images/back_arrow.png');
|
||||
final _backArrowImageDarkTheme =
|
||||
Image.asset('assets/images/back_arrow_dark_theme.png');
|
||||
@@ -83,9 +90,8 @@ abstract class BasePage extends StatelessWidget {
|
||||
leading: leading(context),
|
||||
middle: middle(context),
|
||||
trailing: trailing(context),
|
||||
backgroundColor: _isDarkTheme
|
||||
? backgroundDarkColor
|
||||
: backgroundLightColor);
|
||||
backgroundColor:
|
||||
_isDarkTheme ? backgroundDarkColor : backgroundLightColor);
|
||||
|
||||
case AppBarStyle.withShadow:
|
||||
return NavBar.withShadow(
|
||||
@@ -93,9 +99,8 @@ abstract class BasePage extends StatelessWidget {
|
||||
leading: leading(context),
|
||||
middle: middle(context),
|
||||
trailing: trailing(context),
|
||||
backgroundColor: _isDarkTheme
|
||||
? backgroundDarkColor
|
||||
: backgroundLightColor);
|
||||
backgroundColor:
|
||||
_isDarkTheme ? backgroundDarkColor : backgroundLightColor);
|
||||
|
||||
default:
|
||||
return NavBar(
|
||||
@@ -103,9 +108,8 @@ abstract class BasePage extends StatelessWidget {
|
||||
leading: leading(context),
|
||||
middle: middle(context),
|
||||
trailing: trailing(context),
|
||||
backgroundColor: _isDarkTheme
|
||||
? backgroundDarkColor
|
||||
: backgroundLightColor);
|
||||
backgroundColor:
|
||||
_isDarkTheme ? backgroundDarkColor : backgroundLightColor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,13 +120,14 @@ abstract class BasePage extends StatelessWidget {
|
||||
final _themeChanger = Provider.of<ThemeChanger>(context);
|
||||
final _isDarkTheme = _themeChanger.getTheme() == Themes.darkTheme;
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: _isDarkTheme
|
||||
? backgroundDarkColor
|
||||
: backgroundLightColor,
|
||||
final root = Scaffold(
|
||||
backgroundColor:
|
||||
_isDarkTheme ? backgroundDarkColor : backgroundLightColor,
|
||||
resizeToAvoidBottomPadding: resizeToAvoidBottomPadding,
|
||||
appBar: appBar(context),
|
||||
body: SafeArea(child: body(context)),
|
||||
floatingActionButton: floatingActionButton(context));
|
||||
|
||||
return rootWrapper?.call(context, root) ?? root;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,36 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard_view_model.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/wallet_card.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/trade_history_panel.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/menu_widget.dart';
|
||||
|
||||
class DashboardPage extends StatelessWidget {
|
||||
DashboardPage({@required this.walletViewModel});
|
||||
|
||||
final DashboardViewModel walletViewModel;
|
||||
final _bodyKey = GlobalKey();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => DashboardPageBody(key: _bodyKey);
|
||||
Widget build(BuildContext context) =>
|
||||
DashboardPageBody(key: _bodyKey, walletViewModel: walletViewModel);
|
||||
}
|
||||
|
||||
class DashboardPageBody extends StatefulWidget {
|
||||
DashboardPageBody({Key key}) : super(key: key);
|
||||
DashboardPageBody({Key key, @required this.walletViewModel})
|
||||
: super(key: key);
|
||||
|
||||
final DashboardViewModel walletViewModel;
|
||||
|
||||
@override
|
||||
DashboardPageBodyState createState() => DashboardPageBodyState();
|
||||
}
|
||||
|
||||
class DashboardPageBodyState extends State<DashboardPageBody> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final menuButton = Image.asset('assets/images/header.png',
|
||||
final menuButton = Image.asset(
|
||||
'assets/images/header.png',
|
||||
color: Theme.of(context).primaryTextTheme.title.color,
|
||||
);
|
||||
|
||||
@@ -30,15 +38,10 @@ class DashboardPageBodyState extends State<DashboardPageBody> {
|
||||
child: Scaffold(
|
||||
body: Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Theme.of(context).scaffoldBackgroundColor,
|
||||
Theme.of(context).primaryColor
|
||||
],
|
||||
begin: Alignment.centerLeft,
|
||||
end: Alignment.centerRight
|
||||
)
|
||||
),
|
||||
gradient: LinearGradient(colors: [
|
||||
Theme.of(context).scaffoldBackgroundColor,
|
||||
Theme.of(context).primaryColor
|
||||
], begin: Alignment.centerLeft, end: Alignment.centerRight)),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
@@ -55,22 +58,17 @@ class DashboardPageBodyState extends State<DashboardPageBody> {
|
||||
padding: EdgeInsets.all(0),
|
||||
onPressed: () async {
|
||||
await showDialog<void>(
|
||||
builder: (_) => MenuWidget(),
|
||||
context: context
|
||||
);
|
||||
builder: (_) => MenuWidget(), context: context);
|
||||
},
|
||||
child: menuButton),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 20, top: 20),
|
||||
child: WalletCard(),
|
||||
),
|
||||
SizedBox(
|
||||
height: 28,
|
||||
),
|
||||
Expanded(child: TradeHistoryPanel())
|
||||
padding: EdgeInsets.only(left: 20, top: 20),
|
||||
child: WalletCard(walletVM: widget.walletViewModel)),
|
||||
SizedBox(height: 28),
|
||||
Expanded(child: TradeHistoryPanel(dashboardViewModel: widget.walletViewModel))
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -17,7 +17,7 @@ class ButtonHeader extends SliverPersistentHeaderDelegate {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
|
||||
final actionListStore = Provider.of<ActionListStore>(context);
|
||||
// final actionListStore = Provider.of<ActionListStore>(context);
|
||||
final historyPanelWidth = MediaQuery.of(context).size.width;
|
||||
|
||||
final _themeChanger = Provider.of<ThemeChanger>(context);
|
||||
@@ -97,44 +97,44 @@ class ButtonHeader extends SliverPersistentHeaderDelegate {
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).primaryTextTheme.caption.color))),
|
||||
PopupMenuItem(
|
||||
value: 0,
|
||||
child: Observer(
|
||||
builder: (_) => Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.spaceBetween,
|
||||
children: [
|
||||
Text(S.of(context).incoming),
|
||||
Checkbox(
|
||||
value: actionListStore
|
||||
.transactionFilterStore
|
||||
.displayIncoming,
|
||||
onChanged: (value) =>
|
||||
actionListStore
|
||||
.transactionFilterStore
|
||||
.toggleIncoming(),
|
||||
)
|
||||
]))),
|
||||
PopupMenuItem(
|
||||
value: 1,
|
||||
child: Observer(
|
||||
builder: (_) => Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.spaceBetween,
|
||||
children: [
|
||||
Text(S.of(context).outgoing),
|
||||
Checkbox(
|
||||
value: actionListStore
|
||||
.transactionFilterStore
|
||||
.displayOutgoing,
|
||||
onChanged: (value) =>
|
||||
actionListStore
|
||||
.transactionFilterStore
|
||||
.toggleOutgoing(),
|
||||
)
|
||||
]))),
|
||||
// PopupMenuItem(
|
||||
// value: 0,
|
||||
// child: Observer(
|
||||
// builder: (_) => Row(
|
||||
// mainAxisAlignment:
|
||||
// MainAxisAlignment
|
||||
// .spaceBetween,
|
||||
// children: [
|
||||
// Text(S.of(context).incoming),
|
||||
// Checkbox(
|
||||
// value: actionListStore
|
||||
// .transactionFilterStore
|
||||
// .displayIncoming,
|
||||
// onChanged: (value) =>
|
||||
// actionListStore
|
||||
// .transactionFilterStore
|
||||
// .toggleIncoming(),
|
||||
// )
|
||||
// ]))),
|
||||
// PopupMenuItem(
|
||||
// value: 1,
|
||||
// child: Observer(
|
||||
// builder: (_) => Row(
|
||||
// mainAxisAlignment:
|
||||
// MainAxisAlignment
|
||||
// .spaceBetween,
|
||||
// children: [
|
||||
// Text(S.of(context).outgoing),
|
||||
// Checkbox(
|
||||
// value: actionListStore
|
||||
// .transactionFilterStore
|
||||
// .displayOutgoing,
|
||||
// onChanged: (value) =>
|
||||
// actionListStore
|
||||
// .transactionFilterStore
|
||||
// .toggleOutgoing(),
|
||||
// )
|
||||
// ]))),
|
||||
PopupMenuItem(
|
||||
value: 2,
|
||||
child:
|
||||
@@ -156,17 +156,17 @@ class ButtonHeader extends SliverPersistentHeaderDelegate {
|
||||
.spaceBetween,
|
||||
children: [
|
||||
Text('XMR.TO'),
|
||||
Checkbox(
|
||||
value: actionListStore
|
||||
.tradeFilterStore
|
||||
.displayXMRTO,
|
||||
onChanged: (value) =>
|
||||
actionListStore
|
||||
.tradeFilterStore
|
||||
.toggleDisplayExchange(
|
||||
ExchangeProviderDescription
|
||||
.xmrto),
|
||||
)
|
||||
// Checkbox(
|
||||
// value: actionListStore
|
||||
// .tradeFilterStore
|
||||
// .displayXMRTO,
|
||||
// onChanged: (value) =>
|
||||
// actionListStore
|
||||
// .tradeFilterStore
|
||||
// .toggleDisplayExchange(
|
||||
// ExchangeProviderDescription
|
||||
// .xmrto),
|
||||
// )
|
||||
]))),
|
||||
PopupMenuItem(
|
||||
value: 4,
|
||||
@@ -177,17 +177,17 @@ class ButtonHeader extends SliverPersistentHeaderDelegate {
|
||||
.spaceBetween,
|
||||
children: [
|
||||
Text('Change.NOW'),
|
||||
Checkbox(
|
||||
value: actionListStore
|
||||
.tradeFilterStore
|
||||
.displayChangeNow,
|
||||
onChanged: (value) =>
|
||||
actionListStore
|
||||
.tradeFilterStore
|
||||
.toggleDisplayExchange(
|
||||
ExchangeProviderDescription
|
||||
.changeNow),
|
||||
)
|
||||
// Checkbox(
|
||||
// value: actionListStore
|
||||
// .tradeFilterStore
|
||||
// .displayChangeNow,
|
||||
// onChanged: (value) =>
|
||||
// actionListStore
|
||||
// .tradeFilterStore
|
||||
// .toggleDisplayExchange(
|
||||
// ExchangeProviderDescription
|
||||
// .changeNow),
|
||||
// )
|
||||
]))),
|
||||
PopupMenuItem(
|
||||
value: 5,
|
||||
@@ -198,17 +198,17 @@ class ButtonHeader extends SliverPersistentHeaderDelegate {
|
||||
.spaceBetween,
|
||||
children: [
|
||||
Text('MorphToken'),
|
||||
Checkbox(
|
||||
value: actionListStore
|
||||
.tradeFilterStore
|
||||
.displayMorphToken,
|
||||
onChanged: (value) =>
|
||||
actionListStore
|
||||
.tradeFilterStore
|
||||
.toggleDisplayExchange(
|
||||
ExchangeProviderDescription
|
||||
.morphToken),
|
||||
)
|
||||
// Checkbox(
|
||||
// value: actionListStore
|
||||
// .tradeFilterStore
|
||||
// .displayMorphToken,
|
||||
// onChanged: (value) =>
|
||||
// actionListStore
|
||||
// .tradeFilterStore
|
||||
// .toggleDisplayExchange(
|
||||
// ExchangeProviderDescription
|
||||
// .morphToken),
|
||||
// )
|
||||
])))
|
||||
],
|
||||
child: filterButton,
|
||||
@@ -225,10 +225,10 @@ class ButtonHeader extends SliverPersistentHeaderDelegate {
|
||||
.add(Duration(days: 1)));
|
||||
|
||||
if (picked != null && picked.length == 2) {
|
||||
actionListStore.transactionFilterStore
|
||||
.changeStartDate(picked.first);
|
||||
actionListStore.transactionFilterStore
|
||||
.changeEndDate(picked.last);
|
||||
// actionListStore.transactionFilterStore
|
||||
// .changeStartDate(picked.first);
|
||||
// actionListStore.transactionFilterStore
|
||||
// .changeEndDate(picked.last);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,21 +1,26 @@
|
||||
import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
|
||||
import 'package:cake_wallet/src/stores/action_list/action_list_store.dart';
|
||||
import 'package:cake_wallet/src/stores/action_list/date_section_item.dart';
|
||||
import 'package:cake_wallet/src/stores/action_list/trade_list_item.dart';
|
||||
import 'package:cake_wallet/src/stores/action_list/transaction_list_item.dart';
|
||||
import 'package:cake_wallet/src/stores/settings/settings_store.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard_view_model.dart';
|
||||
import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
|
||||
import 'package:cake_wallet/src/stores/action_list/action_list_store.dart';
|
||||
import 'package:cake_wallet/src/stores/action_list/date_section_item.dart';
|
||||
import 'package:cake_wallet/src/stores/action_list/trade_list_item.dart';
|
||||
import 'package:cake_wallet/src/stores/action_list/transaction_list_item.dart';
|
||||
import 'package:cake_wallet/src/stores/settings/settings_store.dart';
|
||||
import 'date_section_raw.dart';
|
||||
import 'trade_row.dart';
|
||||
import 'transaction_raw.dart';
|
||||
import 'button_header.dart';
|
||||
|
||||
class TradeHistoryPanel extends StatefulWidget {
|
||||
TradeHistoryPanel({this.dashboardViewModel});
|
||||
|
||||
DashboardViewModel dashboardViewModel;
|
||||
|
||||
@override
|
||||
TradeHistoryPanelState createState() => TradeHistoryPanelState();
|
||||
}
|
||||
@@ -44,119 +49,127 @@ class TradeHistoryPanelState extends State<TradeHistoryPanel> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final actionListStore = Provider.of<ActionListStore>(context);
|
||||
final settingsStore = Provider.of<SettingsStore>(context);
|
||||
final transactionDateFormat = DateFormat("HH:mm");
|
||||
// final actionListStore = Provider.of<ActionListStore>(context);
|
||||
// final settingsStore = Provider.of<SettingsStore>(context);
|
||||
final transactionDateFormat = DateFormat('HH:mm');
|
||||
|
||||
return Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: AnimatedContainer(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: panelHeight,
|
||||
duration: Duration(milliseconds: 1000),
|
||||
curve: Curves.fastOutSlowIn,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20)),
|
||||
child: CustomScrollView(
|
||||
slivers: <Widget>[
|
||||
SliverPersistentHeader(
|
||||
delegate: ButtonHeader(),
|
||||
pinned: true,
|
||||
floating: false,
|
||||
),
|
||||
Observer(
|
||||
key: _listObserverKey,
|
||||
builder: (_) {
|
||||
final items = actionListStore.items == null
|
||||
? <String>[]
|
||||
: actionListStore.items;
|
||||
final itemsCount = items.length + 1;
|
||||
final symbol = settingsStore.fiatCurrency.toString();
|
||||
double freeSpaceHeight = MediaQuery.of(context).size.height - 496;
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: AnimatedContainer(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: panelHeight,
|
||||
duration: Duration(milliseconds: 1000),
|
||||
curve: Curves.fastOutSlowIn,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(20),
|
||||
topRight: Radius.circular(20)),
|
||||
child: CustomScrollView(
|
||||
slivers: <Widget>[
|
||||
SliverPersistentHeader(
|
||||
delegate: ButtonHeader(),
|
||||
pinned: true,
|
||||
floating: false,
|
||||
),
|
||||
Observer(
|
||||
key: _listObserverKey,
|
||||
builder: (_) {
|
||||
// final items = actionListStore.items == null
|
||||
// ? <String>[]
|
||||
// : actionListStore.items;
|
||||
final items = widget.dashboardViewModel.transactions;
|
||||
final itemsCount = items.length + 1;
|
||||
final symbol =
|
||||
'\$'; // settingsStore.fiatCurrency.toString();
|
||||
var freeSpaceHeight =
|
||||
MediaQuery.of(context).size.height - 496;
|
||||
|
||||
return SliverList(
|
||||
key: _listKey,
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) {
|
||||
return SliverList(
|
||||
key: _listKey,
|
||||
delegate:
|
||||
SliverChildBuilderDelegate((context, index) {
|
||||
if (index == itemsCount - 1) {
|
||||
freeSpaceHeight = freeSpaceHeight >= 0
|
||||
? freeSpaceHeight
|
||||
: 0;
|
||||
|
||||
if (index == itemsCount - 1) {
|
||||
freeSpaceHeight = freeSpaceHeight >= 0 ? freeSpaceHeight : 0;
|
||||
return Container(
|
||||
height: freeSpaceHeight,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
color: Theme.of(context).backgroundColor);
|
||||
}
|
||||
|
||||
final item = items[index];
|
||||
|
||||
if (item is DateSectionItem) {
|
||||
freeSpaceHeight -= 38;
|
||||
return DateSectionRaw(date: item.date);
|
||||
}
|
||||
|
||||
if (item is TransactionListItem) {
|
||||
freeSpaceHeight -= 62;
|
||||
final transaction = item.transaction;
|
||||
final savedDisplayMode =
|
||||
BalanceDisplayMode.all;
|
||||
//settingsStore
|
||||
// .balanceDisplayMode;
|
||||
final formattedAmount = savedDisplayMode ==
|
||||
BalanceDisplayMode.hiddenBalance
|
||||
? '---'
|
||||
: transaction.amountFormatted();
|
||||
final formattedFiatAmount =
|
||||
savedDisplayMode ==
|
||||
BalanceDisplayMode.hiddenBalance
|
||||
? '---'
|
||||
: transaction
|
||||
.fiatAmount(); // symbol ???
|
||||
|
||||
return TransactionRow(
|
||||
onTap: () => Navigator.of(context)
|
||||
.pushNamed(Routes.transactionDetails,
|
||||
arguments: transaction),
|
||||
direction: transaction.direction,
|
||||
formattedDate: transactionDateFormat
|
||||
.format(transaction.date),
|
||||
formattedAmount: formattedAmount,
|
||||
formattedFiatAmount: formattedFiatAmount,
|
||||
isPending: transaction.isPending);
|
||||
}
|
||||
|
||||
if (item is TradeListItem) {
|
||||
freeSpaceHeight -= 62;
|
||||
final trade = item.trade;
|
||||
final savedDisplayMode =
|
||||
BalanceDisplayMode.all;
|
||||
//settingsStore
|
||||
// .balanceDisplayMode;
|
||||
final formattedAmount = trade.amount != null
|
||||
? savedDisplayMode ==
|
||||
BalanceDisplayMode.hiddenBalance
|
||||
? '---'
|
||||
: trade.amountFormatted()
|
||||
: trade.amount;
|
||||
|
||||
return TradeRow(
|
||||
onTap: () => Navigator.of(context)
|
||||
.pushNamed(Routes.tradeDetails,
|
||||
arguments: trade),
|
||||
provider: trade.provider,
|
||||
from: trade.from,
|
||||
to: trade.to,
|
||||
createdAtFormattedDate:
|
||||
transactionDateFormat
|
||||
.format(trade.createdAt),
|
||||
formattedAmount: formattedAmount);
|
||||
}
|
||||
|
||||
return Container(
|
||||
height: freeSpaceHeight,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
color: Theme.of(context).backgroundColor,
|
||||
);
|
||||
}
|
||||
|
||||
final item = items[index];
|
||||
|
||||
if (item is DateSectionItem) {
|
||||
freeSpaceHeight -= 38;
|
||||
return DateSectionRaw(date: item.date);
|
||||
}
|
||||
|
||||
if (item is TransactionListItem) {
|
||||
freeSpaceHeight -= 62;
|
||||
final transaction = item.transaction;
|
||||
final savedDisplayMode = settingsStore.balanceDisplayMode;
|
||||
final formattedAmount =
|
||||
savedDisplayMode == BalanceDisplayMode.hiddenBalance
|
||||
? '---'
|
||||
: transaction.amountFormatted();
|
||||
final formattedFiatAmount =
|
||||
savedDisplayMode == BalanceDisplayMode.hiddenBalance
|
||||
? '---'
|
||||
: transaction.fiatAmount(); // symbol ???
|
||||
|
||||
return TransactionRow(
|
||||
onTap: () => Navigator.of(context).pushNamed(
|
||||
Routes.transactionDetails,
|
||||
arguments: transaction),
|
||||
direction: transaction.direction,
|
||||
formattedDate:
|
||||
transactionDateFormat.format(transaction.date),
|
||||
formattedAmount: formattedAmount,
|
||||
formattedFiatAmount: formattedFiatAmount,
|
||||
isPending: transaction.isPending);
|
||||
}
|
||||
|
||||
if (item is TradeListItem) {
|
||||
freeSpaceHeight -= 62;
|
||||
final trade = item.trade;
|
||||
final savedDisplayMode = settingsStore.balanceDisplayMode;
|
||||
final formattedAmount = trade.amount != null
|
||||
? savedDisplayMode == BalanceDisplayMode.hiddenBalance
|
||||
? '---'
|
||||
: trade.amountFormatted()
|
||||
: trade.amount;
|
||||
|
||||
return TradeRow(
|
||||
onTap: () => Navigator.of(context)
|
||||
.pushNamed(Routes.tradeDetails, arguments: trade),
|
||||
provider: trade.provider,
|
||||
from: trade.from,
|
||||
to: trade.to,
|
||||
createdAtFormattedDate:
|
||||
transactionDateFormat.format(trade.createdAt),
|
||||
formattedAmount: formattedAmount);
|
||||
}
|
||||
|
||||
return Container(
|
||||
color: Theme.of(context).backgroundColor
|
||||
);
|
||||
},
|
||||
|
||||
childCount: itemsCount
|
||||
)
|
||||
);
|
||||
})
|
||||
],
|
||||
),
|
||||
)
|
||||
),
|
||||
);
|
||||
color: Theme.of(context).backgroundColor);
|
||||
}, childCount: itemsCount));
|
||||
})
|
||||
],
|
||||
)))); //,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,27 @@
|
||||
import 'dart:async';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
|
||||
import 'package:cake_wallet/src/stores/balance/balance_store.dart';
|
||||
import 'package:cake_wallet/src/stores/settings/settings_store.dart';
|
||||
import 'package:cake_wallet/src/stores/sync/sync_store.dart';
|
||||
import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/domain/common/sync_status.dart';
|
||||
import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard_view_model.dart';
|
||||
|
||||
class WalletCard extends StatefulWidget {
|
||||
WalletCard({this.walletVM});
|
||||
|
||||
DashboardViewModel walletVM;
|
||||
|
||||
@override
|
||||
WalletCardState createState() => WalletCardState();
|
||||
}
|
||||
@@ -50,14 +56,12 @@ class WalletCardState extends State<WalletCard> {
|
||||
cardWidth = screenWidth;
|
||||
opacity = 1;
|
||||
});
|
||||
Timer(Duration(milliseconds: 500), () =>
|
||||
setState(() => isDraw = true)
|
||||
);
|
||||
Timer(Duration(milliseconds: 500), () => setState(() => isDraw = true));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final List<Color> colorsSync = [
|
||||
final colorsSync = [
|
||||
Theme.of(context).cardTheme.color,
|
||||
Theme.of(context).hoverColor
|
||||
];
|
||||
@@ -67,77 +71,67 @@ class WalletCardState extends State<WalletCard> {
|
||||
height: cardHeight,
|
||||
alignment: Alignment.centerRight,
|
||||
child: AnimatedContainer(
|
||||
alignment: Alignment.centerLeft,
|
||||
width: cardWidth,
|
||||
height: cardHeight,
|
||||
duration: Duration(milliseconds: 500),
|
||||
curve: Curves.fastOutSlowIn,
|
||||
padding: EdgeInsets.only(
|
||||
top: 1,
|
||||
left: 1,
|
||||
bottom: 1
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.only(topLeft: Radius.circular(10), bottomLeft: Radius.circular(10)),
|
||||
color: Theme.of(context).focusColor,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: PaletteDark.darkNightBlue.withOpacity(0.5),
|
||||
blurRadius: 8,
|
||||
offset: Offset(5, 5))
|
||||
]
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.only(topLeft: Radius.circular(10), bottomLeft: Radius.circular(10)),
|
||||
child: Container(
|
||||
width: cardWidth,
|
||||
height: cardHeight,
|
||||
color: Theme.of(context).cardColor,
|
||||
child: InkWell(
|
||||
onTap: () => setState(() => isFrontSide = !isFrontSide),
|
||||
child: isFrontSide
|
||||
? frontSide(colorsSync)
|
||||
: backSide(colorsSync)
|
||||
alignment: Alignment.centerLeft,
|
||||
width: cardWidth,
|
||||
height: cardHeight,
|
||||
duration: Duration(milliseconds: 500),
|
||||
curve: Curves.fastOutSlowIn,
|
||||
padding: EdgeInsets.only(top: 1, left: 1, bottom: 1),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(10),
|
||||
bottomLeft: Radius.circular(10)),
|
||||
color: Theme.of(context).focusColor,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: PaletteDark.darkNightBlue.withOpacity(0.5),
|
||||
blurRadius: 8,
|
||||
offset: Offset(5, 5))
|
||||
]),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(10), bottomLeft: Radius.circular(10)),
|
||||
child: Container(
|
||||
width: cardWidth,
|
||||
height: cardHeight,
|
||||
color: Theme.of(context).cardColor,
|
||||
child: InkWell(
|
||||
onTap: () => setState(() => isFrontSide = !isFrontSide),
|
||||
child: isFrontSide
|
||||
? frontSide(colorsSync)
|
||||
: backSide(colorsSync)),
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
Widget frontSide(List<Color> colorsSync) {
|
||||
final syncStore = Provider.of<SyncStore>(context);
|
||||
final walletStore = Provider.of<WalletStore>(context);
|
||||
// final syncStore = Provider.of<SyncStore>(context);
|
||||
// final walletStore = Provider.of<WalletStore>(context);
|
||||
final settingsStore = Provider.of<SettingsStore>(context);
|
||||
final balanceStore = Provider.of<BalanceStore>(context);
|
||||
final triangleButton = Image.asset('assets/images/triangle.png',
|
||||
// final balanceStore = Provider.of<BalanceStore>(context);
|
||||
final triangleButton = Image.asset(
|
||||
'assets/images/triangle.png',
|
||||
color: Theme.of(context).primaryTextTheme.title.color,
|
||||
);
|
||||
|
||||
return Observer(
|
||||
key: _syncingObserverKey,
|
||||
builder: (_) {
|
||||
final status = syncStore.status;
|
||||
final status = widget.walletVM.status;
|
||||
final statusText = status.title();
|
||||
final progress = syncStore.status.progress();
|
||||
final progress = status.progress();
|
||||
final indicatorWidth = progress * cardWidth;
|
||||
|
||||
String shortAddress = walletStore.subaddress.address;
|
||||
shortAddress = shortAddress.replaceRange(4, shortAddress.length - 4, '...');
|
||||
|
||||
final shortAddress = widget.walletVM.address
|
||||
.replaceRange(4, widget.walletVM.address.length - 4, '...');
|
||||
var descriptionText = '';
|
||||
|
||||
if (status is SyncingSyncStatus) {
|
||||
descriptionText = S
|
||||
.of(context)
|
||||
.Blocks_remaining(
|
||||
syncStore.status.toString());
|
||||
descriptionText = S.of(context).Blocks_remaining(status.toString());
|
||||
}
|
||||
|
||||
if (status is FailedSyncStatus) {
|
||||
descriptionText = S
|
||||
.of(context)
|
||||
.please_try_to_connect_to_another_node;
|
||||
descriptionText = S.of(context).please_try_to_connect_to_another_node;
|
||||
}
|
||||
|
||||
return Container(
|
||||
@@ -149,183 +143,206 @@ class WalletCardState extends State<WalletCard> {
|
||||
height: cardHeight,
|
||||
width: indicatorWidth,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.only(topLeft: Radius.circular(10), bottomLeft: Radius.circular(10)),
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(10),
|
||||
bottomLeft: Radius.circular(10)),
|
||||
gradient: LinearGradient(
|
||||
colors: colorsSync,
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter
|
||||
)
|
||||
),
|
||||
end: Alignment.bottomCenter)),
|
||||
),
|
||||
progress != 1
|
||||
? Positioned(
|
||||
left: indicatorWidth,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
width: 1,
|
||||
height: cardHeight,
|
||||
color: Theme.of(context).focusColor,
|
||||
)
|
||||
)
|
||||
: Offstage(),
|
||||
isDraw ? Positioned(
|
||||
left: 20,
|
||||
right: 20,
|
||||
top: 30,
|
||||
bottom: 30,
|
||||
child: Container(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
? Positioned(
|
||||
left: indicatorWidth,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
width: 1,
|
||||
height: cardHeight,
|
||||
color: Theme.of(context).focusColor,
|
||||
))
|
||||
: Offstage(),
|
||||
isDraw
|
||||
? Positioned(
|
||||
left: 20,
|
||||
right: 20,
|
||||
top: 30,
|
||||
bottom: 30,
|
||||
child: Container(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Column(
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
InkWell(
|
||||
onTap: () {},
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Text(
|
||||
walletStore.name,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).primaryTextTheme.title.color
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
InkWell(
|
||||
onTap: () {},
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Text(
|
||||
widget.walletVM.name,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.title
|
||||
.color),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
triangleButton
|
||||
],
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
triangleButton
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
if (widget.walletVM.subname?.isNotEmpty ?? false)
|
||||
Text(
|
||||
widget.walletVM.subname,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.caption
|
||||
.color),
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
walletStore.account.label,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).primaryTextTheme.caption.color
|
||||
Container(
|
||||
width: 98,
|
||||
height: 32,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.subtitle
|
||||
.backgroundColor,
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(16))),
|
||||
child: Text(
|
||||
shortAddress,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.caption
|
||||
.color),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
Container(
|
||||
width: 98,
|
||||
height: 32,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).accentTextTheme.subtitle.backgroundColor,
|
||||
borderRadius: BorderRadius.all(Radius.circular(16))
|
||||
),
|
||||
child: Text(
|
||||
shortAddress,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).primaryTextTheme.caption.color
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
status is SyncedSyncStatus
|
||||
? Observer(
|
||||
key: _balanceObserverKey,
|
||||
builder: (_) {
|
||||
final balanceDisplayMode = settingsStore.balanceDisplayMode;
|
||||
final symbol = settingsStore
|
||||
.fiatCurrency
|
||||
.toString();
|
||||
var balance = '---';
|
||||
var fiatBalance = '---';
|
||||
status is SyncedSyncStatus
|
||||
? Observer(
|
||||
key: _balanceObserverKey,
|
||||
builder: (_) {
|
||||
final balanceDisplayMode =
|
||||
BalanceDisplayMode.fullBalance;
|
||||
// settingsStore.balanceDisplayMode;
|
||||
final symbol =
|
||||
settingsStore.fiatCurrency.toString();
|
||||
var balance = '---';
|
||||
var fiatBalance = '---';
|
||||
|
||||
if (balanceDisplayMode ==
|
||||
BalanceDisplayMode.availableBalance) {
|
||||
balance =
|
||||
balanceStore.unlockedBalance ??
|
||||
'0.0';
|
||||
fiatBalance =
|
||||
'$symbol ${balanceStore.fiatUnlockedBalance}';
|
||||
}
|
||||
if (balanceDisplayMode ==
|
||||
BalanceDisplayMode.availableBalance) {
|
||||
balance = widget.walletVM.balance
|
||||
.unlockedBalance ??
|
||||
'0.0';
|
||||
fiatBalance = '\$ 123.43';
|
||||
// '$symbol ${balanceStore.fiatUnlockedBalance}';
|
||||
}
|
||||
|
||||
if (balanceDisplayMode ==
|
||||
BalanceDisplayMode.fullBalance) {
|
||||
balance =
|
||||
balanceStore.fullBalance ?? '0.0';
|
||||
fiatBalance =
|
||||
'$symbol ${balanceStore.fiatFullBalance}';
|
||||
}
|
||||
if (balanceDisplayMode ==
|
||||
BalanceDisplayMode.fullBalance) {
|
||||
balance = widget.walletVM.balance
|
||||
.totalBalance ??
|
||||
'0.0';
|
||||
fiatBalance = '\$ 123.43';
|
||||
// '$symbol ${balanceStore.fiatFullBalance}';
|
||||
}
|
||||
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
return Row(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.end,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
balanceDisplayMode.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.caption
|
||||
.color),
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
Text(
|
||||
balance,
|
||||
style: TextStyle(
|
||||
fontSize: 28,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.title
|
||||
.color),
|
||||
)
|
||||
],
|
||||
),
|
||||
Text(
|
||||
fiatBalance,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.title
|
||||
.color),
|
||||
)
|
||||
],
|
||||
);
|
||||
})
|
||||
: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
balanceDisplayMode.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).primaryTextTheme.caption.color
|
||||
),
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
Text(
|
||||
balance,
|
||||
style: TextStyle(
|
||||
fontSize: 28,
|
||||
color: Theme.of(context).primaryTextTheme.title.color
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
statusText,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.caption
|
||||
.color),
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
Text(
|
||||
descriptionText,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.title
|
||||
.color),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
Text(
|
||||
fiatBalance,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Theme.of(context).primaryTextTheme.title.color
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
)
|
||||
: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
statusText,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).primaryTextTheme.caption.color
|
||||
),
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
Text(
|
||||
descriptionText,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Theme.of(context).primaryTextTheme.title.color
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
)
|
||||
: Offstage()
|
||||
),
|
||||
))
|
||||
: Offstage()
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -334,149 +351,157 @@ class WalletCardState extends State<WalletCard> {
|
||||
}
|
||||
|
||||
Widget backSide(List<Color> colorsSync) {
|
||||
final walletStore = Provider.of<WalletStore>(context);
|
||||
final rightArrow = Image.asset('assets/images/right_arrow.png',
|
||||
final rightArrow = Image.asset(
|
||||
'assets/images/right_arrow.png',
|
||||
color: Theme.of(context).primaryTextTheme.title.color,
|
||||
);
|
||||
double messageBoxHeight = 0;
|
||||
double messageBoxWidth = cardWidth - 10;
|
||||
var messageBoxHeight = 0.0;
|
||||
var messageBoxWidth = cardWidth - 10;
|
||||
|
||||
return Observer(
|
||||
key: _addressObserverKey,
|
||||
builder: (_) {
|
||||
return Container(
|
||||
width: cardWidth,
|
||||
height: cardHeight,
|
||||
alignment: Alignment.topCenter,
|
||||
child: Stack(
|
||||
alignment: Alignment.topRight,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: cardWidth,
|
||||
height: cardHeight,
|
||||
padding: EdgeInsets.only(left: 20, right: 20, top: 30, bottom: 30),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.only(topLeft: Radius.circular(10), bottomLeft: Radius.circular(10)),
|
||||
gradient: LinearGradient(
|
||||
colors: colorsSync,
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter
|
||||
)
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
key: _addressObserverKey,
|
||||
builder: (_) {
|
||||
return Container(
|
||||
width: cardWidth,
|
||||
height: cardHeight,
|
||||
alignment: Alignment.topCenter,
|
||||
child: Stack(
|
||||
alignment: Alignment.topRight,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: cardWidth,
|
||||
height: cardHeight,
|
||||
padding:
|
||||
EdgeInsets.only(left: 20, right: 20, top: 30, bottom: 30),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(10),
|
||||
bottomLeft: Radius.circular(10)),
|
||||
gradient: LinearGradient(
|
||||
colors: colorsSync,
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter)),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
height: 90,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
S.current.card_address,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).primaryTextTheme.caption.color
|
||||
),
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.caption
|
||||
.color),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(
|
||||
text: walletStore.subaddress.address));
|
||||
_addressObserverKey.currentState.setState(() {
|
||||
text: widget.walletVM.address));
|
||||
_addressObserverKey.currentState
|
||||
.setState(() {
|
||||
messageBoxHeight = 20;
|
||||
messageBoxWidth = cardWidth;
|
||||
});
|
||||
Timer(Duration(milliseconds: 1000), () {
|
||||
try {
|
||||
_addressObserverKey.currentState.setState(() {
|
||||
_addressObserverKey.currentState
|
||||
.setState(() {
|
||||
messageBoxHeight = 0;
|
||||
messageBoxWidth = cardWidth - 10;
|
||||
});
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
print('${e.toString()}');
|
||||
}
|
||||
});
|
||||
},
|
||||
child: Text(
|
||||
walletStore.subaddress.address,
|
||||
widget.walletVM.address,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Theme.of(context).primaryTextTheme.title.color
|
||||
),
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.title
|
||||
.color),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
)),
|
||||
SizedBox(width: 10),
|
||||
Container(
|
||||
width: 90,
|
||||
height: 90,
|
||||
child: QrImage(
|
||||
data: widget.walletVM.address,
|
||||
backgroundColor: Colors.transparent,
|
||||
foregroundColor: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.caption
|
||||
.color),
|
||||
)
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
Container(
|
||||
width: 90,
|
||||
height: 90,
|
||||
child: QrImage(
|
||||
data: walletStore.subaddress.address,
|
||||
backgroundColor: Colors.transparent,
|
||||
foregroundColor: Theme.of(context).primaryTextTheme.caption.color
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
Container(
|
||||
height: 44,
|
||||
padding: EdgeInsets.only(left: 20, right: 20),
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(22)),
|
||||
color: Theme.of(context).primaryTextTheme.overline.color
|
||||
],
|
||||
),
|
||||
child: InkWell(
|
||||
onTap: () => Navigator.of(context,
|
||||
rootNavigator: true)
|
||||
.pushNamed(Routes.receive),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
S.of(context).accounts_subaddresses,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Theme.of(context).primaryTextTheme.title.color
|
||||
Container(
|
||||
height: 44,
|
||||
padding: EdgeInsets.only(left: 20, right: 20),
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(22)),
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.overline
|
||||
.color),
|
||||
child: InkWell(
|
||||
onTap: () =>
|
||||
Navigator.of(context, rootNavigator: true)
|
||||
.pushNamed(Routes.receive),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
S.of(context).accounts_subaddresses,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.title
|
||||
.color),
|
||||
),
|
||||
),
|
||||
rightArrow
|
||||
],
|
||||
rightArrow
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
AnimatedContainer(
|
||||
width: messageBoxWidth,
|
||||
height: messageBoxHeight,
|
||||
alignment: Alignment.center,
|
||||
duration: Duration(milliseconds: 500),
|
||||
curve: Curves.fastOutSlowIn,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.only(topLeft: Radius.circular(10)),
|
||||
color: Colors.green
|
||||
),
|
||||
child: Text(
|
||||
S.of(context).copied_to_clipboard,
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: Colors.white
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
);
|
||||
AnimatedContainer(
|
||||
width: messageBoxWidth,
|
||||
height: messageBoxHeight,
|
||||
alignment: Alignment.center,
|
||||
duration: Duration(milliseconds: 500),
|
||||
curve: Curves.fastOutSlowIn,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius:
|
||||
BorderRadius.only(topLeft: Radius.circular(10)),
|
||||
color: Colors.green),
|
||||
child: Text(
|
||||
S.of(context).copied_to_clipboard,
|
||||
style: TextStyle(fontSize: 10, color: Colors.white),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,85 +1,54 @@
|
||||
import 'package:cake_wallet/core/monero_wallet_list_service.dart';
|
||||
import 'package:cake_wallet/core/wallet_creation_service.dart';
|
||||
import 'package:cake_wallet/core/wallet_credentials.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/stores/wallet_creation/wallet_creation_store.dart';
|
||||
import 'package:cake_wallet/src/stores/wallet_creation/wallet_creation_state.dart';
|
||||
import 'package:cake_wallet/src/domain/services/wallet_list_service.dart';
|
||||
import 'package:cake_wallet/src/domain/services/wallet_service.dart';
|
||||
import 'package:cake_wallet/core/validator.dart';
|
||||
import 'package:cake_wallet/src/widgets/seed_language_selector.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||
import 'package:cake_wallet/src/stores/seed_language/seed_language_store.dart';
|
||||
import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
|
||||
import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_creation_state.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_new_vm.dart';
|
||||
|
||||
class NewWalletPage extends BasePage {
|
||||
NewWalletPage(
|
||||
{@required this.walletsService,
|
||||
@required this.walletService,
|
||||
@required this.sharedPreferences});
|
||||
NewWalletPage(this._walletNewVM);
|
||||
|
||||
final WalletListService walletsService;
|
||||
final WalletService walletService;
|
||||
final SharedPreferences sharedPreferences;
|
||||
final WalletNewVM _walletNewVM;
|
||||
|
||||
@override
|
||||
String get title => S.current.new_wallet;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) => WalletNameForm();
|
||||
Widget body(BuildContext context) => WalletNameForm(_walletNewVM);
|
||||
}
|
||||
|
||||
class WalletNameForm extends StatefulWidget {
|
||||
WalletNameForm(this._walletNewVM);
|
||||
|
||||
final WalletNewVM _walletNewVM;
|
||||
|
||||
@override
|
||||
_WalletNameFormState createState() => _WalletNameFormState();
|
||||
_WalletNameFormState createState() => _WalletNameFormState(_walletNewVM);
|
||||
}
|
||||
|
||||
class _WalletNameFormState extends State<WalletNameForm> {
|
||||
_WalletNameFormState(this._walletNewVM);
|
||||
|
||||
static const aspectRatioImage = 1.22;
|
||||
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final nameController = TextEditingController();
|
||||
final walletNameImage = Image.asset('assets/images/wallet_name.png');
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final _languageSelectorKey = GlobalKey<SeedLanguageSelectorState>();
|
||||
ReactionDisposer _stateReaction;
|
||||
final WalletNewVM _walletNewVM;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
nameController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final walletCreationStore = Provider.of<WalletCreationStore>(context);
|
||||
final walletCreationService = Provider.of<WalletCreationService>(context);
|
||||
|
||||
// FIXME: Does seed language store is really needed ???
|
||||
|
||||
final seedLanguageStore = Provider.of<SeedLanguageStore>(context);
|
||||
|
||||
final seedLocales = [
|
||||
S.current.seed_language_english,
|
||||
S.current.seed_language_chinese,
|
||||
S.current.seed_language_dutch,
|
||||
S.current.seed_language_german,
|
||||
S.current.seed_language_japanese,
|
||||
S.current.seed_language_portuguese,
|
||||
S.current.seed_language_russian,
|
||||
S.current.seed_language_spanish
|
||||
];
|
||||
|
||||
nameController.addListener(() =>
|
||||
walletCreationStore.setDisabledStatus(!nameController.text.isNotEmpty));
|
||||
|
||||
reaction((_) => walletCreationStore.state, (WalletCreationState state) {
|
||||
void initState() {
|
||||
_stateReaction ??=
|
||||
reaction((_) => _walletNewVM.state, (WalletCreationState state) {
|
||||
if (state is WalletCreatedSuccessfully) {
|
||||
Navigator.of(context).popUntil((route) => route.isFirst);
|
||||
}
|
||||
@@ -98,7 +67,11 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
||||
});
|
||||
}
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: ScrollableWithBottomSection(
|
||||
@@ -116,94 +89,76 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: TextFormField(
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 20.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).primaryTextTheme.title.color),
|
||||
controller: nameController,
|
||||
decoration: InputDecoration(
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 16.0,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.caption
|
||||
.color),
|
||||
hintText: S.of(context).wallet_name,
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1.0)),
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1.0))),
|
||||
validator: (value) {
|
||||
walletCreationStore.validateWalletName(value);
|
||||
return walletCreationStore.errorMessage;
|
||||
},
|
||||
)),
|
||||
onChanged: (value) => _walletNewVM.name = value,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 20.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
color:
|
||||
Theme.of(context).primaryTextTheme.title.color),
|
||||
decoration: InputDecoration(
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 16.0,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.caption
|
||||
.color),
|
||||
hintText: S.of(context).wallet_name,
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1.0)),
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1.0))),
|
||||
validator: WalletNameValidator())),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 40),
|
||||
child: Text(
|
||||
S.of(context).seed_language_choose,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).primaryTextTheme.title.color),
|
||||
if (_walletNewVM.hasLanguageSelector) ...[
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 40),
|
||||
child: Text(
|
||||
S.of(context).seed_language_choose,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).primaryTextTheme.title.color),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: Observer(
|
||||
builder: (_) => SelectButton(
|
||||
image: null,
|
||||
text: seedLocales[seedLanguages
|
||||
.indexOf(seedLanguageStore.selectedSeedLanguage)],
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.title
|
||||
.backgroundColor,
|
||||
textColor: Theme.of(context).primaryTextTheme.title.color,
|
||||
onTap: () async => await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) =>
|
||||
SeedLanguagePicker()))),
|
||||
)
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: SeedLanguageSelector(
|
||||
key: _languageSelectorKey,
|
||||
initialSelected: defaultSeedLanguage),
|
||||
)
|
||||
]
|
||||
]),
|
||||
bottomSectionPadding:
|
||||
EdgeInsets.only(left: 24, right: 24, bottom: 24),
|
||||
bottomSection: Observer(
|
||||
builder: (context) {
|
||||
return LoadingPrimaryButton(
|
||||
onPressed: () => _confirmForm(walletCreationService,
|
||||
seedLanguageStore.selectedSeedLanguage),
|
||||
onPressed: _confirmForm,
|
||||
text: S.of(context).continue_text,
|
||||
color: Colors.green,
|
||||
textColor: Colors.white,
|
||||
isLoading: walletCreationStore.state is WalletIsCreating,
|
||||
isDisabled: walletCreationStore.isDisabledStatus,
|
||||
isLoading: _walletNewVM.state is WalletCreatedSuccessfully,
|
||||
isDisabled: _walletNewVM.name.isEmpty,
|
||||
);
|
||||
},
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
void _confirmForm(
|
||||
WalletCreationService walletCreationService, String language) {
|
||||
void _confirmForm() {
|
||||
if (!_formKey.currentState.validate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
WalletCredentials credentials;
|
||||
|
||||
if (walletCreationService.type == WalletType.monero) {
|
||||
credentials = MoneroNewWalletCredentials(
|
||||
name: nameController.text, language: language);
|
||||
}
|
||||
|
||||
walletCreationService.create(credentials);
|
||||
_walletNewVM.create(
|
||||
options: _walletNewVM.hasLanguageSelector
|
||||
? _languageSelectorKey.currentState.selected
|
||||
: null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
@@ -8,14 +9,23 @@ import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
|
||||
class NewWalletTypePage extends BasePage {
|
||||
NewWalletTypePage({this.onTypeSelected});
|
||||
|
||||
final void Function(BuildContext, WalletType) onTypeSelected;
|
||||
|
||||
@override
|
||||
String get title => S.current.new_wallet;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) => WalletTypeForm();
|
||||
Widget body(BuildContext context) =>
|
||||
WalletTypeForm(onTypeSelected: onTypeSelected);
|
||||
}
|
||||
|
||||
class WalletTypeForm extends StatefulWidget {
|
||||
WalletTypeForm({this.onTypeSelected});
|
||||
|
||||
final void Function(BuildContext, WalletType) onTypeSelected;
|
||||
|
||||
@override
|
||||
WalletTypeFormState createState() => WalletTypeFormState();
|
||||
}
|
||||
@@ -23,35 +33,19 @@ class WalletTypeForm extends StatefulWidget {
|
||||
class WalletTypeFormState extends State<WalletTypeForm> {
|
||||
static const aspectRatioImage = 1.22;
|
||||
|
||||
final moneroIcon = Image.asset('assets/images/monero.png', height: 24, width: 24);
|
||||
final bitcoinIcon = Image.asset('assets/images/bitcoin.png', height: 24, width: 24);
|
||||
final moneroIcon =
|
||||
Image.asset('assets/images/monero.png', height: 24, width: 24);
|
||||
final bitcoinIcon =
|
||||
Image.asset('assets/images/bitcoin.png', height: 24, width: 24);
|
||||
final walletTypeImage = Image.asset('assets/images/wallet_type.png');
|
||||
|
||||
bool isDisabledButton;
|
||||
bool isMoneroSelected;
|
||||
bool isBitcoinSelected;
|
||||
|
||||
Color moneroBackgroundColor = Colors.transparent;
|
||||
Color moneroTextColor = Colors.transparent;
|
||||
Color bitcoinBackgroundColor = Colors.transparent;
|
||||
Color bitcoinTextColor = Colors.transparent;
|
||||
WalletType selected;
|
||||
List<WalletType> types;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
isDisabledButton = true;
|
||||
isMoneroSelected = false;
|
||||
isBitcoinSelected = false;
|
||||
|
||||
types = [WalletType.bitcoin, WalletType.monero];
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback(afterLayout);
|
||||
}
|
||||
|
||||
void afterLayout(dynamic _) {
|
||||
moneroBackgroundColor = Theme.of(context).accentTextTheme.title.backgroundColor;
|
||||
moneroTextColor = Theme.of(context).primaryTextTheme.title.color;
|
||||
bitcoinBackgroundColor = Theme.of(context).accentTextTheme.title.backgroundColor;
|
||||
bitcoinTextColor = Theme.of(context).primaryTextTheme.title.color;
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -75,71 +69,52 @@ class WalletTypeFormState extends State<WalletTypeForm> {
|
||||
S.of(context).choose_wallet_currency,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).primaryTextTheme.title.color
|
||||
),
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).primaryTextTheme.title.color),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: SelectButton(
|
||||
image: bitcoinIcon,
|
||||
text: 'Bitcoin',
|
||||
color: bitcoinBackgroundColor,
|
||||
textColor: bitcoinTextColor,
|
||||
onTap: () {}),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 20),
|
||||
child: SelectButton(
|
||||
image: moneroIcon,
|
||||
text: 'Monero',
|
||||
color: moneroBackgroundColor,
|
||||
textColor: moneroTextColor,
|
||||
onTap: () => onSelectMoneroButton(context)),
|
||||
)
|
||||
...types.map((type) => Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: SelectButton(
|
||||
image: _iconFor(type),
|
||||
text: walletTypeToString(type),
|
||||
color: _backgroundColorFor(selected == type),
|
||||
textColor: _textColorFor(selected == type),
|
||||
onTap: () => setState(() => selected = type)),
|
||||
))
|
||||
],
|
||||
),
|
||||
bottomSectionPadding: EdgeInsets.only(
|
||||
left: 24,
|
||||
right: 24,
|
||||
bottom: 24
|
||||
),
|
||||
bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
|
||||
bottomSection: PrimaryButton(
|
||||
onPressed: () => Navigator.of(context).pushNamed(Routes.newWallet),
|
||||
onPressed: () => widget.onTypeSelected(context, selected),
|
||||
text: S.of(context).seed_language_next,
|
||||
color: Colors.green,
|
||||
textColor: Colors.white,
|
||||
isDisabled: isDisabledButton,
|
||||
isDisabled: selected == null,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void onSelectMoneroButton(BuildContext context) {
|
||||
isMoneroSelected = true;
|
||||
isBitcoinSelected = false;
|
||||
isDisabledButton = false;
|
||||
// FIXME: Move color selection inside ui element; add isSelected to buttons.
|
||||
|
||||
moneroBackgroundColor = Theme.of(context).accentTextTheme.title.decorationColor;
|
||||
moneroTextColor = Theme.of(context).primaryTextTheme.title.backgroundColor;
|
||||
bitcoinBackgroundColor = Theme.of(context).accentTextTheme.title.backgroundColor;
|
||||
bitcoinTextColor = Theme.of(context).primaryTextTheme.title.color;
|
||||
Color _backgroundColorFor(bool isSelected) => isSelected
|
||||
? Theme.of(context).accentTextTheme.title.decorationColor
|
||||
: Theme.of(context).accentTextTheme.title.backgroundColor;
|
||||
|
||||
setState(() {});
|
||||
Color _textColorFor(bool isSelected) => isSelected
|
||||
? Theme.of(context).primaryTextTheme.title.backgroundColor
|
||||
: Theme.of(context).primaryTextTheme.title.color;
|
||||
|
||||
Image _iconFor(WalletType type) {
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
return moneroIcon;
|
||||
case WalletType.bitcoin:
|
||||
return bitcoinIcon;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void onSelectBitcoinButton(BuildContext context) {
|
||||
isMoneroSelected = false;
|
||||
isBitcoinSelected = true;
|
||||
isDisabledButton = false;
|
||||
|
||||
moneroBackgroundColor = Theme.of(context).accentTextTheme.title.backgroundColor;
|
||||
moneroTextColor = Theme.of(context).primaryTextTheme.title.color;
|
||||
bitcoinBackgroundColor = moneroBackgroundColor = Theme.of(context).accentTextTheme.title.decorationColor;
|
||||
bitcoinTextColor = Theme.of(context).primaryTextTheme.title.backgroundColor;
|
||||
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@@ -16,347 +18,256 @@ import 'package:cake_wallet/src/screens/receive/widgets/header_tile.dart';
|
||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||
import 'package:cake_wallet/themes.dart';
|
||||
import 'package:cake_wallet/theme_changer.dart';
|
||||
import 'package:cake_wallet/core/amount_validator.dart';
|
||||
import 'package:cake_wallet/src/screens/receive/widgets/address_cell.dart';
|
||||
import 'package:cake_wallet/view_model/address_list/account_list_header.dart';
|
||||
import 'package:cake_wallet/view_model/address_list/address_list_header.dart';
|
||||
import 'package:cake_wallet/view_model/address_list/address_list_item.dart';
|
||||
import 'package:cake_wallet/view_model/address_list/address_list_view_model.dart';
|
||||
|
||||
class ReceivePage extends StatefulWidget {
|
||||
@override
|
||||
ReceivePageState createState() => ReceivePageState();
|
||||
}
|
||||
class ReceivePage extends BasePage {
|
||||
ReceivePage({this.addressListViewModel})
|
||||
: amountController = TextEditingController(),
|
||||
_formKey = GlobalKey<FormState>() {
|
||||
amountController.addListener(() => addressListViewModel.amount =
|
||||
_formKey.currentState.validate() ? amountController.text : '');
|
||||
}
|
||||
|
||||
class ReceivePageState extends State<ReceivePage> {
|
||||
final amountController = TextEditingController();
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final _backArrowImage = Image.asset('assets/images/back_arrow.png');
|
||||
final _backArrowImageDarkTheme =
|
||||
Image.asset('assets/images/back_arrow_dark_theme.png');
|
||||
final AddressListViewModel addressListViewModel;
|
||||
final TextEditingController amountController;
|
||||
final GlobalKey<FormState> _formKey;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
amountController.dispose();
|
||||
super.dispose();
|
||||
Color get backgroundLightColor => Colors.transparent;
|
||||
|
||||
@override
|
||||
Color get backgroundDarkColor => Colors.transparent;
|
||||
|
||||
@override
|
||||
Widget Function(BuildContext, Widget) get rootWrapper =>
|
||||
(BuildContext context, Widget scaffold) => Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(colors: [
|
||||
Theme.of(context).scaffoldBackgroundColor,
|
||||
Theme.of(context).primaryColor
|
||||
], begin: Alignment.topLeft, end: Alignment.bottomRight)),
|
||||
child: scaffold);
|
||||
|
||||
@override
|
||||
Widget middle(BuildContext context) => Text(
|
||||
S.of(context).receive,
|
||||
style: TextStyle(
|
||||
fontSize: 18.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).primaryTextTheme.title.color),
|
||||
);
|
||||
|
||||
@override
|
||||
Widget trailing(BuildContext context) {
|
||||
final shareImage = Image.asset('assets/images/share.png',
|
||||
color: Theme.of(context).primaryTextTheme.title.color);
|
||||
|
||||
return SizedBox(
|
||||
height: 20.0,
|
||||
width: 14.0,
|
||||
child: ButtonTheme(
|
||||
minWidth: double.minPositive,
|
||||
child: FlatButton(
|
||||
highlightColor: Colors.transparent,
|
||||
splashColor: Colors.transparent,
|
||||
padding: EdgeInsets.all(0),
|
||||
onPressed: () => Share.text(S.current.share_address,
|
||||
addressListViewModel.address.address, 'text/plain'),
|
||||
child: shareImage),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final walletStore = Provider.of<WalletStore>(context);
|
||||
final subaddressListStore = Provider.of<SubaddressListStore>(context);
|
||||
final accountListStore = Provider.of<AccountListStore>(context);
|
||||
return super.build(context);
|
||||
}
|
||||
|
||||
final shareImage = Image.asset('assets/images/share.png',
|
||||
color: Theme.of(context).primaryTextTheme.title.color,
|
||||
);
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
final copyImage = Image.asset('assets/images/copy_content.png',
|
||||
color: Theme.of(context).primaryTextTheme.title.color,
|
||||
);
|
||||
color: Theme.of(context).primaryTextTheme.title.color);
|
||||
|
||||
final currentColor = Theme.of(context).accentTextTheme.subtitle.decorationColor;
|
||||
final notCurrentColor = Theme.of(context).backgroundColor;
|
||||
|
||||
final currentTextColor = Colors.blue;
|
||||
final notCurrentTextColor = Theme.of(context).primaryTextTheme.caption.color;
|
||||
|
||||
final _themeChanger = Provider.of<ThemeChanger>(context);
|
||||
Image _backButton;
|
||||
|
||||
if (_themeChanger.getTheme() == Themes.darkTheme) {
|
||||
_backButton = _backArrowImageDarkTheme;
|
||||
} else {
|
||||
_backButton = _backArrowImage;
|
||||
}
|
||||
|
||||
amountController.addListener(() {
|
||||
if (_formKey.currentState.validate()) {
|
||||
walletStore.onChangedAmountValue(amountController.text);
|
||||
} else {
|
||||
walletStore.onChangedAmountValue('');
|
||||
}
|
||||
});
|
||||
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomPadding: false,
|
||||
body: Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Theme.of(context).scaffoldBackgroundColor,
|
||||
Theme.of(context).primaryColor
|
||||
],
|
||||
begin: Alignment.centerLeft,
|
||||
end: Alignment.centerRight
|
||||
)
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
SizedBox(height: 25),
|
||||
Row(children: <Widget>[
|
||||
Spacer(flex: 4),
|
||||
Observer(
|
||||
builder: (_) => Flexible(
|
||||
flex: 6,
|
||||
child: Center(
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1.0,
|
||||
child: QrImage(
|
||||
data: addressListViewModel.uri.toString(),
|
||||
backgroundColor: Colors.transparent,
|
||||
foregroundColor: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.display4
|
||||
.color,
|
||||
))))),
|
||||
Spacer(flex: 4)
|
||||
]),
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(24, 40, 24, 0),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: BaseTextFormField(
|
||||
controller: amountController,
|
||||
keyboardType:
|
||||
TextInputType.numberWithOptions(decimal: true),
|
||||
inputFormatters: [
|
||||
BlacklistingTextInputFormatter(
|
||||
RegExp('[\\-|\\ |\\,]'))
|
||||
],
|
||||
textAlign: TextAlign.center,
|
||||
hintText: S.of(context).receive_amount,
|
||||
borderColor: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.headline5
|
||||
.color
|
||||
.withOpacity(0.4),
|
||||
validator: AmountValidator(),
|
||||
autovalidate: true,
|
||||
placeholderTextStyle: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.headline5
|
||||
.color,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600))))
|
||||
],
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: EdgeInsets.only(
|
||||
top: 10,
|
||||
bottom: 20,
|
||||
left: 5,
|
||||
right: 10
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
SizedBox(
|
||||
height: 44,
|
||||
width: 44,
|
||||
child: ButtonTheme(
|
||||
minWidth: double.minPositive,
|
||||
child: FlatButton(
|
||||
highlightColor: Colors.transparent,
|
||||
splashColor: Colors.transparent,
|
||||
padding: EdgeInsets.all(0),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: _backButton),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
S.of(context).receive,
|
||||
style: TextStyle(
|
||||
fontSize: 18.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).primaryTextTheme.title.color),
|
||||
),
|
||||
SizedBox(
|
||||
height: 44.0,
|
||||
width: 44.0,
|
||||
child: ButtonTheme(
|
||||
minWidth: double.minPositive,
|
||||
child: FlatButton(
|
||||
highlightColor: Colors.transparent,
|
||||
splashColor: Colors.transparent,
|
||||
padding: EdgeInsets.all(0),
|
||||
onPressed: () => Share.text(
|
||||
S.current.share_address, walletStore.subaddress.address, 'text/plain'),
|
||||
child: shareImage),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Observer(builder: (_) {
|
||||
return Row(
|
||||
children: <Widget>[
|
||||
Spacer(
|
||||
flex: 1,
|
||||
),
|
||||
Flexible(
|
||||
flex: 2,
|
||||
child: Center(
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1.0,
|
||||
child: QrImage(
|
||||
data: walletStore.subaddress.address +
|
||||
walletStore.amountValue,
|
||||
backgroundColor: Colors.transparent,
|
||||
foregroundColor: Theme.of(context).primaryTextTheme.display4.color,
|
||||
),
|
||||
),
|
||||
)),
|
||||
Spacer(
|
||||
flex: 1,
|
||||
)
|
||||
],
|
||||
);
|
||||
}),
|
||||
Padding(
|
||||
padding: EdgeInsets.all(24),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: BaseTextFormField(
|
||||
controller: amountController,
|
||||
keyboardType: TextInputType.numberWithOptions(decimal: true),
|
||||
inputFormatters: [
|
||||
BlacklistingTextInputFormatter(
|
||||
RegExp('[\\-|\\ |\\,]'))
|
||||
],
|
||||
textAlign: TextAlign.center,
|
||||
hintText: S.of(context).receive_amount,
|
||||
borderColor: Theme.of(context).primaryTextTheme.caption.color,
|
||||
validator: (value) {
|
||||
walletStore.validateAmount(value);
|
||||
return walletStore.errorMessage;
|
||||
},
|
||||
autovalidate: true,
|
||||
)
|
||||
)
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
|
||||
child: Builder(
|
||||
builder: (context) => Observer(
|
||||
builder: (context) => GestureDetector(
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(
|
||||
text: walletStore.subaddress.address));
|
||||
Scaffold.of(context).showSnackBar(SnackBar(
|
||||
content: Text(
|
||||
S.of(context).copied_to_clipboard,
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
backgroundColor: Colors.green,
|
||||
duration: Duration(milliseconds: 500),
|
||||
));
|
||||
},
|
||||
child: Container(
|
||||
height: 48,
|
||||
padding: EdgeInsets.only(left: 24, right: 24),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(24)),
|
||||
color: Theme.of(context).primaryTextTheme.overline.color
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Text(
|
||||
walletStore.subaddress.address,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).primaryTextTheme.title.color
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 12),
|
||||
child: copyImage,
|
||||
)
|
||||
],
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 24, right: 24, bottom: 40, top: 40),
|
||||
child: Builder(
|
||||
builder: (context) => Observer(
|
||||
builder: (context) => GestureDetector(
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(
|
||||
text: addressListViewModel.address.address));
|
||||
Scaffold.of(context).showSnackBar(SnackBar(
|
||||
content: Text(
|
||||
S.of(context).copied_to_clipboard,
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
backgroundColor: Colors.green,
|
||||
duration: Duration(milliseconds: 500),
|
||||
));
|
||||
},
|
||||
child: Container(
|
||||
height: 48,
|
||||
padding: EdgeInsets.only(left: 24, right: 24),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(24)),
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.overline
|
||||
.color),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Text(
|
||||
addressListViewModel.address.address,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.title
|
||||
.color),
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
Observer(
|
||||
builder: (_) => ListView.separated(
|
||||
separatorBuilder: (context, index) => Divider(
|
||||
height: 1,
|
||||
color: Theme.of(context).dividerColor,
|
||||
),
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
itemCount: subaddressListStore.subaddresses.length + 2,
|
||||
itemBuilder: (context, index) {
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 12),
|
||||
child: copyImage,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
))),
|
||||
),
|
||||
Observer(
|
||||
builder: (_) => ListView.separated(
|
||||
separatorBuilder: (context, _) =>
|
||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
itemCount: addressListViewModel.items.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = addressListViewModel.items[index];
|
||||
Widget cell = Container();
|
||||
|
||||
if (index == 0) {
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(24),
|
||||
topRight: Radius.circular(24)
|
||||
),
|
||||
child: HeaderTile(
|
||||
onTap: () async {
|
||||
await showDialog<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AccountListPage(accountListStore: accountListStore);
|
||||
}
|
||||
);
|
||||
},
|
||||
title: walletStore.account.label,
|
||||
icon: Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
size: 14,
|
||||
color: Theme.of(context).primaryTextTheme.title.color,
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
if (item is AccountListHeader) {
|
||||
cell = HeaderTile(
|
||||
onTap: () async {
|
||||
await showDialog<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
// return AccountListPage(
|
||||
// accountListStore:
|
||||
// accountListStore);
|
||||
});
|
||||
},
|
||||
title: addressListViewModel.accountLabel,
|
||||
icon: Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
size: 14,
|
||||
color:
|
||||
Theme.of(context).primaryTextTheme.title.color,
|
||||
));
|
||||
}
|
||||
|
||||
if (index == 1) {
|
||||
return HeaderTile(
|
||||
onTap: () => Navigator.of(context)
|
||||
.pushNamed(Routes.newSubaddress),
|
||||
title: S.of(context).subaddresses,
|
||||
icon: Icon(
|
||||
Icons.add,
|
||||
size: 20,
|
||||
color: Theme.of(context).primaryTextTheme.title.color,
|
||||
)
|
||||
);
|
||||
}
|
||||
if (item is AddressListHeader) {
|
||||
cell = HeaderTile(
|
||||
onTap: () => Navigator.of(context)
|
||||
.pushNamed(Routes.newSubaddress),
|
||||
title: S.of(context).subaddresses,
|
||||
icon: Icon(
|
||||
Icons.add,
|
||||
size: 20,
|
||||
color:
|
||||
Theme.of(context).primaryTextTheme.title.color,
|
||||
));
|
||||
}
|
||||
|
||||
index -= 2;
|
||||
if (item is AddressListItem) {
|
||||
cell = Observer(
|
||||
builder: (_) => AddressCell.fromItem(item,
|
||||
isCurrent: item.address ==
|
||||
addressListViewModel.address.address,
|
||||
onTap: (_) =>
|
||||
addressListViewModel.address = item,
|
||||
onEdit: () => Navigator.of(context)
|
||||
.pushNamed(Routes.newSubaddress, arguments: item)));
|
||||
}
|
||||
|
||||
return Observer(
|
||||
builder: (_) {
|
||||
final subaddress = subaddressListStore.subaddresses[index];
|
||||
final isCurrent =
|
||||
walletStore.subaddress.address == subaddress.address;
|
||||
|
||||
final label = subaddress.label.isNotEmpty
|
||||
? subaddress.label
|
||||
: subaddress.address;
|
||||
|
||||
final content = InkWell(
|
||||
onTap: () => walletStore.setSubaddress(subaddress),
|
||||
child: Container(
|
||||
color: isCurrent ? currentColor : notCurrentColor,
|
||||
padding: EdgeInsets.only(
|
||||
left: 24,
|
||||
right: 24,
|
||||
top: 28,
|
||||
bottom: 28
|
||||
),
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: subaddress.label.isNotEmpty
|
||||
? 18 : 10,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: isCurrent
|
||||
? currentTextColor
|
||||
: notCurrentTextColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return isCurrent
|
||||
? content
|
||||
: Slidable(
|
||||
key: Key(subaddress.address),
|
||||
actionPane: SlidableDrawerActionPane(),
|
||||
child: content,
|
||||
secondaryActions: <Widget>[
|
||||
IconSlideAction(
|
||||
caption: S.of(context).edit,
|
||||
color: Theme.of(context).primaryTextTheme.overline.color,
|
||||
icon: Icons.edit,
|
||||
onTap: () => Navigator.of(context)
|
||||
.pushNamed(Routes.newSubaddress, arguments: subaddress),
|
||||
)
|
||||
]
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
)
|
||||
],
|
||||
)
|
||||
return index != 0
|
||||
? cell
|
||||
: ClipRRect(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(24),
|
||||
topRight: Radius.circular(24)),
|
||||
child: cell,
|
||||
);
|
||||
})),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_slidable/flutter_slidable.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/view_model/address_list/address_list_item.dart';
|
||||
|
||||
class AddressCell extends StatelessWidget {
|
||||
factory AddressCell.fromItem(AddressListItem item,
|
||||
{@required bool isCurrent,
|
||||
Function(String) onTap,
|
||||
Function() onEdit}) =>
|
||||
AddressCell(
|
||||
address: item.address,
|
||||
name: item.name,
|
||||
isCurrent: isCurrent,
|
||||
onTap: onTap,
|
||||
onEdit: onEdit);
|
||||
|
||||
AddressCell(
|
||||
{@required this.address,
|
||||
@required this.name,
|
||||
@required this.isCurrent,
|
||||
this.onTap,
|
||||
this.onEdit});
|
||||
|
||||
final String address;
|
||||
final String name;
|
||||
final bool isCurrent;
|
||||
final Function(String) onTap;
|
||||
final Function() onEdit;
|
||||
|
||||
String get label => name ?? address;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const currentTextColor = Colors.blue; // FIXME: Why it's defined here ?
|
||||
final currentColor =
|
||||
Theme.of(context).accentTextTheme.subtitle.decorationColor;
|
||||
final notCurrentColor = Theme.of(context).backgroundColor;
|
||||
final notCurrentTextColor =
|
||||
Theme.of(context).primaryTextTheme.caption.color;
|
||||
final Widget cell = InkWell(
|
||||
onTap: () => onTap(address),
|
||||
child: Container(
|
||||
color: isCurrent ? currentColor : notCurrentColor,
|
||||
padding: EdgeInsets.only(left: 24, right: 24, top: 28, bottom: 28),
|
||||
child: Text(
|
||||
name ?? address,
|
||||
style: TextStyle(
|
||||
fontSize: name?.isNotEmpty ?? false ? 18 : 10,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: isCurrent ? currentTextColor : notCurrentTextColor,
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
return isCurrent
|
||||
? cell
|
||||
: Slidable(
|
||||
key: Key(address),
|
||||
actionPane: SlidableDrawerActionPane(),
|
||||
child: cell,
|
||||
secondaryActions: <Widget>[
|
||||
IconSlideAction(
|
||||
caption: S.of(context).edit,
|
||||
color: Theme.of(context).primaryTextTheme.overline.color,
|
||||
icon: Icons.edit,
|
||||
onTap: () => onEdit?.call())
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,35 @@
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/stores/wallet_restoration/wallet_restoration_store.dart';
|
||||
import 'package:cake_wallet/src/stores/wallet_restoration/wallet_restoration_state.dart';
|
||||
import 'package:cake_wallet/core/validator.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_creation_state.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart';
|
||||
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_restoration_from_seed_vm.dart';
|
||||
|
||||
class RestoreWalletFromSeedDetailsPage extends BasePage {
|
||||
RestoreWalletFromSeedDetailsPage(
|
||||
{@required this.walletRestorationFromSeedVM});
|
||||
|
||||
final WalletRestorationFromSeedVM walletRestorationFromSeedVM;
|
||||
|
||||
@override
|
||||
String get title => S.current.restore_wallet_restore_description;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) => RestoreFromSeedDetailsForm();
|
||||
Widget body(BuildContext context) => RestoreFromSeedDetailsForm(
|
||||
walletRestorationFromSeedVM: walletRestorationFromSeedVM);
|
||||
}
|
||||
|
||||
class RestoreFromSeedDetailsForm extends StatefulWidget {
|
||||
RestoreFromSeedDetailsForm({@required this.walletRestorationFromSeedVM});
|
||||
|
||||
final WalletRestorationFromSeedVM walletRestorationFromSeedVM;
|
||||
|
||||
@override
|
||||
_RestoreFromSeedDetailsFormState createState() =>
|
||||
_RestoreFromSeedDetailsFormState();
|
||||
@@ -31,31 +40,17 @@ class _RestoreFromSeedDetailsFormState
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final _blockchainHeightKey = GlobalKey<BlockchainHeightState>();
|
||||
final _nameController = TextEditingController();
|
||||
ReactionDisposer _stateReaction;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_nameController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final walletRestorationStore = Provider.of<WalletRestorationStore>(context);
|
||||
|
||||
_nameController.addListener(() {
|
||||
if (_nameController.text.isNotEmpty) {
|
||||
walletRestorationStore.setDisabledState(false);
|
||||
} else {
|
||||
walletRestorationStore.setDisabledState(true);
|
||||
}
|
||||
});
|
||||
|
||||
reaction((_) => walletRestorationStore.state, (WalletRestorationState state) {
|
||||
if (state is WalletRestoredSuccessfully) {
|
||||
void initState() {
|
||||
_stateReaction = reaction((_) => widget.walletRestorationFromSeedVM.state,
|
||||
(WalletCreationState state) {
|
||||
if (state is WalletCreatedSuccessfully) {
|
||||
Navigator.of(context).popUntil((route) => route.isFirst);
|
||||
}
|
||||
|
||||
if (state is WalletRestorationFailure) {
|
||||
if (state is WalletCreationFailure) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
@@ -64,73 +59,87 @@ class _RestoreFromSeedDetailsFormState
|
||||
alertTitle: S.current.restore_title_from_seed,
|
||||
alertContent: state.error,
|
||||
buttonText: S.of(context).ok,
|
||||
buttonAction: () => Navigator.of(context).pop()
|
||||
);
|
||||
buttonAction: () => Navigator.of(context).pop());
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
_nameController.addListener(
|
||||
() => widget.walletRestorationFromSeedVM.name = _nameController.text);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_nameController.dispose();
|
||||
_stateReaction.reaction.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.only(left: 24, right: 24),
|
||||
child: ScrollableWithBottomSection(
|
||||
contentPadding: EdgeInsets.only(bottom: 24.0),
|
||||
content: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
child: Column(children: <Widget>[
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(top: 20.0),
|
||||
child: TextFormField(
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
color: Theme.of(context).primaryTextTheme.title.color
|
||||
),
|
||||
controller: _nameController,
|
||||
decoration: InputDecoration(
|
||||
hintStyle: TextStyle(
|
||||
color: Theme.of(context).primaryTextTheme.caption.color,
|
||||
fontSize: 16
|
||||
),
|
||||
hintText: S.of(context).restore_wallet_name,
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1.0)),
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1.0))),
|
||||
validator: (value) {
|
||||
walletRestorationStore
|
||||
.validateWalletName(value);
|
||||
return walletRestorationStore.errorMessage;
|
||||
},
|
||||
),
|
||||
))
|
||||
],
|
||||
),
|
||||
BlockchainHeightWidget(key: _blockchainHeightKey),
|
||||
]),
|
||||
Flexible(
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(top: 20.0),
|
||||
child: TextFormField(
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
color: Theme.of(context).primaryTextTheme.title.color),
|
||||
controller: _nameController,
|
||||
decoration: InputDecoration(
|
||||
hintStyle: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.caption
|
||||
.color,
|
||||
fontSize: 16),
|
||||
hintText: S.of(context).restore_wallet_name,
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1.0)),
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1.0))),
|
||||
validator: WalletNameValidator(),
|
||||
),
|
||||
))
|
||||
],
|
||||
),
|
||||
if (widget.walletRestorationFromSeedVM.hasRestorationHeight)
|
||||
BlockchainHeightWidget(
|
||||
key: _blockchainHeightKey,
|
||||
onHeightChange: (height) {
|
||||
widget.walletRestorationFromSeedVM.height = height;
|
||||
print(height);
|
||||
}),
|
||||
]),
|
||||
),
|
||||
bottomSectionPadding: EdgeInsets.only(bottom: 24),
|
||||
bottomSection: Observer(builder: (_) {
|
||||
return LoadingPrimaryButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState.validate()) {
|
||||
walletRestorationStore.restoreFromSeed(
|
||||
name: _nameController.text,
|
||||
restoreHeight: _blockchainHeightKey.currentState.height);
|
||||
widget.walletRestorationFromSeedVM.create();
|
||||
}
|
||||
},
|
||||
isLoading: walletRestorationStore.state is WalletIsRestoring,
|
||||
isLoading:
|
||||
widget.walletRestorationFromSeedVM.state is WalletCreating,
|
||||
text: S.of(context).restore_recover,
|
||||
color: Colors.green,
|
||||
textColor: Colors.white,
|
||||
isDisabled: walletRestorationStore.disabledState,
|
||||
isDisabled: _nameController.text.isNotEmpty,
|
||||
);
|
||||
}),
|
||||
),
|
||||
|
||||
@@ -1,27 +1,19 @@
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/domain/services/wallet_list_service.dart';
|
||||
import 'package:cake_wallet/src/domain/services/wallet_service.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/stores/wallet_restoration/wallet_restoration_store.dart';
|
||||
import 'package:cake_wallet/src/widgets/seed_widget.dart';
|
||||
import 'package:cake_wallet/src/stores/seed_language/seed_language_store.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||
import 'package:cake_wallet/core/seed_validator.dart';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:cake_wallet/core/mnemonic_length.dart';
|
||||
|
||||
class RestoreWalletFromSeedPage extends BasePage {
|
||||
RestoreWalletFromSeedPage(
|
||||
{@required this.walletsService,
|
||||
@required this.walletService,
|
||||
@required this.sharedPreferences});
|
||||
RestoreWalletFromSeedPage({@required this.type, @required this.language});
|
||||
|
||||
final WalletListService walletsService;
|
||||
final WalletService walletService;
|
||||
final SharedPreferences sharedPreferences;
|
||||
final WalletType type;
|
||||
final String language;
|
||||
final formKey = GlobalKey<_RestoreFromSeedFormState>();
|
||||
|
||||
@override
|
||||
@@ -34,11 +26,14 @@ class RestoreWalletFromSeedPage extends BasePage {
|
||||
Color get backgroundDarkColor => PaletteDark.lightNightBlue;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) => RestoreFromSeedForm(key: formKey);
|
||||
Widget body(BuildContext context) =>
|
||||
RestoreFromSeedForm(key: formKey, type: type, language: language);
|
||||
}
|
||||
|
||||
class RestoreFromSeedForm extends StatefulWidget {
|
||||
RestoreFromSeedForm({Key key}) : super(key: key);
|
||||
RestoreFromSeedForm({Key key, this.type, this.language}) : super(key: key);
|
||||
final WalletType type;
|
||||
final String language;
|
||||
|
||||
@override
|
||||
_RestoreFromSeedFormState createState() => _RestoreFromSeedFormState();
|
||||
@@ -46,13 +41,11 @@ class RestoreFromSeedForm extends StatefulWidget {
|
||||
|
||||
class _RestoreFromSeedFormState extends State<RestoreFromSeedForm> {
|
||||
final _seedKey = GlobalKey<SeedWidgetState>();
|
||||
void clear() => _seedKey.currentState.clear();
|
||||
|
||||
String mnemonic() => _seedKey.currentState.items.map((e) => e.text).join(' ');
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final walletRestorationStore = Provider.of<WalletRestorationStore>(context);
|
||||
final seedLanguageStore = Provider.of<SeedLanguageStore>(context);
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () =>
|
||||
SystemChannels.textInput.invokeMethod<void>('TextInput.hide'),
|
||||
@@ -60,11 +53,13 @@ class _RestoreFromSeedFormState extends State<RestoreFromSeedForm> {
|
||||
color: Theme.of(context).backgroundColor,
|
||||
child: SeedWidget(
|
||||
key: _seedKey,
|
||||
onMnemoticChange: (seed) => walletRestorationStore.setSeed(seed),
|
||||
maxLength: mnemonicLength(widget.type),
|
||||
onMnemonicChange: (seed) => null,
|
||||
onFinish: () => Navigator.of(context).pushNamed(
|
||||
Routes.restoreWalletFromSeedDetails,
|
||||
arguments: _seedKey.currentState.items),
|
||||
seedLanguage: seedLanguageStore.selectedSeedLanguage,
|
||||
arguments: [widget.type, widget.language, mnemonic()]),
|
||||
validator:
|
||||
SeedValidator(type: widget.type, language: widget.language),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:cake_wallet/src/screens/restore/widgets/restore_button.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/stores/seed_language/seed_language_store.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class RestoreWalletOptionsPage extends BasePage {
|
||||
RestoreWalletOptionsPage({@required this.type});
|
||||
RestoreWalletOptionsPage(
|
||||
{@required this.type,
|
||||
@required this.onRestoreFromSeed,
|
||||
@required this.onRestoreFromKeys});
|
||||
|
||||
static const _aspectRatioImage = 2.086;
|
||||
final WalletType type;
|
||||
final Function(BuildContext context) onRestoreFromSeed;
|
||||
final Function(BuildContext context) onRestoreFromKeys;
|
||||
|
||||
@override
|
||||
String get title => S.current.restore_seed_keys_restore;
|
||||
@@ -23,8 +25,6 @@ class RestoreWalletOptionsPage extends BasePage {
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
final seedLanguageStore = Provider.of<SeedLanguageStore>(context);
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
@@ -33,28 +33,56 @@ class RestoreWalletOptionsPage extends BasePage {
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
RestoreButton(
|
||||
onPressed: () {
|
||||
seedLanguageStore
|
||||
.setCurrentRoute(Routes.restoreWalletFromSeed);
|
||||
Navigator.pushNamed(context, Routes.seedLanguage);
|
||||
},
|
||||
onPressed: () => onRestoreFromSeed(context),
|
||||
image: imageSeed,
|
||||
title: S.of(context).restore_title_from_seed,
|
||||
description: S.of(context).restore_description_from_seed),
|
||||
description: _fromSeedDescription(context)),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: RestoreButton(
|
||||
onPressed: () {
|
||||
seedLanguageStore
|
||||
.setCurrentRoute(Routes.restoreWalletFromKeys);
|
||||
Navigator.pushNamed(context, Routes.seedLanguage);
|
||||
},
|
||||
onPressed: () => onRestoreFromKeys(context),
|
||||
image: imageKeys,
|
||||
title: S.of(context).restore_title_from_keys,
|
||||
description: S.of(context).restore_description_from_keys),
|
||||
title: _fromKeyTitle(context),
|
||||
description: _fromKeyDescription(context)),
|
||||
)
|
||||
],
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
String _fromSeedDescription(BuildContext context) {
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
return S.of(context).restore_description_from_seed;
|
||||
case WalletType.bitcoin:
|
||||
// TODO: Add transaction for bitcoin description.
|
||||
return 'Restore your wallet from 12 word combination code';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
String _fromKeyDescription(BuildContext context) {
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
return S.of(context).restore_description_from_keys;
|
||||
case WalletType.bitcoin:
|
||||
// TODO: Add transaction for bitcoin description.
|
||||
return 'Restore your wallet from generated WIF string from your private keys';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
String _fromKeyTitle(BuildContext context) {
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
return S.of(context).restore_title_from_keys;
|
||||
case WalletType.bitcoin:
|
||||
// TODO: Add transaction for bitcoin description.
|
||||
return 'Restore from WIF';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/dashboard_page.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/stores/authentication/authentication_store.dart';
|
||||
import 'package:cake_wallet/store/authentication_store.dart';
|
||||
|
||||
//import 'package:cake_wallet/src/stores/authentication/authentication_store.dart';
|
||||
import 'package:cake_wallet/src/stores/price/price_store.dart';
|
||||
import 'package:cake_wallet/src/stores/settings/settings_store.dart';
|
||||
import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
|
||||
@@ -21,7 +26,10 @@ import 'package:cake_wallet/src/screens/auth/auth_page.dart';
|
||||
import 'package:cake_wallet/src/screens/welcome/create_welcome_page.dart';
|
||||
|
||||
class Root extends StatefulWidget {
|
||||
Root({Key key}) : super(key: key);
|
||||
Root({Key key, this.authenticationStore, this.appStore}) : super(key: key);
|
||||
|
||||
final AuthenticationStore authenticationStore;
|
||||
final AppStore appStore;
|
||||
|
||||
@override
|
||||
RootState createState() => RootState();
|
||||
@@ -30,7 +38,6 @@ class Root extends StatefulWidget {
|
||||
class RootState extends State<Root> with WidgetsBindingObserver {
|
||||
bool _isInactive;
|
||||
bool _postFrameCallback;
|
||||
AuthenticationStore _authenticationStore;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -48,12 +55,12 @@ class RootState extends State<Root> with WidgetsBindingObserver {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_isInactive &&
|
||||
_authenticationStore.state ==
|
||||
AuthenticationState.authenticated ||
|
||||
_authenticationStore.state == AuthenticationState.active) {
|
||||
setState(() => _isInactive = true);
|
||||
}
|
||||
// if (!_isInactive &&
|
||||
// widget.authenticationStore.state ==
|
||||
// AuthenticationState.authenticated ||
|
||||
// widget.authenticationStore.state == AuthenticationState.active) {
|
||||
// setState(() => _isInactive = true);
|
||||
// }
|
||||
|
||||
break;
|
||||
default:
|
||||
@@ -63,18 +70,18 @@ class RootState extends State<Root> with WidgetsBindingObserver {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_authenticationStore = Provider.of<AuthenticationStore>(context);
|
||||
final sharedPreferences = Provider.of<SharedPreferences>(context);
|
||||
final walletListService = Provider.of<WalletListService>(context);
|
||||
final walletService = Provider.of<WalletService>(context);
|
||||
final userService = Provider.of<UserService>(context);
|
||||
final priceStore = Provider.of<PriceStore>(context);
|
||||
final authenticationStore = Provider.of<AuthenticationStore>(context);
|
||||
final trades = Provider.of<Box<Trade>>(context);
|
||||
final transactionDescriptions =
|
||||
Provider.of<Box<TransactionDescription>>(context);
|
||||
final walletStore = Provider.of<WalletStore>(context);
|
||||
final settingsStore = Provider.of<SettingsStore>(context);
|
||||
// _authenticationStore = Provider.of<AuthenticationStore>(context);
|
||||
// final sharedPreferences = Provider.of<SharedPreferences>(context);
|
||||
// final walletListService = Provider.of<WalletListService>(context);
|
||||
// final walletService = Provider.of<WalletService>(context);
|
||||
// final userService = Provider.of<UserService>(context);
|
||||
// final priceStore = Provider.of<PriceStore>(context);
|
||||
// final authenticationStore = Provider.of<AuthenticationStore>(context);
|
||||
// final trades = Provider.of<Box<Trade>>(context);
|
||||
// final transactionDescriptions =
|
||||
// Provider.of<Box<TransactionDescription>>(context);
|
||||
// final walletStore = Provider.of<WalletStore>(context);
|
||||
// final settingsStore = Provider.of<SettingsStore>(context);
|
||||
|
||||
if (_isInactive && !_postFrameCallback) {
|
||||
_postFrameCallback = true;
|
||||
@@ -96,38 +103,51 @@ class RootState extends State<Root> with WidgetsBindingObserver {
|
||||
}
|
||||
|
||||
return Observer(builder: (_) {
|
||||
final state = _authenticationStore.state;
|
||||
final state = widget.authenticationStore.state;
|
||||
print(state);
|
||||
if (state == AuthenticationState.denied) {
|
||||
return createWelcomePage();
|
||||
}
|
||||
|
||||
if (state == AuthenticationState.readyToLogin) {
|
||||
return createLoginPage(
|
||||
sharedPreferences: sharedPreferences,
|
||||
userService: userService,
|
||||
walletService: walletService,
|
||||
walletListService: walletListService,
|
||||
authenticationStore: authenticationStore);
|
||||
if (state == AuthenticationState.installed) {
|
||||
return getIt.get<AuthPage>();
|
||||
}
|
||||
|
||||
if (state == AuthenticationState.authenticated ||
|
||||
state == AuthenticationState.restored) {
|
||||
return createDashboardPage(
|
||||
walletService: walletService,
|
||||
priceStore: priceStore,
|
||||
trades: trades,
|
||||
transactionDescriptions: transactionDescriptions,
|
||||
walletStore: walletStore,
|
||||
settingsStore: settingsStore);
|
||||
if (state == AuthenticationState.allowed) {
|
||||
return getIt.get<DashboardPage>();
|
||||
}
|
||||
|
||||
if (state == AuthenticationState.created) {
|
||||
return createSeedPage(
|
||||
settingsStore: settingsStore,
|
||||
walletService: walletService,
|
||||
callback: () =>
|
||||
_authenticationStore.state = AuthenticationState.authenticated);
|
||||
}
|
||||
// if (state == AuthenticationState.denied) {
|
||||
// return createWelcomePage();
|
||||
// }
|
||||
|
||||
// if (state == AuthenticationState.readyToLogin) {
|
||||
// return createLoginPage(
|
||||
// sharedPreferences: sharedPreferences,
|
||||
// userService: userService,
|
||||
// walletService: walletService,
|
||||
// walletListService: walletListService,
|
||||
// authenticationStore: authenticationStore);
|
||||
// }
|
||||
|
||||
// if (state == AuthenticationState.authenticated ||
|
||||
// state == AuthenticationState.restored) {
|
||||
// return createDashboardPage(
|
||||
// walletService: walletService,
|
||||
// priceStore: priceStore,
|
||||
// trades: trades,
|
||||
// transactionDescriptions: transactionDescriptions,
|
||||
// walletStore: walletStore,
|
||||
// settingsStore: settingsStore);
|
||||
// }
|
||||
|
||||
// if (state == AuthenticationState.created) {
|
||||
// return createSeedPage(
|
||||
// settingsStore: settingsStore,
|
||||
// walletService: walletService,
|
||||
// callback: () =>
|
||||
// _authenticationStore.state = AuthenticationState.authenticated);
|
||||
// }
|
||||
|
||||
return Container(color: Colors.white);
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:cake_wallet/src/widgets/seed_language_selector.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -11,79 +12,68 @@ import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
|
||||
import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
|
||||
|
||||
class SeedLanguage extends BasePage {
|
||||
SeedLanguage({this.onConfirm});
|
||||
|
||||
final Function(BuildContext, String) onConfirm;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) => SeedLanguageForm();
|
||||
Widget body(BuildContext context) => SeedLanguageForm(onConfirm: onConfirm);
|
||||
}
|
||||
|
||||
class SeedLanguageForm extends StatefulWidget {
|
||||
SeedLanguageForm({this.onConfirm});
|
||||
|
||||
final Function(BuildContext, String) onConfirm;
|
||||
|
||||
@override
|
||||
SeedLanguageFormState createState() => SeedLanguageFormState();
|
||||
}
|
||||
|
||||
class SeedLanguageFormState extends State<SeedLanguageForm> {
|
||||
static const aspectRatioImage = 1.22;
|
||||
|
||||
final walletNameImage = Image.asset('assets/images/wallet_name.png');
|
||||
final _languageSelectorKey = GlobalKey<SeedLanguageSelectorState>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final seedLanguageStore = Provider.of<SeedLanguageStore>(context);
|
||||
|
||||
final List<String> seedLocales = [
|
||||
S.current.seed_language_english,
|
||||
S.current.seed_language_chinese,
|
||||
S.current.seed_language_dutch,
|
||||
S.current.seed_language_german,
|
||||
S.current.seed_language_japanese,
|
||||
S.current.seed_language_portuguese,
|
||||
S.current.seed_language_russian,
|
||||
S.current.seed_language_spanish
|
||||
];
|
||||
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: ScrollableWithBottomSection(
|
||||
contentPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
|
||||
content: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 12, right: 12),
|
||||
child: AspectRatio(
|
||||
aspectRatio: aspectRatioImage,
|
||||
child: FittedBox(child: walletNameImage, fit: BoxFit.fill)),
|
||||
),
|
||||
Padding(padding: EdgeInsets.only(top: 40),
|
||||
child: Text(
|
||||
S.of(context).seed_language_choose,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).primaryTextTheme.title.color
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(padding: EdgeInsets.only(top: 24),
|
||||
child: Observer(
|
||||
builder: (_) => SelectButton(
|
||||
image: null,
|
||||
text: seedLocales[seedLanguages.indexOf(seedLanguageStore.selectedSeedLanguage)],
|
||||
color: Theme.of(context).accentTextTheme.title.backgroundColor,
|
||||
textColor: Theme.of(context).primaryTextTheme.title.color,
|
||||
onTap: () async => await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) => SeedLanguagePicker()
|
||||
)
|
||||
)
|
||||
),
|
||||
)
|
||||
]),
|
||||
bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
|
||||
content:
|
||||
Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 12, right: 12),
|
||||
child: AspectRatio(
|
||||
aspectRatio: aspectRatioImage,
|
||||
child: FittedBox(child: walletNameImage, fit: BoxFit.fill)),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 40),
|
||||
child: Text(
|
||||
S.of(context).seed_language_choose,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).primaryTextTheme.title.color),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: SeedLanguageSelector(
|
||||
key: _languageSelectorKey,
|
||||
initialSelected: defaultSeedLanguage),
|
||||
)
|
||||
]),
|
||||
bottomSectionPadding:
|
||||
EdgeInsets.only(left: 24, right: 24, bottom: 24),
|
||||
bottomSection: Observer(
|
||||
builder: (context) {
|
||||
return PrimaryButton(
|
||||
onPressed: () =>
|
||||
Navigator.of(context).popAndPushNamed(seedLanguageStore.currentRoute),
|
||||
onPressed: () => widget
|
||||
.onConfirm(context, _languageSelectorKey.currentState.selected),
|
||||
text: S.of(context).seed_language_next,
|
||||
color: Colors.green,
|
||||
textColor: Colors.white);
|
||||
|
||||
@@ -17,7 +17,7 @@ List<Image> flagImages = [
|
||||
Image.asset('assets/images/spain.png'),
|
||||
];
|
||||
|
||||
List<String> languageCodes = [
|
||||
const List<String> languageCodes = [
|
||||
'Eng',
|
||||
'Chi',
|
||||
'Ned',
|
||||
@@ -28,19 +28,39 @@ List<String> languageCodes = [
|
||||
'Esp',
|
||||
];
|
||||
|
||||
enum Places {topLeft, topRight, bottomLeft, bottomRight, inside}
|
||||
const defaultSeedLanguage = 'English';
|
||||
|
||||
const List<String> seedLanguages = [
|
||||
defaultSeedLanguage,
|
||||
'Chinese (simplified)',
|
||||
'Dutch',
|
||||
'German',
|
||||
'Japanese',
|
||||
'Portuguese',
|
||||
'Russian',
|
||||
'Spanish'
|
||||
];
|
||||
|
||||
enum Places { topLeft, topRight, bottomLeft, bottomRight, inside }
|
||||
|
||||
class SeedLanguagePicker extends StatefulWidget {
|
||||
SeedLanguagePicker({Key key, this.selected = defaultSeedLanguage})
|
||||
: super(key: key);
|
||||
|
||||
final String selected;
|
||||
|
||||
@override
|
||||
SeedLanguagePickerState createState() => SeedLanguagePickerState();
|
||||
SeedLanguagePickerState createState() =>
|
||||
SeedLanguagePickerState(selected: selected);
|
||||
}
|
||||
|
||||
class SeedLanguagePickerState extends State<SeedLanguagePicker> {
|
||||
SeedLanguagePickerState({this.selected});
|
||||
|
||||
String selected;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final seedLanguageStore = Provider.of<SeedLanguageStore>(context);
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () => Navigator.of(context).pop(),
|
||||
child: Container(
|
||||
@@ -48,7 +68,8 @@ class SeedLanguagePickerState extends State<SeedLanguagePicker> {
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: 3.0, sigmaY: 3.0),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(color: PaletteDark.darkNightBlue.withOpacity(0.75)),
|
||||
decoration: BoxDecoration(
|
||||
color: PaletteDark.darkNightBlue.withOpacity(0.75)),
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@@ -62,8 +83,7 @@ class SeedLanguagePickerState extends State<SeedLanguagePicker> {
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
decoration: TextDecoration.none,
|
||||
color: Colors.white
|
||||
),
|
||||
color: Colors.white),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
@@ -74,9 +94,8 @@ class SeedLanguagePickerState extends State<SeedLanguagePicker> {
|
||||
height: 300,
|
||||
width: 300,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(14)),
|
||||
color: Theme.of(context).dividerColor
|
||||
),
|
||||
borderRadius: BorderRadius.all(Radius.circular(14)),
|
||||
color: Theme.of(context).dividerColor),
|
||||
child: GridView.count(
|
||||
shrinkWrap: true,
|
||||
crossAxisCount: 3,
|
||||
@@ -85,71 +104,64 @@ class SeedLanguagePickerState extends State<SeedLanguagePicker> {
|
||||
crossAxisSpacing: 1,
|
||||
mainAxisSpacing: 1,
|
||||
children: List.generate(9, (index) {
|
||||
|
||||
if (index == 8) {
|
||||
|
||||
return gridTile(
|
||||
isCurrent: false,
|
||||
place: Places.bottomRight,
|
||||
image: null,
|
||||
text: '',
|
||||
onTap: null);
|
||||
|
||||
isCurrent: false,
|
||||
place: Places.bottomRight,
|
||||
image: null,
|
||||
text: '',
|
||||
onTap: null);
|
||||
} else {
|
||||
|
||||
final code = languageCodes[index];
|
||||
final flag = flagImages[index];
|
||||
final isCurrent = index == seedLanguages.indexOf(seedLanguageStore.selectedSeedLanguage);
|
||||
final isCurrent =
|
||||
index == seedLanguages.indexOf(selected);
|
||||
|
||||
if (index == 0) {
|
||||
return gridTile(
|
||||
isCurrent: isCurrent,
|
||||
place: Places.topLeft,
|
||||
image: flag,
|
||||
text: code,
|
||||
onTap: () {
|
||||
seedLanguageStore.setSelectedSeedLanguage(seedLanguages[index]);
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
);
|
||||
isCurrent: isCurrent,
|
||||
place: Places.topLeft,
|
||||
image: flag,
|
||||
text: code,
|
||||
onTap: () {
|
||||
selected = seedLanguages[index];
|
||||
Navigator.of(context).pop(selected);
|
||||
});
|
||||
}
|
||||
|
||||
if (index == 2) {
|
||||
return gridTile(
|
||||
isCurrent: isCurrent,
|
||||
place: Places.topRight,
|
||||
image: flag,
|
||||
text: code,
|
||||
onTap: () {
|
||||
seedLanguageStore.setSelectedSeedLanguage(seedLanguages[index]);
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
);
|
||||
isCurrent: isCurrent,
|
||||
place: Places.topRight,
|
||||
image: flag,
|
||||
text: code,
|
||||
onTap: () {
|
||||
selected = seedLanguages[index];
|
||||
Navigator.of(context).pop(selected);
|
||||
});
|
||||
}
|
||||
|
||||
if (index == 6) {
|
||||
return gridTile(
|
||||
isCurrent: isCurrent,
|
||||
place: Places.bottomLeft,
|
||||
image: flag,
|
||||
text: code,
|
||||
onTap: () {
|
||||
seedLanguageStore.setSelectedSeedLanguage(seedLanguages[index]);
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
);
|
||||
isCurrent: isCurrent,
|
||||
place: Places.bottomLeft,
|
||||
image: flag,
|
||||
text: code,
|
||||
onTap: () {
|
||||
selected = seedLanguages[index];
|
||||
Navigator.of(context).pop(selected);
|
||||
});
|
||||
}
|
||||
|
||||
return gridTile(
|
||||
isCurrent: isCurrent,
|
||||
place: Places.inside,
|
||||
image: flag,
|
||||
text: code,
|
||||
onTap: () {
|
||||
seedLanguageStore.setSelectedSeedLanguage(seedLanguages[index]);
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
);
|
||||
isCurrent: isCurrent,
|
||||
place: Places.inside,
|
||||
image: flag,
|
||||
text: code,
|
||||
onTap: () {
|
||||
selected = seedLanguages[index];
|
||||
Navigator.of(context).pop(selected);
|
||||
});
|
||||
}
|
||||
}),
|
||||
),
|
||||
@@ -165,13 +177,12 @@ class SeedLanguagePickerState extends State<SeedLanguagePicker> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget gridTile({
|
||||
@required bool isCurrent,
|
||||
@required Places place,
|
||||
@required Image image,
|
||||
@required String text,
|
||||
@required VoidCallback onTap}) {
|
||||
|
||||
Widget gridTile(
|
||||
{@required bool isCurrent,
|
||||
@required Places place,
|
||||
@required Image image,
|
||||
@required String text,
|
||||
@required VoidCallback onTap}) {
|
||||
BorderRadius borderRadius;
|
||||
final color = isCurrent
|
||||
? Theme.of(context).accentTextTheme.subtitle.decorationColor
|
||||
@@ -199,40 +210,33 @@ class SeedLanguagePickerState extends State<SeedLanguagePicker> {
|
||||
}
|
||||
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: borderRadius,
|
||||
color: color
|
||||
),
|
||||
child: Center(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
image != null
|
||||
? image
|
||||
: Offstage(),
|
||||
Padding(
|
||||
padding: image != null
|
||||
? EdgeInsets.only(left: 10)
|
||||
: EdgeInsets.only(left: 0),
|
||||
child: Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
decoration: TextDecoration.none,
|
||||
color: textColor
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(borderRadius: borderRadius, color: color),
|
||||
child: Center(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
image != null ? image : Offstage(),
|
||||
Padding(
|
||||
padding: image != null
|
||||
? EdgeInsets.only(left: 10)
|
||||
: EdgeInsets.only(left: 0),
|
||||
child: Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
decoration: TextDecoration.none,
|
||||
color: textColor),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/view_model/address_list/address_edit_or_create_view_model.dart';
|
||||
import 'package:cake_wallet/core/AddressLabelValidator.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
|
||||
class AddressEditOrCreatePage extends BasePage {
|
||||
AddressEditOrCreatePage({@required this.addressEditOrCreateViewModel})
|
||||
: _formKey = GlobalKey<FormState>(),
|
||||
_labelController = TextEditingController(),
|
||||
super() {
|
||||
_labelController.addListener(
|
||||
() => addressEditOrCreateViewModel.label = _labelController.text);
|
||||
_labelController.text = addressEditOrCreateViewModel.label;
|
||||
print(_labelController.text);
|
||||
print(addressEditOrCreateViewModel.label);
|
||||
}
|
||||
|
||||
final AddressEditOrCreateViewModel addressEditOrCreateViewModel;
|
||||
final GlobalKey<FormState> _formKey;
|
||||
final TextEditingController _labelController;
|
||||
|
||||
@override
|
||||
String get title => S.current.new_subaddress_title;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
reaction((_) => addressEditOrCreateViewModel.state,
|
||||
(AddressEditOrCreateState state) {
|
||||
if (state is AddressSavedSuccessfully) {
|
||||
WidgetsBinding.instance
|
||||
.addPostFrameCallback((_) => Navigator.of(context).pop());
|
||||
}
|
||||
});
|
||||
|
||||
return Form(
|
||||
key: _formKey,
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(24.0),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Center(
|
||||
child: BaseTextFormField(
|
||||
controller: _labelController,
|
||||
hintText: S.of(context).new_subaddress_label_name,
|
||||
validator: AddressLabelValidator()))),
|
||||
Observer(
|
||||
builder: (_) => LoadingPrimaryButton(
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState.validate()) {
|
||||
await addressEditOrCreateViewModel.save();
|
||||
}
|
||||
},
|
||||
text: addressEditOrCreateViewModel.isEdit
|
||||
? S.of(context).rename
|
||||
: S.of(context).new_subaddress_create,
|
||||
color: Colors.green,
|
||||
textColor: Colors.white,
|
||||
isLoading:
|
||||
addressEditOrCreateViewModel.state is AddressIsSaving,
|
||||
isDisabled:
|
||||
addressEditOrCreateViewModel.label?.isEmpty ?? true,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
import 'package:cake_wallet/src/domain/monero/subaddress.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/stores/subaddress_creation/subaddress_creation_state.dart';
|
||||
import 'package:cake_wallet/src/stores/subaddress_creation/subaddress_creation_store.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||
|
||||
class NewSubaddressPage extends BasePage {
|
||||
NewSubaddressPage({this.subaddress});
|
||||
|
||||
final Subaddress subaddress;
|
||||
|
||||
@override
|
||||
String get title => S.current.new_subaddress_title;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) => NewSubaddressForm(subaddress);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final subaddressCreationStore =
|
||||
Provider.of<SubadrressCreationStore>(context);
|
||||
|
||||
reaction((_) => subaddressCreationStore.state, (SubaddressCreationState state) {
|
||||
if (state is SubaddressCreatedSuccessfully) {
|
||||
WidgetsBinding.instance
|
||||
.addPostFrameCallback((_) => Navigator.of(context).pop());
|
||||
}
|
||||
});
|
||||
|
||||
return super.build(context);
|
||||
}
|
||||
}
|
||||
|
||||
class NewSubaddressForm extends StatefulWidget {
|
||||
NewSubaddressForm(this.subaddress);
|
||||
|
||||
final Subaddress subaddress;
|
||||
|
||||
@override
|
||||
NewSubaddressFormState createState() => NewSubaddressFormState(subaddress);
|
||||
}
|
||||
|
||||
class NewSubaddressFormState extends State<NewSubaddressForm> {
|
||||
NewSubaddressFormState(this.subaddress);
|
||||
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final _labelController = TextEditingController();
|
||||
final Subaddress subaddress;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
if (subaddress != null) _labelController.text = subaddress.label;
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_labelController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final subaddressCreationStore =
|
||||
Provider.of<SubadrressCreationStore>(context);
|
||||
|
||||
_labelController.addListener(() {
|
||||
if (_labelController.text.isNotEmpty) {
|
||||
subaddressCreationStore.setDisabledStatus(false);
|
||||
} else {
|
||||
subaddressCreationStore.setDisabledStatus(true);
|
||||
}
|
||||
});
|
||||
|
||||
return Form(
|
||||
key: _formKey,
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(24.0),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Center(
|
||||
child: BaseTextFormField(
|
||||
controller: _labelController,
|
||||
hintText: S.of(context).new_subaddress_label_name,
|
||||
validator: (value) {
|
||||
subaddressCreationStore.validateSubaddressName(value);
|
||||
return subaddressCreationStore.errorMessage;
|
||||
}
|
||||
)
|
||||
)
|
||||
),
|
||||
Observer(
|
||||
builder: (_) => LoadingPrimaryButton(
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState.validate()) {
|
||||
if (subaddress != null) {
|
||||
await subaddressCreationStore.setLabel(
|
||||
addressIndex: subaddress.id,
|
||||
label: _labelController.text
|
||||
);
|
||||
} else {
|
||||
await subaddressCreationStore.add(
|
||||
label: _labelController.text);
|
||||
}
|
||||
}
|
||||
},
|
||||
text: subaddress != null
|
||||
? S.of(context).rename
|
||||
: S.of(context).new_subaddress_create,
|
||||
color: Colors.green,
|
||||
textColor: Colors.white,
|
||||
isLoading:
|
||||
subaddressCreationStore.state is SubaddressIsCreating,
|
||||
isDisabled: subaddressCreationStore.isDisabledStatus,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -32,9 +32,7 @@ class SubaddressListPage extends BasePage {
|
||||
child: Observer(
|
||||
builder: (_) => ListView.separated(
|
||||
separatorBuilder: (_, __) => Divider(
|
||||
color: Theme.of(context).dividerTheme.color,
|
||||
height: 1.0,
|
||||
),
|
||||
color: Theme.of(context).dividerTheme.color, height: 1.0),
|
||||
itemCount: subaddressListStore.subaddresses == null
|
||||
? 0
|
||||
: subaddressListStore.subaddresses.length,
|
||||
@@ -42,9 +40,7 @@ class SubaddressListPage extends BasePage {
|
||||
final subaddress = subaddressListStore.subaddresses[index];
|
||||
final isCurrent =
|
||||
walletStore.subaddress.address == subaddress.address;
|
||||
final label = subaddress.label != null
|
||||
? subaddress.label
|
||||
: subaddress.address;
|
||||
final label = subaddress.label ?? subaddress.address;
|
||||
|
||||
return InkWell(
|
||||
onTap: () => Navigator.of(context).pop(subaddress),
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
abstract class AuthState {}
|
||||
|
||||
class AuthenticationStateInitial extends AuthState {}
|
||||
|
||||
class AuthenticationInProgress extends AuthState {}
|
||||
|
||||
class AuthenticatedSuccessfully extends AuthState {}
|
||||
|
||||
class AuthenticationFailure extends AuthState {
|
||||
AuthenticationFailure({this.error});
|
||||
|
||||
final String error;
|
||||
}
|
||||
|
||||
class AuthenticationBanned extends AuthState {
|
||||
AuthenticationBanned({this.error});
|
||||
|
||||
final String error;
|
||||
}
|
||||
|
||||
@@ -1,99 +1,99 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/src/domain/services/user_service.dart';
|
||||
import 'package:cake_wallet/src/domain/services/wallet_service.dart';
|
||||
import 'package:cake_wallet/src/stores/auth/auth_state.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
|
||||
part 'auth_store.g.dart';
|
||||
|
||||
class AuthStore = AuthStoreBase with _$AuthStore;
|
||||
|
||||
abstract class AuthStoreBase with Store {
|
||||
AuthStoreBase(
|
||||
{@required this.userService,
|
||||
@required this.walletService,
|
||||
@required this.sharedPreferences}) {
|
||||
state = AuthenticationStateInitial();
|
||||
_failureCounter = 0;
|
||||
}
|
||||
|
||||
static const maxFailedLogins = 3;
|
||||
static const banTimeout = 180; // 3 mins
|
||||
final banTimeoutKey = S.current.auth_store_ban_timeout;
|
||||
|
||||
final UserService userService;
|
||||
final WalletService walletService;
|
||||
|
||||
final SharedPreferences sharedPreferences;
|
||||
|
||||
@observable
|
||||
AuthState state;
|
||||
|
||||
@observable
|
||||
int _failureCounter;
|
||||
|
||||
@action
|
||||
Future auth({String password}) async {
|
||||
state = AuthenticationStateInitial();
|
||||
final _banDuration = banDuration();
|
||||
|
||||
if (_banDuration != null) {
|
||||
state = AuthenticationBanned(
|
||||
error: S.current.auth_store_banned_for + '${_banDuration.inMinutes}' + S.current.auth_store_banned_minutes);
|
||||
return;
|
||||
}
|
||||
|
||||
state = AuthenticationInProgress();
|
||||
final isAuth = await userService.authenticate(password);
|
||||
|
||||
if (isAuth) {
|
||||
state = AuthenticatedSuccessfully();
|
||||
_failureCounter = 0;
|
||||
} else {
|
||||
_failureCounter += 1;
|
||||
|
||||
if (_failureCounter >= maxFailedLogins) {
|
||||
final banDuration = await ban();
|
||||
state = AuthenticationBanned(
|
||||
error: S.current.auth_store_banned_for + '${banDuration.inMinutes}' + S.current.auth_store_banned_minutes);
|
||||
return;
|
||||
}
|
||||
|
||||
state = AuthenticationFailure(error: S.current.auth_store_incorrect_password);
|
||||
}
|
||||
}
|
||||
|
||||
Duration banDuration() {
|
||||
final unbanTimestamp = sharedPreferences.getInt(banTimeoutKey);
|
||||
|
||||
if (unbanTimestamp == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final unbanTime = DateTime.fromMillisecondsSinceEpoch(unbanTimestamp);
|
||||
final now = DateTime.now();
|
||||
|
||||
if (now.isAfter(unbanTime)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Duration(milliseconds: unbanTimestamp - now.millisecondsSinceEpoch);
|
||||
}
|
||||
|
||||
Future<Duration> ban() async {
|
||||
final multiplier = _failureCounter - maxFailedLogins + 1;
|
||||
final timeout = (multiplier * banTimeout) * 1000;
|
||||
final unbanTimestamp = DateTime.now().millisecondsSinceEpoch + timeout;
|
||||
await sharedPreferences.setInt(banTimeoutKey, unbanTimestamp);
|
||||
|
||||
return Duration(milliseconds: timeout);
|
||||
}
|
||||
|
||||
@action
|
||||
void biometricAuth() {
|
||||
state = AuthenticatedSuccessfully();
|
||||
}
|
||||
}
|
||||
//import 'dart:async';
|
||||
//import 'package:flutter/foundation.dart';
|
||||
//import 'package:shared_preferences/shared_preferences.dart';
|
||||
//import 'package:mobx/mobx.dart';
|
||||
//import 'package:cake_wallet/src/domain/services/user_service.dart';
|
||||
//import 'package:cake_wallet/src/domain/services/wallet_service.dart';
|
||||
//import 'package:cake_wallet/view_model/auth_state.dart';
|
||||
//import 'package:cake_wallet/generated/i18n.dart';
|
||||
//
|
||||
//part 'auth_store.g.dart';
|
||||
//
|
||||
//class AuthStore = AuthStoreBase with _$AuthStore;
|
||||
//
|
||||
//abstract class AuthStoreBase with Store {
|
||||
// AuthStoreBase(
|
||||
// {@required this.userService,
|
||||
// @required this.walletService,
|
||||
// @required this.sharedPreferences}) {
|
||||
// state = AuthenticationStateInitial();
|
||||
// _failureCounter = 0;
|
||||
// }
|
||||
//
|
||||
// static const maxFailedLogins = 3;
|
||||
// static const banTimeout = 180; // 3 mins
|
||||
// final banTimeoutKey = S.current.auth_store_ban_timeout;
|
||||
//
|
||||
// final UserService userService;
|
||||
// final WalletService walletService;
|
||||
//
|
||||
// final SharedPreferences sharedPreferences;
|
||||
//
|
||||
// @observable
|
||||
// AuthState state;
|
||||
//
|
||||
// @observable
|
||||
// int _failureCounter;
|
||||
//
|
||||
// @action
|
||||
// Future auth({String password}) async {
|
||||
// state = AuthenticationStateInitial();
|
||||
// final _banDuration = banDuration();
|
||||
//
|
||||
// if (_banDuration != null) {
|
||||
// state = AuthenticationBanned(
|
||||
// error: S.current.auth_store_banned_for + '${_banDuration.inMinutes}' + S.current.auth_store_banned_minutes);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// state = AuthenticationInProgress();
|
||||
// final isAuth = await userService.authenticate(password);
|
||||
//
|
||||
// if (isAuth) {
|
||||
// state = AuthenticatedSuccessfully();
|
||||
// _failureCounter = 0;
|
||||
// } else {
|
||||
// _failureCounter += 1;
|
||||
//
|
||||
// if (_failureCounter >= maxFailedLogins) {
|
||||
// final banDuration = await ban();
|
||||
// state = AuthenticationBanned(
|
||||
// error: S.current.auth_store_banned_for + '${banDuration.inMinutes}' + S.current.auth_store_banned_minutes);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// state = AuthenticationFailure(error: S.current.auth_store_incorrect_password);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Duration banDuration() {
|
||||
// final unbanTimestamp = sharedPreferences.getInt(banTimeoutKey);
|
||||
//
|
||||
// if (unbanTimestamp == null) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// final unbanTime = DateTime.fromMillisecondsSinceEpoch(unbanTimestamp);
|
||||
// final now = DateTime.now();
|
||||
//
|
||||
// if (now.isAfter(unbanTime)) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// return Duration(milliseconds: unbanTimestamp - now.millisecondsSinceEpoch);
|
||||
// }
|
||||
//
|
||||
// Future<Duration> ban() async {
|
||||
// final multiplier = _failureCounter - maxFailedLogins + 1;
|
||||
// final timeout = (multiplier * banTimeout) * 1000;
|
||||
// final unbanTimestamp = DateTime.now().millisecondsSinceEpoch + timeout;
|
||||
// await sharedPreferences.setInt(banTimeoutKey, unbanTimestamp);
|
||||
//
|
||||
// return Duration(milliseconds: timeout);
|
||||
// }
|
||||
//
|
||||
// @action
|
||||
// void biometricAuth() {
|
||||
// state = AuthenticatedSuccessfully();
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -30,8 +30,8 @@ abstract class AuthenticationStoreBase with Store {
|
||||
@observable
|
||||
AuthenticationState state;
|
||||
|
||||
@observable
|
||||
String errorMessage;
|
||||
// @observable
|
||||
// String errorMessage;
|
||||
|
||||
Future started() async {
|
||||
final canAuth = await userService.canAuthenticate();
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:mobx/mobx.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:cake_wallet/src/domain/services/wallet_list_service.dart';
|
||||
import 'package:cake_wallet/src/domain/common/mnemotic_item.dart';
|
||||
import 'package:cake_wallet/src/domain/common/mnemonic_item.dart';
|
||||
import 'package:cake_wallet/src/stores/wallet_restoration/wallet_restoration_state.dart';
|
||||
import 'package:cake_wallet/src/stores/authentication/authentication_store.dart';
|
||||
import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
|
||||
@@ -37,7 +37,7 @@ abstract class WalleRestorationStoreBase with Store {
|
||||
bool isValid;
|
||||
|
||||
@observable
|
||||
List<MnemoticItem> seed;
|
||||
List<MnemonicItem> seed;
|
||||
|
||||
@observable
|
||||
bool disabledState;
|
||||
@@ -79,35 +79,35 @@ abstract class WalleRestorationStoreBase with Store {
|
||||
}
|
||||
|
||||
@action
|
||||
void setSeed(List<MnemoticItem> seed) {
|
||||
void setSeed(List<MnemonicItem> seed) {
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
@action
|
||||
void validateSeed(List<MnemoticItem> seed) {
|
||||
final _seed = seed != null ? seed : this.seed;
|
||||
bool isValid = _seed != null ? _seed.length == 25 : false;
|
||||
|
||||
if (!isValid) {
|
||||
errorMessage = S.current.wallet_restoration_store_incorrect_seed_length;
|
||||
this.isValid = isValid;
|
||||
return;
|
||||
}
|
||||
|
||||
for (final item in _seed) {
|
||||
if (!item.isCorrect()) {
|
||||
isValid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isValid) {
|
||||
errorMessage = null;
|
||||
}
|
||||
|
||||
this.isValid = isValid;
|
||||
return;
|
||||
}
|
||||
// @action
|
||||
// void validateSeed(List<MnemonicItem> seed) {
|
||||
// final _seed = seed != null ? seed : this.seed;
|
||||
// bool isValid = _seed != null ? _seed.length == 25 : false;
|
||||
//
|
||||
// if (!isValid) {
|
||||
// errorMessage = S.current.wallet_restoration_store_incorrect_seed_length;
|
||||
// this.isValid = isValid;
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// for (final item in _seed) {
|
||||
// if (!item.isCorrect()) {
|
||||
// isValid = false;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (isValid) {
|
||||
// errorMessage = null;
|
||||
// }
|
||||
//
|
||||
// this.isValid = isValid;
|
||||
// return;
|
||||
// }
|
||||
|
||||
String _seedText() {
|
||||
return seed.fold('', (acc, item) => acc + ' ' + item.toString());
|
||||
|
||||
@@ -2,24 +2,24 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class BaseTextFormField extends StatelessWidget {
|
||||
BaseTextFormField({
|
||||
this.controller,
|
||||
this.keyboardType = TextInputType.text,
|
||||
this.textInputAction = TextInputAction.done,
|
||||
this.textAlign = TextAlign.start,
|
||||
this.autovalidate = false,
|
||||
this.hintText = '',
|
||||
this.maxLines = 1,
|
||||
this.inputFormatters,
|
||||
this.textColor,
|
||||
this.hintColor,
|
||||
this.borderColor,
|
||||
this.prefix,
|
||||
this.suffix,
|
||||
this.suffixIcon,
|
||||
this.enabled = true,
|
||||
this.validator
|
||||
});
|
||||
BaseTextFormField(
|
||||
{this.controller,
|
||||
this.keyboardType = TextInputType.text,
|
||||
this.textInputAction = TextInputAction.done,
|
||||
this.textAlign = TextAlign.start,
|
||||
this.autovalidate = false,
|
||||
this.hintText = '',
|
||||
this.maxLines = 1,
|
||||
this.inputFormatters,
|
||||
this.textColor,
|
||||
this.hintColor,
|
||||
this.borderColor,
|
||||
this.prefix,
|
||||
this.suffix,
|
||||
this.suffixIcon,
|
||||
this.enabled = true,
|
||||
this.validator,
|
||||
this.placeholderTextStyle});
|
||||
|
||||
final TextEditingController controller;
|
||||
final TextInputType keyboardType;
|
||||
@@ -37,6 +37,7 @@ class BaseTextFormField extends StatelessWidget {
|
||||
final Widget suffixIcon;
|
||||
final bool enabled;
|
||||
final FormFieldValidator<String> validator;
|
||||
final TextStyle placeholderTextStyle;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -50,32 +51,27 @@ class BaseTextFormField extends StatelessWidget {
|
||||
inputFormatters: inputFormatters,
|
||||
enabled: enabled,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
color: textColor ?? Theme.of(context).primaryTextTheme.title.color
|
||||
),
|
||||
fontSize: 16.0,
|
||||
color: textColor ?? Theme.of(context).primaryTextTheme.title.color),
|
||||
decoration: InputDecoration(
|
||||
prefix: prefix,
|
||||
suffix: suffix,
|
||||
suffixIcon: suffixIcon,
|
||||
hintStyle: TextStyle(
|
||||
color: hintColor ?? Theme.of(context).primaryTextTheme.caption.color,
|
||||
fontSize: 16
|
||||
),
|
||||
hintText: hintText,
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: borderColor ?? Theme.of(context).dividerColor,
|
||||
width: 1.0
|
||||
)
|
||||
),
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: borderColor ?? Theme.of(context).dividerColor,
|
||||
width: 1.0
|
||||
)
|
||||
)
|
||||
),
|
||||
prefix: prefix,
|
||||
suffix: suffix,
|
||||
suffixIcon: suffixIcon,
|
||||
hintStyle: placeholderTextStyle ??
|
||||
TextStyle(
|
||||
color: hintColor ??
|
||||
Theme.of(context).primaryTextTheme.caption.color,
|
||||
fontSize: 16),
|
||||
hintText: hintText,
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: borderColor ?? Theme.of(context).dividerColor,
|
||||
width: 1.0)),
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: borderColor ?? Theme.of(context).dividerColor,
|
||||
width: 1.0))),
|
||||
validator: validator,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,10 @@ import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/get_height_by_date.dart';
|
||||
|
||||
class BlockchainHeightWidget extends StatefulWidget {
|
||||
BlockchainHeightWidget({GlobalKey key}) : super(key: key);
|
||||
BlockchainHeightWidget({GlobalKey key, this.onHeightChange})
|
||||
: super(key: key);
|
||||
|
||||
final Function(int) onHeightChange;
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => BlockchainHeightState();
|
||||
@@ -13,15 +16,23 @@ class BlockchainHeightWidget extends StatefulWidget {
|
||||
class BlockchainHeightState extends State<BlockchainHeightWidget> {
|
||||
final dateController = TextEditingController();
|
||||
final restoreHeightController = TextEditingController();
|
||||
|
||||
int get height => _height;
|
||||
int _height = 0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
restoreHeightController.addListener(() => _height =
|
||||
restoreHeightController.text != null
|
||||
restoreHeightController.addListener(() {
|
||||
try {
|
||||
_changeHeight(restoreHeightController.text != null &&
|
||||
restoreHeightController.text.isNotEmpty
|
||||
? int.parse(restoreHeightController.text)
|
||||
: 0);
|
||||
} catch (_) {
|
||||
_changeHeight(0);
|
||||
}
|
||||
});
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@@ -38,21 +49,18 @@ class BlockchainHeightState extends State<BlockchainHeightWidget> {
|
||||
child: TextFormField(
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
color: Theme.of(context).primaryTextTheme.title.color
|
||||
),
|
||||
color: Theme.of(context).primaryTextTheme.title.color),
|
||||
controller: restoreHeightController,
|
||||
keyboardType: TextInputType.numberWithOptions(
|
||||
signed: false, decimal: false),
|
||||
decoration: InputDecoration(
|
||||
hintStyle: TextStyle(
|
||||
color: Theme.of(context).primaryTextTheme.caption.color,
|
||||
fontSize: 16
|
||||
),
|
||||
fontSize: 16),
|
||||
hintText: S.of(context).widgets_restore_from_blockheight,
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1.0)),
|
||||
color: Theme.of(context).dividerColor, width: 1.0)),
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
@@ -81,13 +89,14 @@ class BlockchainHeightState extends State<BlockchainHeightWidget> {
|
||||
child: TextFormField(
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
color: Theme.of(context).primaryTextTheme.title.color
|
||||
),
|
||||
color: Theme.of(context).primaryTextTheme.title.color),
|
||||
decoration: InputDecoration(
|
||||
hintStyle: TextStyle(
|
||||
color: Theme.of(context).primaryTextTheme.caption.color,
|
||||
fontSize: 16
|
||||
),
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.caption
|
||||
.color,
|
||||
fontSize: 16),
|
||||
hintText: S.of(context).widgets_restore_from_date,
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
@@ -113,7 +122,7 @@ class BlockchainHeightState extends State<BlockchainHeightWidget> {
|
||||
|
||||
Future _selectDate(BuildContext context) async {
|
||||
final now = DateTime.now();
|
||||
final DateTime date = await showDatePicker(
|
||||
final date = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: now.subtract(Duration(days: 1)),
|
||||
firstDate: DateTime(2014, DateTime.april),
|
||||
@@ -125,8 +134,13 @@ class BlockchainHeightState extends State<BlockchainHeightWidget> {
|
||||
setState(() {
|
||||
dateController.text = DateFormat('yyyy-MM-dd').format(date);
|
||||
restoreHeightController.text = '$height';
|
||||
_height = height;
|
||||
_changeHeight(height);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _changeHeight(int height) {
|
||||
_height = height;
|
||||
widget.onHeightChange?.call(height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
|
||||
import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
|
||||
|
||||
class SeedLanguageSelector extends StatefulWidget {
|
||||
SeedLanguageSelector({Key key, this.initialSelected}) : super(key: key);
|
||||
|
||||
final String initialSelected;
|
||||
|
||||
@override
|
||||
SeedLanguageSelectorState createState() =>
|
||||
SeedLanguageSelectorState(selected: initialSelected);
|
||||
}
|
||||
|
||||
class SeedLanguageSelectorState extends State<SeedLanguageSelector> {
|
||||
SeedLanguageSelectorState({this.selected});
|
||||
|
||||
final seedLocales = [
|
||||
S.current.seed_language_english,
|
||||
S.current.seed_language_chinese,
|
||||
S.current.seed_language_dutch,
|
||||
S.current.seed_language_german,
|
||||
S.current.seed_language_japanese,
|
||||
S.current.seed_language_portuguese,
|
||||
S.current.seed_language_russian,
|
||||
S.current.seed_language_spanish
|
||||
];
|
||||
String selected;
|
||||
final _pickerKey = GlobalKey<SeedLanguagePickerState>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SelectButton(
|
||||
image: null,
|
||||
text: seedLocales[seedLanguages.indexOf(selected)],
|
||||
color: Theme.of(context).accentTextTheme.title.backgroundColor,
|
||||
textColor: Theme.of(context).primaryTextTheme.title.color,
|
||||
onTap: () async {
|
||||
final selected = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (BuildContext context) =>
|
||||
SeedLanguagePicker(key: _pickerKey, selected: this.selected));
|
||||
setState(() => this.selected = selected);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+235
-256
@@ -1,94 +1,64 @@
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/mnemonics/english.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/mnemonics/chinese_simplified.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/mnemonics/dutch.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/mnemonics/german.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/mnemonics/japanese.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/mnemonics/portuguese.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/mnemonics/russian.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/mnemonics/spanish.dart';
|
||||
import 'package:cake_wallet/src/domain/common/mnemotic_item.dart';
|
||||
import 'package:cake_wallet/core/seed_validator.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/src/domain/common/mnemonic_item.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
|
||||
class SeedWidget extends StatefulWidget {
|
||||
SeedWidget({Key key, this.onMnemoticChange, this.onFinish, this.seedLanguage}) : super(key: key) {
|
||||
switch (seedLanguage) {
|
||||
case 'English':
|
||||
words = EnglishMnemonics.words;
|
||||
break;
|
||||
case 'Chinese (simplified)':
|
||||
words = ChineseSimplifiedMnemonics.words;
|
||||
break;
|
||||
case 'Dutch':
|
||||
words = DutchMnemonics.words;
|
||||
break;
|
||||
case 'German':
|
||||
words = GermanMnemonics.words;
|
||||
break;
|
||||
case 'Japanese':
|
||||
words = JapaneseMnemonics.words;
|
||||
break;
|
||||
case 'Portuguese':
|
||||
words = PortugueseMnemonics.words;
|
||||
break;
|
||||
case 'Russian':
|
||||
words = RussianMnemonics.words;
|
||||
break;
|
||||
case 'Spanish':
|
||||
words = SpanishMnemonics.words;
|
||||
break;
|
||||
default:
|
||||
words = EnglishMnemonics.words;
|
||||
}
|
||||
}
|
||||
SeedWidget(
|
||||
{Key key,
|
||||
this.maxLength,
|
||||
this.onMnemonicChange,
|
||||
this.onFinish,
|
||||
this.validator})
|
||||
: super(key: key);
|
||||
|
||||
final Function(List<MnemoticItem>) onMnemoticChange;
|
||||
final int maxLength;
|
||||
final Function(List<MnemonicItem>) onMnemonicChange;
|
||||
final Function() onFinish;
|
||||
final String seedLanguage;
|
||||
List<String> words;
|
||||
final SeedValidator validator;
|
||||
|
||||
@override
|
||||
SeedWidgetState createState() => SeedWidgetState();
|
||||
SeedWidgetState createState() => SeedWidgetState(maxLength: maxLength);
|
||||
}
|
||||
|
||||
class SeedWidgetState extends State<SeedWidget> {
|
||||
static const maxLength = 25;
|
||||
SeedWidgetState({this.maxLength});
|
||||
|
||||
List<MnemoticItem> items = <MnemoticItem>[];
|
||||
List<MnemonicItem> items = <MnemonicItem>[];
|
||||
final int maxLength;
|
||||
final _seedController = TextEditingController();
|
||||
final _seedTextFieldKey = GlobalKey();
|
||||
MnemoticItem selectedItem;
|
||||
MnemonicItem selectedItem;
|
||||
bool isValid;
|
||||
String errorMessage;
|
||||
|
||||
List<MnemoticItem> currentMnemotics;
|
||||
bool isCurrentMnemoticValid;
|
||||
List<MnemonicItem> currentMnemonics;
|
||||
bool isCurrentMnemonicValid;
|
||||
String _errorMessage;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
isValid = false;
|
||||
isCurrentMnemoticValid = false;
|
||||
isCurrentMnemonicValid = false;
|
||||
_seedController
|
||||
.addListener(() => changeCurrentMnemotic(_seedController.text));
|
||||
.addListener(() => changeCurrentMnemonic(_seedController.text));
|
||||
}
|
||||
|
||||
void addMnemotic(String text) {
|
||||
setState(() => items.add(MnemoticItem(
|
||||
text: text.trim().toLowerCase(), dic: widget.words)));
|
||||
void addMnemonic(String text) {
|
||||
setState(() => items.add(MnemonicItem(text: text.trim().toLowerCase())));
|
||||
_seedController.text = '';
|
||||
|
||||
if (widget.onMnemoticChange != null) {
|
||||
widget.onMnemoticChange(items);
|
||||
if (widget.onMnemonicChange != null) {
|
||||
widget.onMnemonicChange(items);
|
||||
}
|
||||
}
|
||||
|
||||
void mnemoticFromText(String text) {
|
||||
void mnemonicFromText(String text) {
|
||||
final splitted = text.split(' ');
|
||||
|
||||
if (splitted.length >= 2) {
|
||||
@@ -98,18 +68,18 @@ class SeedWidgetState extends State<SeedWidget> {
|
||||
}
|
||||
|
||||
if (selectedItem != null) {
|
||||
editTextOfSelectedMnemotic(text);
|
||||
editTextOfSelectedMnemonic(text);
|
||||
} else {
|
||||
addMnemotic(text);
|
||||
addMnemonic(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void selectMnemotic(MnemoticItem item) {
|
||||
void selectMnemonic(MnemonicItem item) {
|
||||
setState(() {
|
||||
selectedItem = item;
|
||||
currentMnemotics = [item];
|
||||
currentMnemonics = [item];
|
||||
|
||||
_seedController
|
||||
..text = item.text
|
||||
@@ -117,23 +87,23 @@ class SeedWidgetState extends State<SeedWidget> {
|
||||
});
|
||||
}
|
||||
|
||||
void onMnemoticTap(MnemoticItem item) {
|
||||
void onMnemonicTap(MnemonicItem item) {
|
||||
if (selectedItem == item) {
|
||||
setState(() => selectedItem = null);
|
||||
_seedController.text = '';
|
||||
return;
|
||||
}
|
||||
|
||||
selectMnemotic(item);
|
||||
selectMnemonic(item);
|
||||
}
|
||||
|
||||
void editTextOfSelectedMnemotic(String text) {
|
||||
void editTextOfSelectedMnemonic(String text) {
|
||||
setState(() => selectedItem.changeText(text));
|
||||
selectedItem = null;
|
||||
_seedController.text = '';
|
||||
|
||||
if (widget.onMnemoticChange != null) {
|
||||
widget.onMnemoticChange(items);
|
||||
if (widget.onMnemonicChange != null) {
|
||||
widget.onMnemonicChange(items);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,83 +113,77 @@ class SeedWidgetState extends State<SeedWidget> {
|
||||
selectedItem = null;
|
||||
_seedController.text = '';
|
||||
|
||||
if (widget.onMnemoticChange != null) {
|
||||
widget.onMnemoticChange(items);
|
||||
if (widget.onMnemonicChange != null) {
|
||||
widget.onMnemonicChange(items);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void invalidate() {
|
||||
setState(() => isValid = false);
|
||||
}
|
||||
void invalidate() => setState(() => isValid = false);
|
||||
|
||||
void validated() {
|
||||
setState(() => isValid = true);
|
||||
}
|
||||
void validated() => setState(() => isValid = true);
|
||||
|
||||
void setErrorMessage(String errorMessage) {
|
||||
setState(() => this.errorMessage = errorMessage);
|
||||
}
|
||||
void setErrorMessage(String errorMessage) =>
|
||||
setState(() => this.errorMessage = errorMessage);
|
||||
|
||||
void replaceText(String text) {
|
||||
setState(() => items = []);
|
||||
mnemoticFromText(text);
|
||||
mnemonicFromText(text);
|
||||
}
|
||||
|
||||
void changeCurrentMnemotic(String text) {
|
||||
void changeCurrentMnemonic(String text) {
|
||||
setState(() {
|
||||
final trimmedText = text.trim();
|
||||
final splitted = trimmedText.split(' ');
|
||||
_errorMessage = null;
|
||||
|
||||
if (text == null) {
|
||||
currentMnemotics = [];
|
||||
isCurrentMnemoticValid = false;
|
||||
currentMnemonics = [];
|
||||
isCurrentMnemonicValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
currentMnemotics = splitted
|
||||
.map((text) => MnemoticItem(text: text, dic: widget.words))
|
||||
.toList();
|
||||
currentMnemonics =
|
||||
splitted.map((text) => MnemonicItem(text: text)).toList();
|
||||
|
||||
bool isValid = true;
|
||||
var isValid = true;
|
||||
|
||||
for (final word in currentMnemotics) {
|
||||
isValid = word.isCorrect();
|
||||
for (final word in currentMnemonics) {
|
||||
isValid = widget.validator.isValid(word);
|
||||
|
||||
if (!isValid) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
isCurrentMnemoticValid = isValid;
|
||||
isCurrentMnemonicValid = isValid;
|
||||
});
|
||||
}
|
||||
|
||||
void saveCurrentMnemoticToItems() {
|
||||
void saveCurrentMnemonicToItems() {
|
||||
setState(() {
|
||||
if (selectedItem != null) {
|
||||
selectedItem.changeText(currentMnemotics.first.text.trim());
|
||||
selectedItem.changeText(currentMnemonics.first.text.trim());
|
||||
selectedItem = null;
|
||||
} else {
|
||||
items.addAll(currentMnemotics);
|
||||
items.addAll(currentMnemonics);
|
||||
}
|
||||
|
||||
currentMnemotics = [];
|
||||
currentMnemonics = [];
|
||||
_seedController.text = '';
|
||||
});
|
||||
}
|
||||
|
||||
void showErrorIfExist() {
|
||||
setState(() => _errorMessage =
|
||||
!isCurrentMnemoticValid ? S.current.incorrect_seed : null);
|
||||
!isCurrentMnemonicValid ? S.current.incorrect_seed : null);
|
||||
}
|
||||
|
||||
bool isSeedValid() {
|
||||
bool isValid;
|
||||
|
||||
for (final item in items) {
|
||||
isValid = item.isCorrect();
|
||||
isValid = widget.validator.isValid(item);
|
||||
|
||||
if (!isValid) {
|
||||
break;
|
||||
@@ -234,192 +198,207 @@ class SeedWidgetState extends State<SeedWidget> {
|
||||
return Container(
|
||||
child: Column(children: [
|
||||
Flexible(
|
||||
fit: FlexFit.tight,
|
||||
flex: 1,
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
padding: EdgeInsets.all(24),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(24),
|
||||
bottomRight: Radius.circular(24)
|
||||
fit: FlexFit.tight,
|
||||
flex: 1,
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
padding: EdgeInsets.all(24),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(24),
|
||||
bottomRight: Radius.circular(24)),
|
||||
color: Theme.of(context).accentTextTheme.title.backgroundColor),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
S.of(context).restore_active_seed,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color:
|
||||
Theme.of(context).primaryTextTheme.caption.color),
|
||||
),
|
||||
color: Theme.of(context).accentTextTheme.title.backgroundColor
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
S.of(context).restore_active_seed,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Theme.of(context).primaryTextTheme.caption.color
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 5),
|
||||
child: Wrap(
|
||||
children: items.map((item) {
|
||||
final isValid = item.isCorrect();
|
||||
final isSelected = selectedItem == item;
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 5),
|
||||
child: Wrap(
|
||||
children: items.map((item) {
|
||||
final isValid = widget.validator.isValid(item);
|
||||
final isSelected = selectedItem == item;
|
||||
|
||||
return InkWell(
|
||||
onTap: () => onMnemoticTap(item),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: isValid ? Colors.transparent : Palette.red),
|
||||
margin: EdgeInsets.only(right: 7, bottom: 8),
|
||||
child: Text(
|
||||
item.toString(),
|
||||
style: TextStyle(
|
||||
color: isValid
|
||||
? Theme.of(context).primaryTextTheme.title.color
|
||||
: Theme.of(context).primaryTextTheme.caption.color,
|
||||
fontSize: 16,
|
||||
fontWeight:
|
||||
isSelected ? FontWeight.w900 : FontWeight.w400,
|
||||
decoration: isSelected
|
||||
? TextDecoration.underline
|
||||
: TextDecoration.none),
|
||||
)),
|
||||
);
|
||||
}).toList(),)
|
||||
)
|
||||
],
|
||||
),
|
||||
return InkWell(
|
||||
onTap: () => onMnemonicTap(item),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: isValid
|
||||
? Colors.transparent
|
||||
: Palette.red),
|
||||
margin: EdgeInsets.only(right: 7, bottom: 8),
|
||||
child: Text(
|
||||
item.toString(),
|
||||
style: TextStyle(
|
||||
color: isValid
|
||||
? Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.title
|
||||
.color
|
||||
: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.caption
|
||||
.color,
|
||||
fontSize: 16,
|
||||
fontWeight: isSelected
|
||||
? FontWeight.w900
|
||||
: FontWeight.w400,
|
||||
decoration: isSelected
|
||||
? TextDecoration.underline
|
||||
: TextDecoration.none),
|
||||
)),
|
||||
);
|
||||
}).toList(),
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
fit: FlexFit.tight,
|
||||
flex: 2,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: 24, top: 48, right: 24, bottom: 24),
|
||||
padding:
|
||||
EdgeInsets.only(left: 24, top: 48, right: 24, bottom: 24),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
S.of(context).restore_new_seed,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).primaryTextTheme.title.color
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: TextFormField(
|
||||
key: _seedTextFieldKey,
|
||||
onFieldSubmitted: (text) => isCurrentMnemoticValid
|
||||
? saveCurrentMnemoticToItems()
|
||||
: null,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
color: Theme.of(context).primaryTextTheme.title.color
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
S.of(context).restore_new_seed,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color:
|
||||
Theme.of(context).primaryTextTheme.title.color),
|
||||
),
|
||||
controller: _seedController,
|
||||
textInputAction: TextInputAction.done,
|
||||
decoration: InputDecoration(
|
||||
suffixIcon: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: 145),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'${items.length}/${SeedWidgetState.maxLength}',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).primaryTextTheme.caption.color,
|
||||
fontSize: 14)),
|
||||
SizedBox(width: 10),
|
||||
InkWell(
|
||||
onTap: () async =>
|
||||
Clipboard.getData('text/plain').then(
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: TextFormField(
|
||||
key: _seedTextFieldKey,
|
||||
onFieldSubmitted: (text) => isCurrentMnemonicValid
|
||||
? saveCurrentMnemonicToItems()
|
||||
: null,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
color:
|
||||
Theme.of(context).primaryTextTheme.title.color),
|
||||
controller: _seedController,
|
||||
textInputAction: TextInputAction.done,
|
||||
decoration: InputDecoration(
|
||||
suffixIcon: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: 145),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: <Widget>[
|
||||
Text('${items.length}/$maxLength',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.caption
|
||||
.color,
|
||||
fontSize: 14)),
|
||||
SizedBox(width: 10),
|
||||
InkWell(
|
||||
onTap: () async =>
|
||||
Clipboard.getData('text/plain').then(
|
||||
(clipboard) =>
|
||||
replaceText(clipboard.text)),
|
||||
child: Container(
|
||||
height: 35,
|
||||
padding: EdgeInsets.all(7),
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
Theme.of(context).accentTextTheme.title.backgroundColor,
|
||||
borderRadius:
|
||||
BorderRadius.circular(10.0)),
|
||||
child: Text(
|
||||
S.of(context).paste,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).primaryTextTheme.title.color
|
||||
),
|
||||
)),
|
||||
)
|
||||
],
|
||||
replaceText(clipboard.text)),
|
||||
child: Container(
|
||||
height: 35,
|
||||
padding: EdgeInsets.all(7),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.title
|
||||
.backgroundColor,
|
||||
borderRadius:
|
||||
BorderRadius.circular(10.0)),
|
||||
child: Text(
|
||||
S.of(context).paste,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.title
|
||||
.color),
|
||||
)),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
hintStyle:
|
||||
TextStyle(
|
||||
color: Theme.of(context).primaryTextTheme.caption.color,
|
||||
fontSize: 16
|
||||
),
|
||||
hintText: S.of(context).restore_from_seed_placeholder,
|
||||
errorText: _errorMessage,
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).dividerColor, width: 1.0)),
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1.0))),
|
||||
enableInteractiveSelection: false,
|
||||
),
|
||||
)
|
||||
]),
|
||||
)
|
||||
),
|
||||
hintStyle: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.caption
|
||||
.color,
|
||||
fontSize: 16),
|
||||
hintText:
|
||||
S.of(context).restore_from_seed_placeholder,
|
||||
errorText: _errorMessage,
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1.0)),
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1.0))),
|
||||
enableInteractiveSelection: false,
|
||||
),
|
||||
)
|
||||
]),
|
||||
)),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(right: 8),
|
||||
child: PrimaryButton(
|
||||
onPressed: clear,
|
||||
text: S.of(context).clear,
|
||||
color: Colors.red,
|
||||
textColor: Colors.white,
|
||||
isDisabled: items.isEmpty,
|
||||
),
|
||||
)
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(right: 8),
|
||||
child: PrimaryButton(
|
||||
onPressed: clear,
|
||||
text: S.of(context).clear,
|
||||
color: Colors.red,
|
||||
textColor: Colors.white,
|
||||
isDisabled: items.isEmpty,
|
||||
),
|
||||
)),
|
||||
Flexible(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: 8),
|
||||
child: (selectedItem == null && items.length == maxLength)
|
||||
? PrimaryButton(
|
||||
text: S.of(context).restore_next,
|
||||
isDisabled: !isSeedValid(),
|
||||
onPressed: () => widget.onFinish != null
|
||||
? widget.onFinish()
|
||||
: null,
|
||||
color: Colors.green,
|
||||
textColor: Colors.white)
|
||||
text: S.of(context).restore_next,
|
||||
isDisabled: !isSeedValid(),
|
||||
onPressed: () => widget.onFinish != null
|
||||
? widget.onFinish()
|
||||
: null,
|
||||
color: Colors.green,
|
||||
textColor: Colors.white)
|
||||
: PrimaryButton(
|
||||
text: selectedItem != null
|
||||
? S.of(context).save
|
||||
: S.of(context).add_new_word,
|
||||
onPressed: () => isCurrentMnemoticValid
|
||||
? saveCurrentMnemoticToItems()
|
||||
: null,
|
||||
onDisabledPressed: () => showErrorIfExist(),
|
||||
isDisabled: !isCurrentMnemoticValid,
|
||||
color: Colors.green,
|
||||
textColor: Colors.white),
|
||||
text: selectedItem != null
|
||||
? S.of(context).save
|
||||
: S.of(context).add_new_word,
|
||||
onPressed: () => isCurrentMnemonicValid
|
||||
? saveCurrentMnemonicToItems()
|
||||
: null,
|
||||
onDisabledPressed: () => showErrorIfExist(),
|
||||
isDisabled: !isCurrentMnemonicValid,
|
||||
color: Colors.green,
|
||||
textColor: Colors.white),
|
||||
),
|
||||
)
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user