mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-31 16:09:49 +00:00
TMP
This commit is contained in:
parent
04e7c18841
commit
f9cc21478a
16 changed files with 796 additions and 303 deletions
|
@ -219,6 +219,8 @@ extern "C"
|
||||||
|
|
||||||
bool create_wallet(char *path, char *password, char *language, int32_t networkType, char *error)
|
bool create_wallet(char *path, char *password, char *language, int32_t networkType, char *error)
|
||||||
{
|
{
|
||||||
|
Monero::WalletManagerFactory::setLogLevel(4);
|
||||||
|
|
||||||
Monero::NetworkType _networkType = static_cast<Monero::NetworkType>(networkType);
|
Monero::NetworkType _networkType = static_cast<Monero::NetworkType>(networkType);
|
||||||
Monero::WalletManager *walletManager = Monero::WalletManagerFactory::getWalletManager();
|
Monero::WalletManager *walletManager = Monero::WalletManagerFactory::getWalletManager();
|
||||||
Monero::Wallet *wallet = walletManager->createWallet(path, password, language, _networkType);
|
Monero::Wallet *wallet = walletManager->createWallet(path, password, language, _networkType);
|
||||||
|
@ -228,9 +230,9 @@ extern "C"
|
||||||
|
|
||||||
wallet->statusWithErrorString(status, errorString);
|
wallet->statusWithErrorString(status, errorString);
|
||||||
|
|
||||||
if (status != Monero::Wallet::Status_Ok)
|
if (wallet->status() != Monero::Wallet::Status_Ok)
|
||||||
{
|
{
|
||||||
error = strdup(errorString.c_str());
|
error = strdup(wallet->errorString().c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,7 +256,7 @@ extern "C"
|
||||||
|
|
||||||
wallet->statusWithErrorString(status, errorString);
|
wallet->statusWithErrorString(status, errorString);
|
||||||
|
|
||||||
if (status != Monero::Wallet::Status_Ok)
|
if (status != Monero::Wallet::Status_Ok || !errorString.empty())
|
||||||
{
|
{
|
||||||
error = strdup(errorString.c_str());
|
error = strdup(errorString.c_str());
|
||||||
return false;
|
return false;
|
||||||
|
@ -282,7 +284,7 @@ extern "C"
|
||||||
|
|
||||||
wallet->statusWithErrorString(status, errorString);
|
wallet->statusWithErrorString(status, errorString);
|
||||||
|
|
||||||
if (status != Monero::Wallet::Status_Ok)
|
if (status != Monero::Wallet::Status_Ok || !errorString.empty())
|
||||||
{
|
{
|
||||||
error = strdup(errorString.c_str());
|
error = strdup(errorString.c_str());
|
||||||
return false;
|
return false;
|
||||||
|
@ -349,11 +351,13 @@ extern "C"
|
||||||
|
|
||||||
uint64_t get_full_balance(uint32_t account_index)
|
uint64_t get_full_balance(uint32_t account_index)
|
||||||
{
|
{
|
||||||
|
// return 0;
|
||||||
return get_current_wallet()->balance(account_index);
|
return get_current_wallet()->balance(account_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t get_unlocked_balance(uint32_t account_index)
|
uint64_t get_unlocked_balance(uint32_t account_index)
|
||||||
{
|
{
|
||||||
|
// return 0;
|
||||||
return get_current_wallet()->unlockedBalance(account_index);
|
return get_current_wallet()->unlockedBalance(account_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -681,6 +685,7 @@ extern "C"
|
||||||
void on_startup()
|
void on_startup()
|
||||||
{
|
{
|
||||||
Monero::Utils::onStartup();
|
Monero::Utils::onStartup();
|
||||||
|
Monero::WalletManagerFactory::setLogLevel(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rescan_blockchain()
|
void rescan_blockchain()
|
||||||
|
|
|
@ -2,4 +2,7 @@ class WalletCreationException implements Exception {
|
||||||
WalletCreationException({this.message});
|
WalletCreationException({this.message});
|
||||||
|
|
||||||
final String message;
|
final String message;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => message;
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
import 'dart:ffi';
|
import 'dart:ffi';
|
||||||
|
import 'package:cw_monero/wallet.dart';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:cw_monero/convert_utf8_to_string.dart';
|
import 'package:cw_monero/convert_utf8_to_string.dart';
|
||||||
|
@ -49,6 +50,8 @@ void createWalletSync(
|
||||||
throw WalletCreationException(
|
throw WalletCreationException(
|
||||||
message: convertUTF8ToString(pointer: errorMessagePointer));
|
message: convertUTF8ToString(pointer: errorMessagePointer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setupNodeSync(address: "node.moneroworld.com:18089");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isWalletExistSync({String path}) {
|
bool isWalletExistSync({String path}) {
|
||||||
|
|
|
@ -354,7 +354,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 4;
|
CURRENT_PROJECT_VERSION = 5;
|
||||||
DEVELOPMENT_TEAM = 32J6BB6VUS;
|
DEVELOPMENT_TEAM = 32J6BB6VUS;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
|
@ -493,7 +493,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 4;
|
CURRENT_PROJECT_VERSION = 5;
|
||||||
DEVELOPMENT_TEAM = 32J6BB6VUS;
|
DEVELOPMENT_TEAM = 32J6BB6VUS;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
|
@ -526,7 +526,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 4;
|
CURRENT_PROJECT_VERSION = 5;
|
||||||
DEVELOPMENT_TEAM = 32J6BB6VUS;
|
DEVELOPMENT_TEAM = 32J6BB6VUS;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
|
|
|
@ -137,6 +137,11 @@ Future<void> ios_migrate_wallet_passwords() async {
|
||||||
final walletsDir = Directory('${appDocDir.path}/wallets');
|
final walletsDir = Directory('${appDocDir.path}/wallets');
|
||||||
final moneroWalletsDir = Directory('${walletsDir.path}/monero');
|
final moneroWalletsDir = Directory('${walletsDir.path}/monero');
|
||||||
|
|
||||||
|
if (!moneroWalletsDir.existsSync() || moneroWalletsDir.listSync().isEmpty) {
|
||||||
|
await prefs.setBool('ios_migration_wallet_passwords_completed', true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
moneroWalletsDir.listSync().forEach((item) async {
|
moneroWalletsDir.listSync().forEach((item) async {
|
||||||
try {
|
try {
|
||||||
if (item is Directory) {
|
if (item is Directory) {
|
||||||
|
|
|
@ -95,7 +95,7 @@ Future<void> initialSetup(
|
||||||
tradesSource: tradesSource,
|
tradesSource: tradesSource,
|
||||||
templates: templates,
|
templates: templates,
|
||||||
exchangeTemplates: exchangeTemplates);
|
exchangeTemplates: exchangeTemplates);
|
||||||
await bootstrap(navigatorKey);
|
bootstrap(navigatorKey);
|
||||||
monero_wallet.onStartup();
|
monero_wallet.onStartup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ class MoneroWalletService extends WalletService<
|
||||||
return wallet;
|
return wallet;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// TODO: Implement Exception for wallet list service.
|
// TODO: Implement Exception for wallet list service.
|
||||||
print('MoneroWalletsManager Error: $e');
|
print('MoneroWalletsManager Error: ${e.toString()}');
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,22 +8,25 @@ import 'package:cake_wallet/store/authentication_store.dart';
|
||||||
ReactionDisposer _onAuthenticationStateChange;
|
ReactionDisposer _onAuthenticationStateChange;
|
||||||
|
|
||||||
void startAuthenticationStateChange(AuthenticationStore authenticationStore,
|
void startAuthenticationStateChange(AuthenticationStore authenticationStore,
|
||||||
GlobalKey<NavigatorState> navigatorKey) {
|
@required GlobalKey<NavigatorState> navigatorKey) {
|
||||||
_onAuthenticationStateChange ??= autorun((_) async {
|
_onAuthenticationStateChange ??= autorun((_) async {
|
||||||
final state = authenticationStore.state;
|
final state = authenticationStore.state;
|
||||||
|
|
||||||
if (state == AuthenticationState.installed) {
|
if (state == AuthenticationState.installed) {
|
||||||
await loadCurrentWallet();
|
await loadCurrentWallet();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == AuthenticationState.allowed) {
|
if (state == AuthenticationState.allowed) {
|
||||||
await navigatorKey.currentState
|
await navigatorKey.currentState
|
||||||
.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false);
|
.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == AuthenticationState.denied) {
|
if (state == AuthenticationState.denied) {
|
||||||
await navigatorKey.currentState
|
await navigatorKey.currentState
|
||||||
.pushNamedAndRemoveUntil(Routes.welcome, (_) => false);
|
.pushNamedAndRemoveUntil(Routes.welcome, (_) => false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ class Router {
|
||||||
return CupertinoPageRoute<void>(
|
return CupertinoPageRoute<void>(
|
||||||
builder: (_) => getIt.get<SetupPinCodePage>(
|
builder: (_) => getIt.get<SetupPinCodePage>(
|
||||||
param1: (BuildContext context, dynamic _) =>
|
param1: (BuildContext context, dynamic _) =>
|
||||||
Navigator.pushNamed(context, Routes.newWalletType)),
|
Navigator.pushNamed(context, Routes.newWallet)),
|
||||||
fullscreenDialog: true);
|
fullscreenDialog: true);
|
||||||
|
|
||||||
case Routes.newWalletType:
|
case Routes.newWalletType:
|
||||||
|
@ -128,7 +128,7 @@ class Router {
|
||||||
return CupertinoPageRoute<void>(
|
return CupertinoPageRoute<void>(
|
||||||
builder: (_) => getIt.get<SetupPinCodePage>(
|
builder: (_) => getIt.get<SetupPinCodePage>(
|
||||||
param1: (BuildContext context, dynamic _) =>
|
param1: (BuildContext context, dynamic _) =>
|
||||||
Navigator.pushNamed(context, Routes.restoreWalletType)),
|
Navigator.pushNamed(context, Routes.restoreWalletFromSeed)),
|
||||||
fullscreenDialog: true);
|
fullscreenDialog: true);
|
||||||
|
|
||||||
case Routes.seed:
|
case Routes.seed:
|
||||||
|
@ -137,15 +137,15 @@ class Router {
|
||||||
getIt.get<WalletSeedPage>(param1: settings.arguments as bool));
|
getIt.get<WalletSeedPage>(param1: settings.arguments as bool));
|
||||||
|
|
||||||
case Routes.restoreWalletFromSeed:
|
case Routes.restoreWalletFromSeed:
|
||||||
final args = settings.arguments as List<dynamic>;
|
// final args = settings.arguments as List<dynamic>;
|
||||||
final type = args.first as WalletType;
|
final type = WalletType.monero; //args.first as WalletType;
|
||||||
final language = type == WalletType.monero
|
// final language = type == WalletType.monero
|
||||||
? args[1] as String
|
// ? args[1] as String
|
||||||
: LanguageList.english;
|
// : LanguageList.english;
|
||||||
|
|
||||||
return CupertinoPageRoute<void>(
|
return CupertinoPageRoute<void>(
|
||||||
builder: (_) =>
|
builder: (_) =>
|
||||||
RestoreWalletFromSeedPage(type: type, language: language));
|
RestoreWalletFromSeedPage(type: type));
|
||||||
|
|
||||||
case Routes.restoreWalletFromKeys:
|
case Routes.restoreWalletFromKeys:
|
||||||
final args = settings.arguments as List<dynamic>;
|
final args = settings.arguments as List<dynamic>;
|
||||||
|
|
83
lib/src/screens/restore/restore_from_keys.dart
Normal file
83
lib/src/screens/restore/restore_from_keys.dart
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||||
|
|
||||||
|
class RestoreFromKeysFrom extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_RestoreFromKeysFromState createState() => _RestoreFromKeysFromState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
final _blockchainHeightKey = GlobalKey<BlockchainHeightState>();
|
||||||
|
final _nameController = TextEditingController();
|
||||||
|
final _addressController = TextEditingController();
|
||||||
|
final _viewKeyController = TextEditingController();
|
||||||
|
final _spendKeyController = TextEditingController();
|
||||||
|
final _wifController = TextEditingController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
// _nameController.addListener(() =>
|
||||||
|
// widget.walletRestorationFromKeysVM.name = _nameController.text);
|
||||||
|
// _addressController.addListener(() =>
|
||||||
|
// widget.walletRestorationFromKeysVM.address = _addressController.text);
|
||||||
|
// _viewKeyController.addListener(() =>
|
||||||
|
// widget.walletRestorationFromKeysVM.viewKey = _viewKeyController.text);
|
||||||
|
// _spendKeyController.addListener(() =>
|
||||||
|
// widget.walletRestorationFromKeysVM.spendKey = _spendKeyController.text);
|
||||||
|
// _wifController.addListener(() =>
|
||||||
|
// widget.walletRestorationFromKeysVM.wif = _wifController.text);
|
||||||
|
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_nameController.dispose();
|
||||||
|
_addressController.dispose();
|
||||||
|
_viewKeyController.dispose();
|
||||||
|
_spendKeyController.dispose();
|
||||||
|
_wifController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.only(left: 24, right: 24),
|
||||||
|
child: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Column(children: <Widget>[
|
||||||
|
BaseTextFormField(
|
||||||
|
controller: _addressController,
|
||||||
|
keyboardType: TextInputType.multiline,
|
||||||
|
maxLines: null,
|
||||||
|
hintText: S.of(context).restore_address,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.only(top: 20.0),
|
||||||
|
child: BaseTextFormField(
|
||||||
|
controller: _viewKeyController,
|
||||||
|
hintText: S.of(context).restore_view_key_private,
|
||||||
|
)),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.only(top: 20.0),
|
||||||
|
child: BaseTextFormField(
|
||||||
|
controller: _spendKeyController,
|
||||||
|
hintText: S.of(context).restore_spend_key_private,
|
||||||
|
)),
|
||||||
|
BlockchainHeightWidget(
|
||||||
|
key: _blockchainHeightKey,
|
||||||
|
onHeightChange: (height) {
|
||||||
|
// widget.walletRestorationFromKeysVM.height = height;
|
||||||
|
print(height);
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,11 @@
|
||||||
|
import 'package:cake_wallet/src/screens/restore/restore_from_keys.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/blockchain_height_widget.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/utils/show_pop_up.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
|
@ -7,48 +15,162 @@ import 'package:cake_wallet/src/widgets/seed_widget.dart';
|
||||||
import 'package:cake_wallet/entities/wallet_type.dart';
|
import 'package:cake_wallet/entities/wallet_type.dart';
|
||||||
import 'package:cake_wallet/core/seed_validator.dart';
|
import 'package:cake_wallet/core/seed_validator.dart';
|
||||||
import 'package:cake_wallet/core/mnemonic_length.dart';
|
import 'package:cake_wallet/core/mnemonic_length.dart';
|
||||||
|
import 'package:smooth_page_indicator/smooth_page_indicator.dart';
|
||||||
|
|
||||||
class RestoreWalletFromSeedPage extends BasePage {
|
class RestoreWalletFromSeedPage extends BasePage {
|
||||||
RestoreWalletFromSeedPage({@required this.type, @required this.language});
|
RestoreWalletFromSeedPage({@required this.type});
|
||||||
|
|
||||||
final WalletType type;
|
final WalletType type;
|
||||||
final String language;
|
final String language = 'en';
|
||||||
final formKey = GlobalKey<_RestoreFromSeedFormState>();
|
|
||||||
|
// final formKey = GlobalKey<_RestoreFromSeedFormState>();
|
||||||
|
// final formKey = GlobalKey<_RestoreFromSeedFormState>();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get title => S.current.restore_title_from_seed;
|
String get title => S.current.restore_title_from_seed;
|
||||||
|
|
||||||
@override
|
final controller = PageController(initialPage: 0);
|
||||||
Color get titleColor => Colors.white;
|
|
||||||
|
Widget _page(BuildContext context, int index) {
|
||||||
|
if (_pages == null || _pages.isEmpty) {
|
||||||
|
_setPages(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _pages[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
int _pageLength(BuildContext context) {
|
||||||
|
if (_pages == null || _pages.isEmpty) {
|
||||||
|
_setPages(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _pages.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _setPages(BuildContext context) {
|
||||||
|
_pages = <Widget>[
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.only(left: 25, right: 25),
|
||||||
|
child: Column(children: [
|
||||||
|
SeedWidget(
|
||||||
|
maxLength: mnemonicLength(WalletType.monero),
|
||||||
|
onMnemonicChange: (seed) => null,
|
||||||
|
onFinish: () => null,
|
||||||
|
// Navigator.of(context).pushNamed(
|
||||||
|
// Routes.restoreWalletFromSeedDetails,
|
||||||
|
// arguments: [WalletType.monero, '', '']),
|
||||||
|
validator: SeedValidator(type: WalletType.monero, language: ''),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () async {
|
||||||
|
final selected = await showPopUp<String>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) =>
|
||||||
|
SeedLanguagePicker(selected: 'English')); //key: _pickerKey
|
||||||
|
print('Seletec $selected');
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
color: Colors.transparent,
|
||||||
|
padding: EdgeInsets.only(top: 20.0),
|
||||||
|
child: IgnorePointer(child: BaseTextFormField(
|
||||||
|
enableInteractiveSelection: false,
|
||||||
|
readOnly: true,
|
||||||
|
hintText: 'Language',
|
||||||
|
initialValue: 'English (Seed language)')))),
|
||||||
|
BlockchainHeightWidget(
|
||||||
|
// key: _blockchainHeightKey,
|
||||||
|
onHeightChange: (height) {
|
||||||
|
// widget.walletRestorationFromKeysVM.height = height;
|
||||||
|
print(height);
|
||||||
|
})
|
||||||
|
])),
|
||||||
|
RestoreFromKeysFrom(),
|
||||||
|
// Container(color: Colors.yellow)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Widget> _pages;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color get backgroundLightColor => Colors.transparent;
|
Widget body(BuildContext context) {
|
||||||
|
return Column(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||||
|
Expanded(
|
||||||
|
child: PageView.builder(
|
||||||
|
onPageChanged: (page) {
|
||||||
|
print('Page index $page');
|
||||||
|
},
|
||||||
|
controller: controller,
|
||||||
|
itemCount: _pageLength(context),
|
||||||
|
itemBuilder: (context, index) => _page(context, index))),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 10),
|
||||||
|
child: SmoothPageIndicator(
|
||||||
|
controller: controller,
|
||||||
|
count: _pageLength(context),
|
||||||
|
effect: ColorTransitionEffect(
|
||||||
|
spacing: 6.0,
|
||||||
|
radius: 6.0,
|
||||||
|
dotWidth: 6.0,
|
||||||
|
dotHeight: 6.0,
|
||||||
|
dotColor: Theme.of(context).hintColor.withOpacity(0.5),
|
||||||
|
activeDotColor: Theme.of(context).hintColor),
|
||||||
|
)),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 20, bottom: 40, left: 25, right: 25),
|
||||||
|
child: PrimaryButton(
|
||||||
|
text: S.of(context).restore_recover,
|
||||||
|
isDisabled: false,
|
||||||
|
onPressed: () => null,
|
||||||
|
color: Theme.of(context).accentTextTheme.body2.color,
|
||||||
|
textColor: Colors.white)),
|
||||||
|
]);
|
||||||
|
|
||||||
@override
|
// return GestureDetector(
|
||||||
Color get backgroundDarkColor => Colors.transparent;
|
// onTap: () =>
|
||||||
|
// SystemChannels.textInput.invokeMethod<void>('TextInput.hide'),
|
||||||
@override
|
// child: ScrollableWithBottomSection(
|
||||||
bool get resizeToAvoidBottomPadding => false;
|
// bottomSection: Column(children: [
|
||||||
|
// GestureDetector(
|
||||||
@override
|
// onTap: () {},
|
||||||
Widget body(BuildContext context) =>
|
// child: Text('Switch to restore from keys',
|
||||||
RestoreFromSeedForm(key: formKey, type: type, language: language,
|
// style: TextStyle(fontSize: 15, color: Theme.of(context).hintColor))),
|
||||||
leading: leading(context), middle: middle(context));
|
// SizedBox(height: 30),
|
||||||
|
// PrimaryButton(
|
||||||
@override
|
// text: S.of(context).restore_next,
|
||||||
Widget build(BuildContext context) {
|
// isDisabled: false,
|
||||||
return Scaffold(
|
// onPressed: () => null,
|
||||||
resizeToAvoidBottomPadding: resizeToAvoidBottomPadding,
|
// color: Theme.of(context).accentTextTheme.body2.color,
|
||||||
body: Container(
|
// textColor: Colors.white)
|
||||||
color: Theme.of(context).backgroundColor,
|
// ]),
|
||||||
child: body(context)
|
// contentPadding: EdgeInsets.only(bottom: 24),
|
||||||
)
|
// content: Container(
|
||||||
);
|
// padding: EdgeInsets.only(left: 25, right: 25),
|
||||||
|
// child: Column(children: [
|
||||||
|
// SeedWidget(
|
||||||
|
// maxLength: mnemonicLength(type),
|
||||||
|
// onMnemonicChange: (seed) => null,
|
||||||
|
// onFinish: () => Navigator.of(context).pushNamed(
|
||||||
|
// Routes.restoreWalletFromSeedDetails,
|
||||||
|
// arguments: [type, language, '']),
|
||||||
|
// validator: SeedValidator(type: type, language: language),
|
||||||
|
// ),
|
||||||
|
// // SizedBox(height: 15),
|
||||||
|
// // BaseTextFormField(hintText: 'Language', initialValue: 'English'),
|
||||||
|
// BlockchainHeightWidget(
|
||||||
|
// // key: _blockchainHeightKey,
|
||||||
|
// onHeightChange: (height) {
|
||||||
|
// // widget.walletRestorationFromKeysVM.height = height;
|
||||||
|
// print(height);
|
||||||
|
// })
|
||||||
|
// ]))),
|
||||||
|
// );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RestoreFromSeedForm extends StatefulWidget {
|
class RestoreFromSeedForm extends StatefulWidget {
|
||||||
RestoreFromSeedForm({Key key, this.type, this.language, this.leading, this.middle}) : super(key: key);
|
RestoreFromSeedForm(
|
||||||
|
{Key key, this.type, this.language, this.leading, this.middle})
|
||||||
|
: super(key: key);
|
||||||
final WalletType type;
|
final WalletType type;
|
||||||
final String language;
|
final String language;
|
||||||
final Widget leading;
|
final Widget leading;
|
||||||
|
@ -59,27 +181,46 @@ class RestoreFromSeedForm extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _RestoreFromSeedFormState extends State<RestoreFromSeedForm> {
|
class _RestoreFromSeedFormState extends State<RestoreFromSeedForm> {
|
||||||
final _seedKey = GlobalKey<SeedWidgetState>();
|
// final _seedKey = GlobalKey<SeedWidgetState>();
|
||||||
|
|
||||||
String mnemonic() => _seedKey.currentState.items.map((e) => e.text).join(' ');
|
String mnemonic() =>
|
||||||
|
''; // _seedKey.currentState.items.map((e) => e.text).join(' ');
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () =>
|
onTap: () =>
|
||||||
SystemChannels.textInput.invokeMethod<void>('TextInput.hide'),
|
SystemChannels.textInput.invokeMethod<void>('TextInput.hide'),
|
||||||
child: SeedWidget(
|
child: Container(
|
||||||
key: _seedKey,
|
padding: EdgeInsets.only(left: 25, right: 25),
|
||||||
maxLength: mnemonicLength(widget.type),
|
// color: Colors.blue,
|
||||||
onMnemonicChange: (seed) => null,
|
// height: 300,
|
||||||
onFinish: () => Navigator.of(context).pushNamed(
|
child: Column(children: [
|
||||||
Routes.restoreWalletFromSeedDetails,
|
SeedWidget(
|
||||||
arguments: [widget.type, widget.language, mnemonic()]),
|
// key: _seedKey,
|
||||||
leading: widget.leading,
|
maxLength: mnemonicLength(widget.type),
|
||||||
middle: widget.middle,
|
onMnemonicChange: (seed) => null,
|
||||||
validator:
|
onFinish: () => Navigator.of(context).pushNamed(
|
||||||
SeedValidator(type: widget.type, language: widget.language),
|
Routes.restoreWalletFromSeedDetails,
|
||||||
),
|
arguments: [widget.type, widget.language, mnemonic()]),
|
||||||
|
leading: widget.leading,
|
||||||
|
middle: widget.middle,
|
||||||
|
validator:
|
||||||
|
SeedValidator(type: widget.type, language: widget.language),
|
||||||
|
),
|
||||||
|
BlockchainHeightWidget(
|
||||||
|
// key: _blockchainHeightKey,
|
||||||
|
onHeightChange: (height) {
|
||||||
|
// widget.walletRestorationFromKeysVM.height = height;
|
||||||
|
print(height);
|
||||||
|
}),
|
||||||
|
Container(
|
||||||
|
color: Colors.green,
|
||||||
|
width: 100,
|
||||||
|
height: 56,
|
||||||
|
child: BaseTextFormField(
|
||||||
|
hintText: 'Language', initialValue: 'English')),
|
||||||
|
])),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,13 +35,15 @@ class SeedLanguageFormState extends State<SeedLanguageForm> {
|
||||||
static const aspectRatioImage = 1.22;
|
static const aspectRatioImage = 1.22;
|
||||||
|
|
||||||
final walletNameImage = Image.asset('assets/images/wallet_name.png');
|
final walletNameImage = Image.asset('assets/images/wallet_name.png');
|
||||||
final walletNameLightImage = Image.asset('assets/images/wallet_name_light.png');
|
final walletNameLightImage =
|
||||||
|
Image.asset('assets/images/wallet_name_light.png');
|
||||||
final _languageSelectorKey = GlobalKey<SeedLanguageSelectorState>();
|
final _languageSelectorKey = GlobalKey<SeedLanguageSelectorState>();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final walletImage = getIt.get<SettingsStore>().isDarkTheme
|
final walletImage = getIt.get<SettingsStore>().isDarkTheme
|
||||||
? walletNameImage : walletNameLightImage;
|
? walletNameImage
|
||||||
|
: walletNameLightImage;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: EdgeInsets.only(top: 24),
|
padding: EdgeInsets.only(top: 24),
|
||||||
|
@ -78,8 +80,8 @@ class SeedLanguageFormState extends State<SeedLanguageForm> {
|
||||||
bottomSection: Observer(
|
bottomSection: Observer(
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return PrimaryButton(
|
return PrimaryButton(
|
||||||
onPressed: () => widget
|
onPressed: () => widget.onConfirm(
|
||||||
.onConfirm(context, _languageSelectorKey.currentState.selected),
|
context, _languageSelectorKey.currentState.selected),
|
||||||
text: S.of(context).seed_language_next,
|
text: S.of(context).seed_language_next,
|
||||||
color: Colors.green,
|
color: Colors.green,
|
||||||
textColor: Colors.white);
|
textColor: Colors.white);
|
||||||
|
|
|
@ -175,7 +175,7 @@ class WalletListBodyState extends State<WalletListBody> {
|
||||||
SizedBox(height: 10.0),
|
SizedBox(height: 10.0),
|
||||||
PrimaryImageButton(
|
PrimaryImageButton(
|
||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
Navigator.of(context).pushNamed(Routes.restoreWalletType),
|
Navigator.of(context).pushNamed(Routes.restoreWalletFromSeed),
|
||||||
image: restoreWalletImage,
|
image: restoreWalletImage,
|
||||||
text: S.of(context).wallet_list_restore_wallet,
|
text: S.of(context).wallet_list_restore_wallet,
|
||||||
color: Theme.of(context).accentTextTheme.caption.color,
|
color: Theme.of(context).accentTextTheme.caption.color,
|
||||||
|
|
|
@ -103,7 +103,7 @@ class WelcomePage extends BasePage {
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(top: 24),
|
padding: EdgeInsets.only(top: 24),
|
||||||
child: PrimaryImageButton(
|
child: PrimaryImageButton(
|
||||||
onPressed: () => Navigator.pushNamed(context, Routes.newWallet),
|
onPressed: () => Navigator.pushNamed(context, Routes.newWalletFromWelcome),
|
||||||
image: newWalletImage,
|
image: newWalletImage,
|
||||||
text: S.of(context).create_new,
|
text: S.of(context).create_new,
|
||||||
color: Theme.of(context).accentTextTheme.subtitle.decorationColor,
|
color: Theme.of(context).accentTextTheme.subtitle.decorationColor,
|
||||||
|
@ -113,7 +113,7 @@ class WelcomePage extends BasePage {
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(top: 10),
|
padding: EdgeInsets.only(top: 10),
|
||||||
child: PrimaryImageButton(
|
child: PrimaryImageButton(
|
||||||
onPressed: () => Navigator.pushNamed(context, Routes.restoreWalletOptions),
|
onPressed: () => Navigator.pushNamed(context, Routes.restoreWalletOptionsFromWelcome),
|
||||||
image: restoreWalletImage,
|
image: restoreWalletImage,
|
||||||
text: S.of(context).restore_wallet,
|
text: S.of(context).restore_wallet,
|
||||||
color: Theme.of(context).accentTextTheme.caption.color,
|
color: Theme.of(context).accentTextTheme.caption.color,
|
||||||
|
|
|
@ -19,11 +19,14 @@ class BaseTextFormField extends StatelessWidget {
|
||||||
this.suffix,
|
this.suffix,
|
||||||
this.suffixIcon,
|
this.suffixIcon,
|
||||||
this.enabled = true,
|
this.enabled = true,
|
||||||
|
this.readOnly = false,
|
||||||
|
this.enableInteractiveSelection = true,
|
||||||
this.validator,
|
this.validator,
|
||||||
this.textStyle,
|
this.textStyle,
|
||||||
this.placeholderTextStyle,
|
this.placeholderTextStyle,
|
||||||
this.maxLength,
|
this.maxLength,
|
||||||
this.focusNode});
|
this.focusNode,
|
||||||
|
this.initialValue});
|
||||||
|
|
||||||
final TextEditingController controller;
|
final TextEditingController controller;
|
||||||
final TextInputType keyboardType;
|
final TextInputType keyboardType;
|
||||||
|
@ -46,10 +49,16 @@ class BaseTextFormField extends StatelessWidget {
|
||||||
final TextStyle textStyle;
|
final TextStyle textStyle;
|
||||||
final int maxLength;
|
final int maxLength;
|
||||||
final FocusNode focusNode;
|
final FocusNode focusNode;
|
||||||
|
final bool readOnly;
|
||||||
|
final bool enableInteractiveSelection;
|
||||||
|
String initialValue;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return TextFormField(
|
return TextFormField(
|
||||||
|
enableInteractiveSelection: enableInteractiveSelection,
|
||||||
|
readOnly: readOnly,
|
||||||
|
initialValue: initialValue,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
controller: controller,
|
controller: controller,
|
||||||
keyboardType: keyboardType,
|
keyboardType: keyboardType,
|
||||||
|
@ -60,9 +69,11 @@ class BaseTextFormField extends StatelessWidget {
|
||||||
inputFormatters: inputFormatters,
|
inputFormatters: inputFormatters,
|
||||||
enabled: enabled,
|
enabled: enabled,
|
||||||
maxLength: maxLength,
|
maxLength: maxLength,
|
||||||
style: textStyle ?? TextStyle(
|
style: textStyle ??
|
||||||
fontSize: 16.0,
|
TextStyle(
|
||||||
color: textColor ?? Theme.of(context).primaryTextTheme.title.color),
|
fontSize: 16.0,
|
||||||
|
color:
|
||||||
|
textColor ?? Theme.of(context).primaryTextTheme.title.color),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
prefixIcon: prefixIcon,
|
prefixIcon: prefixIcon,
|
||||||
|
@ -75,15 +86,18 @@ class BaseTextFormField extends StatelessWidget {
|
||||||
hintText: hintText,
|
hintText: hintText,
|
||||||
focusedBorder: UnderlineInputBorder(
|
focusedBorder: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: borderColor ?? Theme.of(context).primaryTextTheme.title.backgroundColor,
|
color: borderColor ??
|
||||||
|
Theme.of(context).primaryTextTheme.title.backgroundColor,
|
||||||
width: 1.0)),
|
width: 1.0)),
|
||||||
disabledBorder: UnderlineInputBorder(
|
disabledBorder: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: borderColor ?? Theme.of(context).primaryTextTheme.title.backgroundColor,
|
color: borderColor ??
|
||||||
|
Theme.of(context).primaryTextTheme.title.backgroundColor,
|
||||||
width: 1.0)),
|
width: 1.0)),
|
||||||
enabledBorder: UnderlineInputBorder(
|
enabledBorder: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: borderColor ?? Theme.of(context).primaryTextTheme.title.backgroundColor,
|
color: borderColor ??
|
||||||
|
Theme.of(context).primaryTextTheme.title.backgroundColor,
|
||||||
width: 1.0))),
|
width: 1.0))),
|
||||||
validator: validator,
|
validator: validator,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'package:cake_wallet/entities/wallet_type.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
@ -8,6 +10,166 @@ import 'package:cake_wallet/entities/mnemonic_item.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
class Annotation extends Comparable<Annotation> {
|
||||||
|
Annotation({@required this.range, this.style});
|
||||||
|
|
||||||
|
final TextRange range;
|
||||||
|
final TextStyle style;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int compareTo(Annotation other) => range.start.compareTo(other.range.start);
|
||||||
|
}
|
||||||
|
|
||||||
|
class TextAnnotation extends Comparable<TextAnnotation> {
|
||||||
|
TextAnnotation({@required this.text, this.style});
|
||||||
|
|
||||||
|
final TextStyle style;
|
||||||
|
final String text;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int compareTo(TextAnnotation other) => text.compareTo(other.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
class AnnotatedEditableText extends EditableText {
|
||||||
|
AnnotatedEditableText({
|
||||||
|
Key key,
|
||||||
|
FocusNode focusNode,
|
||||||
|
TextEditingController controller,
|
||||||
|
TextStyle style,
|
||||||
|
ValueChanged<String> onChanged,
|
||||||
|
ValueChanged<String> onSubmitted,
|
||||||
|
Color cursorColor,
|
||||||
|
Color selectionColor,
|
||||||
|
Color backgroundCursorColor,
|
||||||
|
TextSelectionControls selectionControls,
|
||||||
|
@required this.words,
|
||||||
|
}) : textAnnotations = words
|
||||||
|
.map((word) => TextAnnotation(
|
||||||
|
text: word,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.black,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
fontSize: 20)))
|
||||||
|
.toList(),
|
||||||
|
super(
|
||||||
|
maxLines: null,
|
||||||
|
key: key,
|
||||||
|
focusNode: focusNode,
|
||||||
|
controller: controller,
|
||||||
|
cursorColor: cursorColor,
|
||||||
|
style: style,
|
||||||
|
keyboardType: TextInputType.text,
|
||||||
|
autocorrect: false,
|
||||||
|
autofocus: false,
|
||||||
|
selectionColor: selectionColor,
|
||||||
|
selectionControls: selectionControls,
|
||||||
|
backgroundCursorColor: backgroundCursorColor,
|
||||||
|
onChanged: onChanged,
|
||||||
|
onSubmitted: onSubmitted,
|
||||||
|
toolbarOptions: const ToolbarOptions(
|
||||||
|
copy: true,
|
||||||
|
cut: true,
|
||||||
|
paste: true,
|
||||||
|
selectAll: true,
|
||||||
|
),
|
||||||
|
enableSuggestions: false,
|
||||||
|
enableInteractiveSelection: true,
|
||||||
|
showSelectionHandles: true,
|
||||||
|
showCursor: true,
|
||||||
|
) {
|
||||||
|
textAnnotations.add(TextAnnotation(
|
||||||
|
text: ' ', style: TextStyle(backgroundColor: Colors.transparent)));
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<String> words;
|
||||||
|
final List<TextAnnotation> textAnnotations;
|
||||||
|
|
||||||
|
@override
|
||||||
|
AnnotatedEditableTextState createState() => AnnotatedEditableTextState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class AnnotatedEditableTextState extends EditableTextState {
|
||||||
|
@override
|
||||||
|
AnnotatedEditableText get widget => super.widget as AnnotatedEditableText;
|
||||||
|
|
||||||
|
List<Annotation> getRanges() {
|
||||||
|
final source = widget.textAnnotations
|
||||||
|
.map((item) => range(item.text, textEditingValue.text)
|
||||||
|
.map((range) => Annotation(style: item.style, range: range)))
|
||||||
|
.expand((e) => e)
|
||||||
|
.toList();
|
||||||
|
final result = List<Annotation>();
|
||||||
|
final text = textEditingValue.text;
|
||||||
|
source.sort();
|
||||||
|
Annotation prev;
|
||||||
|
|
||||||
|
for (var item in source) {
|
||||||
|
if (prev == null) {
|
||||||
|
if (item.range.start > 0) {
|
||||||
|
result.add(Annotation(
|
||||||
|
range: TextRange(start: 0, end: item.range.start),
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.black, backgroundColor: Colors.transparent)));
|
||||||
|
}
|
||||||
|
result.add(item);
|
||||||
|
prev = item;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if (prev.range.end > item.range.start) {
|
||||||
|
// throw StateError('Invalid (intersecting) ranges for annotated field');
|
||||||
|
} else if (prev.range.end < item.range.start) {
|
||||||
|
result.add(Annotation(
|
||||||
|
range: TextRange(start: prev.range.end, end: item.range.start),
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.red, backgroundColor: Colors.transparent)));
|
||||||
|
}
|
||||||
|
|
||||||
|
result.add(item);
|
||||||
|
prev = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.length > 0 && result.last.range.end < text.length) {
|
||||||
|
result.add(Annotation(
|
||||||
|
range: TextRange(start: result.last.range.end, end: text.length),
|
||||||
|
style: TextStyle( backgroundColor: Colors.transparent)));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TextRange> range(String pattern, String source) {
|
||||||
|
final result = List<TextRange>();
|
||||||
|
|
||||||
|
for (int index = source.indexOf(pattern);
|
||||||
|
index >= 0;
|
||||||
|
index = source.indexOf(pattern, index + 1)) {
|
||||||
|
final start = index;
|
||||||
|
final end = start + pattern.length;
|
||||||
|
result.add(TextRange(start: start, end: end));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
TextSpan buildTextSpan() {
|
||||||
|
final text = textEditingValue.text;
|
||||||
|
final ranges = getRanges();
|
||||||
|
|
||||||
|
if (ranges.isNotEmpty) {
|
||||||
|
return TextSpan(
|
||||||
|
style: widget.style,
|
||||||
|
children: ranges
|
||||||
|
.map((item) => TextSpan(
|
||||||
|
style: item.style, text: item.range.textInside(text)))
|
||||||
|
.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
return TextSpan(style: widget.style, text: text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class SeedWidget extends StatefulWidget {
|
class SeedWidget extends StatefulWidget {
|
||||||
SeedWidget(
|
SeedWidget(
|
||||||
{Key key,
|
{Key key,
|
||||||
|
@ -48,10 +210,13 @@ class SeedWidgetState extends State<SeedWidget> {
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
showPlaceholder = true;
|
||||||
isValid = false;
|
isValid = false;
|
||||||
isCurrentMnemonicValid = false;
|
isCurrentMnemonicValid = false;
|
||||||
_seedController
|
_seedController
|
||||||
.addListener(() => changeCurrentMnemonic(_seedController.text));
|
.addListener(() => changeCurrentMnemonic(_seedController.text));
|
||||||
|
focusNode.addListener(() => setState(() =>
|
||||||
|
showPlaceholder = !focusNode.hasFocus && controller.text.isEmpty));
|
||||||
}
|
}
|
||||||
|
|
||||||
void addMnemonic(String text) {
|
void addMnemonic(String text) {
|
||||||
|
@ -198,239 +363,308 @@ class SeedWidgetState extends State<SeedWidget> {
|
||||||
return isValid;
|
return isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final controller = TextEditingController();
|
||||||
|
final focusNode = FocusNode();
|
||||||
|
|
||||||
|
bool showPlaceholder;
|
||||||
|
|
||||||
|
final words =
|
||||||
|
SeedValidator.getWordList(type: WalletType.monero, language: 'en');
|
||||||
|
|
||||||
|
Future<void> _pasteAddress() async {
|
||||||
|
final value = await Clipboard.getData('text/plain');
|
||||||
|
|
||||||
|
if (value?.text?.isNotEmpty ?? false) {
|
||||||
|
controller.text = value.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
print('build');
|
||||||
return Container(
|
return Container(
|
||||||
child: Column(children: [
|
child: Column(
|
||||||
Flexible(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
fit: FlexFit.tight,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
flex: 2,
|
children: [
|
||||||
child: Container(
|
Stack(children: [
|
||||||
width: double.infinity,
|
SizedBox(height: 35),
|
||||||
height: double.infinity,
|
if (showPlaceholder)
|
||||||
padding: EdgeInsets.all(0),
|
Positioned(
|
||||||
decoration: BoxDecoration(
|
top: 10,
|
||||||
borderRadius: BorderRadius.only(
|
left: 0,
|
||||||
bottomLeft: Radius.circular(24),
|
child: Text('Enter your seed',
|
||||||
bottomRight: Radius.circular(24)),
|
|
||||||
gradient: LinearGradient(colors: [
|
|
||||||
Theme.of(context).primaryTextTheme.subhead.color,
|
|
||||||
Theme.of(context).primaryTextTheme.subhead.decorationColor,
|
|
||||||
], begin: Alignment.topLeft, end: Alignment.bottomRight)),
|
|
||||||
child: Column(
|
|
||||||
children: <Widget>[
|
|
||||||
CupertinoNavigationBar(
|
|
||||||
leading: widget.leading,
|
|
||||||
middle: widget.middle,
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
border: null,
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Container(
|
|
||||||
padding: EdgeInsets.all(24),
|
|
||||||
alignment: Alignment.topLeft,
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: <Widget>[
|
|
||||||
Text(
|
|
||||||
S.of(context).restore_active_seed,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.overline
|
|
||||||
.backgroundColor),
|
|
||||||
),
|
|
||||||
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: () => 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
|
|
||||||
? Colors.white
|
|
||||||
: Colors.grey,
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: isSelected
|
|
||||||
? FontWeight.w900
|
|
||||||
: FontWeight.w600,
|
|
||||||
decoration: isSelected
|
|
||||||
? TextDecoration.underline
|
|
||||||
: TextDecoration.none),
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
))
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
Flexible(
|
|
||||||
fit: FlexFit.tight,
|
|
||||||
flex: 3,
|
|
||||||
child: Padding(
|
|
||||||
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(
|
style: TextStyle(
|
||||||
fontSize: 20,
|
fontSize: 16.0, color: Theme.of(context).hintColor))),
|
||||||
fontWeight: FontWeight.w500,
|
Padding(
|
||||||
color:
|
padding: EdgeInsets.only(right: 40, top: 10),
|
||||||
Theme.of(context).primaryTextTheme.title.color),
|
child: AnnotatedEditableText(
|
||||||
),
|
cursorColor: Colors.green,
|
||||||
Padding(
|
backgroundCursorColor: Colors.blue,
|
||||||
padding: EdgeInsets.only(top: 24),
|
style: TextStyle(
|
||||||
child: TextFormField(
|
fontSize: 20,
|
||||||
key: _seedTextFieldKey,
|
color: Colors.red,
|
||||||
onFieldSubmitted: (text) => isCurrentMnemonicValid
|
fontWeight: FontWeight.normal,
|
||||||
? saveCurrentMnemonicToItems()
|
backgroundColor: Colors.transparent),
|
||||||
: null,
|
focusNode: focusNode,
|
||||||
style: TextStyle(
|
controller: controller,
|
||||||
fontSize: 16.0,
|
words: words)),
|
||||||
fontWeight: FontWeight.normal,
|
Positioned(
|
||||||
color:
|
top: 0,
|
||||||
Theme.of(context).primaryTextTheme.title.color),
|
right: 0,
|
||||||
controller: _seedController,
|
child: Container(
|
||||||
textInputAction: TextInputAction.done,
|
width: 34,
|
||||||
decoration: InputDecoration(
|
height: 34,
|
||||||
suffixIcon: GestureDetector(
|
child: InkWell(
|
||||||
behavior: HitTestBehavior.opaque,
|
onTap: () async => _pasteAddress(),
|
||||||
child: ConstrainedBox(
|
child: Container(
|
||||||
constraints: BoxConstraints(maxWidth: 145),
|
decoration: BoxDecoration(
|
||||||
child: Row(
|
color: Theme.of(context).hintColor,
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
borderRadius:
|
||||||
children: <Widget>[
|
BorderRadius.all(Radius.circular(6))),
|
||||||
Text('${items.length}/$maxLength',
|
child: Image.asset('assets/images/duplicate.png',
|
||||||
style: TextStyle(
|
color: Theme.of(context)
|
||||||
color: Theme.of(context)
|
.primaryTextTheme
|
||||||
.accentTextTheme
|
.display1
|
||||||
.display2
|
.decorationColor)),
|
||||||
.decorationColor,
|
)))
|
||||||
fontWeight: FontWeight.normal,
|
]),
|
||||||
fontSize: 16)),
|
Container(
|
||||||
SizedBox(width: 10),
|
margin: EdgeInsets.only(top: 15),
|
||||||
InkWell(
|
height: 1.0,
|
||||||
onTap: () async =>
|
color: Theme.of(context).primaryTextTheme.title.backgroundColor),
|
||||||
Clipboard.getData('text/plain').then(
|
]));
|
||||||
(clipboard) =>
|
// return Container(
|
||||||
replaceText(clipboard.text)),
|
// child: Column(children: [
|
||||||
child: Container(
|
// Flexible(
|
||||||
height: 35,
|
// fit: FlexFit.tight,
|
||||||
padding: EdgeInsets.all(7),
|
// flex: 2,
|
||||||
decoration: BoxDecoration(
|
// child: Container(
|
||||||
color: Theme.of(context)
|
// width: double.infinity,
|
||||||
.accentTextTheme
|
// height: double.infinity,
|
||||||
.caption
|
// padding: EdgeInsets.all(0),
|
||||||
.color,
|
// decoration: BoxDecoration(
|
||||||
borderRadius:
|
// borderRadius: BorderRadius.only(
|
||||||
BorderRadius.circular(10.0)),
|
// bottomLeft: Radius.circular(24),
|
||||||
child: Text(
|
// bottomRight: Radius.circular(24)),
|
||||||
S.of(context).paste,
|
// gradient: LinearGradient(colors: [
|
||||||
style: TextStyle(
|
// Theme.of(context).primaryTextTheme.subhead.color,
|
||||||
color: Palette.blueCraiola),
|
// Theme.of(context).primaryTextTheme.subhead.decorationColor,
|
||||||
)),
|
// ], begin: Alignment.topLeft, end: Alignment.bottomRight)),
|
||||||
)
|
// child: Column(
|
||||||
],
|
// children: <Widget>[
|
||||||
),
|
// CupertinoNavigationBar(
|
||||||
),
|
// leading: widget.leading,
|
||||||
),
|
// middle: widget.middle,
|
||||||
hintStyle: TextStyle(
|
// backgroundColor: Colors.transparent,
|
||||||
color: Theme.of(context)
|
// border: null,
|
||||||
.accentTextTheme
|
// ),
|
||||||
.display2
|
// Expanded(
|
||||||
.decorationColor,
|
// child: Container(
|
||||||
fontWeight: FontWeight.normal,
|
// padding: EdgeInsets.all(24),
|
||||||
fontSize: 16),
|
// alignment: Alignment.topLeft,
|
||||||
hintText:
|
// child: SingleChildScrollView(
|
||||||
S.of(context).restore_from_seed_placeholder,
|
// child: Column(
|
||||||
errorText: _errorMessage,
|
// mainAxisAlignment: MainAxisAlignment.start,
|
||||||
focusedBorder: UnderlineInputBorder(
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
borderSide: BorderSide(
|
// children: <Widget>[
|
||||||
color: Theme.of(context)
|
// Text(
|
||||||
.accentTextTheme
|
// S.of(context).restore_active_seed,
|
||||||
.subtitle
|
// style: TextStyle(
|
||||||
.backgroundColor,
|
// fontSize: 14,
|
||||||
width: 1.0)),
|
// fontWeight: FontWeight.w500,
|
||||||
enabledBorder: UnderlineInputBorder(
|
// color: Theme.of(context)
|
||||||
borderSide: BorderSide(
|
// .textTheme
|
||||||
color: Theme.of(context)
|
// .overline
|
||||||
.accentTextTheme
|
// .backgroundColor),
|
||||||
.subtitle
|
// ),
|
||||||
.backgroundColor,
|
// Padding(
|
||||||
width: 1.0))),
|
// padding: EdgeInsets.only(top: 5),
|
||||||
enableInteractiveSelection: false,
|
// child: Wrap(
|
||||||
),
|
// children: items.map((item) {
|
||||||
)
|
// final isValid =
|
||||||
]),
|
// widget.validator.isValid(item);
|
||||||
)),
|
// final isSelected = selectedItem == item;
|
||||||
Padding(
|
//
|
||||||
padding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
|
// return InkWell(
|
||||||
child: Row(
|
// onTap: () => onMnemonicTap(item),
|
||||||
children: <Widget>[
|
// child: Container(
|
||||||
Flexible(
|
// decoration: BoxDecoration(
|
||||||
child: Padding(
|
// color: isValid
|
||||||
padding: EdgeInsets.only(right: 8),
|
// ? Colors.transparent
|
||||||
child: PrimaryButton(
|
// : Palette.red),
|
||||||
onPressed: clear,
|
// margin: EdgeInsets.only(
|
||||||
text: S.of(context).clear,
|
// right: 7, bottom: 8),
|
||||||
color: Colors.orange,
|
// child: Text(
|
||||||
textColor: Colors.white,
|
// item.toString(),
|
||||||
isDisabled: items.isEmpty,
|
// style: TextStyle(
|
||||||
),
|
// color: isValid
|
||||||
)),
|
// ? Colors.white
|
||||||
Flexible(
|
// : Colors.grey,
|
||||||
child: Padding(
|
// fontSize: 16,
|
||||||
padding: EdgeInsets.only(left: 8),
|
// fontWeight: isSelected
|
||||||
child: (selectedItem == null && items.length == maxLength)
|
// ? FontWeight.w900
|
||||||
? PrimaryButton(
|
// : FontWeight.w600,
|
||||||
text: S.of(context).restore_next,
|
// decoration: isSelected
|
||||||
isDisabled: !isSeedValid(),
|
// ? TextDecoration.underline
|
||||||
onPressed: () => widget.onFinish != null
|
// : TextDecoration.none),
|
||||||
? widget.onFinish()
|
// )),
|
||||||
: null,
|
// );
|
||||||
color: Theme.of(context).accentTextTheme.body2.color,
|
// }).toList(),
|
||||||
textColor: Colors.white)
|
// ))
|
||||||
: PrimaryButton(
|
// ],
|
||||||
text: selectedItem != null
|
// ),
|
||||||
? S.of(context).save
|
// ),
|
||||||
: S.of(context).add_new_word,
|
// ))
|
||||||
onPressed: () => isCurrentMnemonicValid
|
// ],
|
||||||
? saveCurrentMnemonicToItems()
|
// )),
|
||||||
: null,
|
// ),
|
||||||
onDisabledPressed: () => showErrorIfExist(),
|
// Flexible(
|
||||||
isDisabled: !isCurrentMnemonicValid,
|
// fit: FlexFit.tight,
|
||||||
color: Theme.of(context).accentTextTheme.body2.color,
|
// flex: 3,
|
||||||
textColor: Colors.white),
|
// child: Padding(
|
||||||
),
|
// 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: 20,
|
||||||
|
// fontWeight: FontWeight.w500,
|
||||||
|
// color:
|
||||||
|
// Theme.of(context).primaryTextTheme.title.color),
|
||||||
|
// ),
|
||||||
|
// Padding(
|
||||||
|
// padding: EdgeInsets.only(top: 24),
|
||||||
|
// child: TextFormField(
|
||||||
|
// key: _seedTextFieldKey,
|
||||||
|
// onFieldSubmitted: (text) => isCurrentMnemonicValid
|
||||||
|
// ? saveCurrentMnemonicToItems()
|
||||||
|
// : null,
|
||||||
|
// style: TextStyle(
|
||||||
|
// fontSize: 16.0,
|
||||||
|
// fontWeight: FontWeight.normal,
|
||||||
|
// 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)
|
||||||
|
// .accentTextTheme
|
||||||
|
// .display2
|
||||||
|
// .decorationColor,
|
||||||
|
// fontWeight: FontWeight.normal,
|
||||||
|
// fontSize: 16)),
|
||||||
|
// 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
|
||||||
|
// .caption
|
||||||
|
// .color,
|
||||||
|
// borderRadius:
|
||||||
|
// BorderRadius.circular(10.0)),
|
||||||
|
// child: Text(
|
||||||
|
// S.of(context).paste,
|
||||||
|
// style: TextStyle(
|
||||||
|
// color: Palette.blueCraiola),
|
||||||
|
// )),
|
||||||
|
// )
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// hintStyle: TextStyle(
|
||||||
|
// color: Theme.of(context)
|
||||||
|
// .accentTextTheme
|
||||||
|
// .display2
|
||||||
|
// .decorationColor,
|
||||||
|
// fontWeight: FontWeight.normal,
|
||||||
|
// fontSize: 16),
|
||||||
|
// hintText:
|
||||||
|
// S.of(context).restore_from_seed_placeholder,
|
||||||
|
// errorText: _errorMessage,
|
||||||
|
// focusedBorder: UnderlineInputBorder(
|
||||||
|
// borderSide: BorderSide(
|
||||||
|
// color: Theme.of(context)
|
||||||
|
// .accentTextTheme
|
||||||
|
// .subtitle
|
||||||
|
// .backgroundColor,
|
||||||
|
// width: 1.0)),
|
||||||
|
// enabledBorder: UnderlineInputBorder(
|
||||||
|
// borderSide: BorderSide(
|
||||||
|
// color: Theme.of(context)
|
||||||
|
// .accentTextTheme
|
||||||
|
// .subtitle
|
||||||
|
// .backgroundColor,
|
||||||
|
// 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.orange,
|
||||||
|
// 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: Theme.of(context).accentTextTheme.body2.color,
|
||||||
|
// textColor: Colors.white)
|
||||||
|
// : PrimaryButton(
|
||||||
|
// text: selectedItem != null
|
||||||
|
// ? S.of(context).save
|
||||||
|
// : S.of(context).add_new_word,
|
||||||
|
// onPressed: () => isCurrentMnemonicValid
|
||||||
|
// ? saveCurrentMnemonicToItems()
|
||||||
|
// : null,
|
||||||
|
// onDisabledPressed: () => showErrorIfExist(),
|
||||||
|
// isDisabled: !isCurrentMnemonicValid,
|
||||||
|
// color: Theme.of(context).accentTextTheme.body2.color,
|
||||||
|
// textColor: Colors.white),
|
||||||
|
// ),
|
||||||
|
// )
|
||||||
|
// ],
|
||||||
|
// ))
|
||||||
|
// ]),
|
||||||
|
// );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue