mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-03-25 08:39:06 +00:00
Merge redesign part 5.
This commit is contained in:
commit
6e6a081685
38 changed files with 1805 additions and 964 deletions
|
@ -1,4 +1,2 @@
|
||||||
-
|
-
|
||||||
uri: electrum2.hodlister.co:50002
|
uri: electrumx.cakewallet.com:50002
|
||||||
-
|
|
||||||
uri: bitcoin.electrumx.multicoin.co:50002
|
|
|
@ -2,6 +2,8 @@
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>NSFaceIDUsageDescription</key>
|
||||||
|
<string>Enable Face ID for fast and secure access to wallets and private keys</string>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
|
@ -23,7 +25,7 @@
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>NSCameraUsageDescription</key>
|
<key>NSCameraUsageDescription</key>
|
||||||
<string>Cake Wallet requires access to your phone’s camera.</string>
|
<string>Used for scan QR code</string>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
<key>UIMainStoryboardFile</key>
|
<key>UIMainStoryboardFile</key>
|
||||||
|
|
25
lib/di.dart
25
lib/di.dart
|
@ -204,6 +204,10 @@ Future setup(
|
||||||
|
|
||||||
getIt.registerFactory<AuthPage>(
|
getIt.registerFactory<AuthPage>(
|
||||||
() => AuthPage(
|
() => AuthPage(
|
||||||
|
allowBiometricalAuthentication: getIt
|
||||||
|
.get<AppStore>()
|
||||||
|
.settingsStore
|
||||||
|
.allowBiometricalAuthentication,
|
||||||
authViewModel: getIt.get<AuthViewModel>(),
|
authViewModel: getIt.get<AuthViewModel>(),
|
||||||
onAuthenticationFinished: (isAuthenticated, __) {
|
onAuthenticationFinished: (isAuthenticated, __) {
|
||||||
if (isAuthenticated) {
|
if (isAuthenticated) {
|
||||||
|
@ -215,10 +219,18 @@ Future setup(
|
||||||
|
|
||||||
getIt
|
getIt
|
||||||
.registerFactoryParam<AuthPage, void Function(bool, AuthPageState), void>(
|
.registerFactoryParam<AuthPage, void Function(bool, AuthPageState), void>(
|
||||||
(onAuthFinished, _) => AuthPage(
|
(onAuthFinished, _) {
|
||||||
authViewModel: getIt.get<AuthViewModel>(),
|
final allowBiometricalAuthentication =
|
||||||
onAuthenticationFinished: onAuthFinished,
|
getIt.get<AppStore>().settingsStore.allowBiometricalAuthentication;
|
||||||
closable: false));
|
|
||||||
|
print('allowBiometricalAuthentication $allowBiometricalAuthentication');
|
||||||
|
|
||||||
|
return AuthPage(
|
||||||
|
allowBiometricalAuthentication: allowBiometricalAuthentication,
|
||||||
|
authViewModel: getIt.get<AuthViewModel>(),
|
||||||
|
onAuthenticationFinished: onAuthFinished,
|
||||||
|
closable: false);
|
||||||
|
});
|
||||||
|
|
||||||
getIt.registerFactory<DashboardPage>(() => DashboardPage(
|
getIt.registerFactory<DashboardPage>(() => DashboardPage(
|
||||||
walletViewModel: getIt.get<DashboardViewModel>(),
|
walletViewModel: getIt.get<DashboardViewModel>(),
|
||||||
|
@ -313,8 +325,9 @@ Future setup(
|
||||||
getIt.get<ContactService>(),
|
getIt.get<ContactService>(),
|
||||||
contactSource));
|
contactSource));
|
||||||
|
|
||||||
getIt.registerFactoryParam<ContactListPage, bool, void>((bool isEditable, _) =>
|
getIt.registerFactoryParam<ContactListPage, bool, void>(
|
||||||
ContactListPage(getIt.get<ContactListViewModel>(), isEditable: isEditable));
|
(bool isEditable, _) => ContactListPage(getIt.get<ContactListViewModel>(),
|
||||||
|
isEditable: isEditable));
|
||||||
|
|
||||||
getIt.registerFactoryParam<ContactPage, Contact, void>((Contact contact, _) =>
|
getIt.registerFactoryParam<ContactPage, Contact, void>((Contact contact, _) =>
|
||||||
ContactPage(getIt.get<ContactViewModel>(param1: contact)));
|
ContactPage(getIt.get<ContactViewModel>(param1: contact)));
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:cake_wallet/src/domain/monero/monero_transaction_creation_credentials.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
import 'package:cw_monero/wallet.dart';
|
import 'package:cw_monero/wallet.dart';
|
||||||
|
@ -18,7 +19,8 @@ import 'package:cake_wallet/src/domain/monero/subaddress.dart';
|
||||||
import 'package:cake_wallet/src/domain/common/node.dart';
|
import 'package:cake_wallet/src/domain/common/node.dart';
|
||||||
import 'package:cake_wallet/core/pending_transaction.dart';
|
import 'package:cake_wallet/core/pending_transaction.dart';
|
||||||
import 'package:cake_wallet/src/domain/common/transaction_priority.dart';
|
import 'package:cake_wallet/src/domain/common/transaction_priority.dart';
|
||||||
import 'package:cake_wallet/src/domain/common/calculate_fiat_amount.dart' as cfa;
|
import 'package:cake_wallet/src/domain/common/calculate_fiat_amount.dart'
|
||||||
|
as cfa;
|
||||||
|
|
||||||
part 'monero_wallet.g.dart';
|
part 'monero_wallet.g.dart';
|
||||||
|
|
||||||
|
@ -137,16 +139,16 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<PendingTransaction> createTransaction(Object credentials) async {
|
Future<PendingTransaction> createTransaction(Object credentials) async {
|
||||||
// final _credentials = credentials as MoneroTransactionCreationCredentials;
|
final _credentials = credentials as MoneroTransactionCreationCredentials;
|
||||||
// final transactionDescription = await transaction_history.createTransaction(
|
// final transactionDescription = await transaction_history.createTransaction(
|
||||||
// address: _credentials.address,
|
// address: _credentials.address,
|
||||||
// paymentId: _credentials.paymentId,
|
// paymentId: _credentials.paymentId,
|
||||||
// amount: _credentials.amount,
|
// amount: _credentials.amount,
|
||||||
// priorityRaw: _credentials.priority.serialize(),
|
// priorityRaw: _credentials.priority.serialize(),
|
||||||
// accountIndex: _account.value.id);
|
// accountIndex: _account.value.id);
|
||||||
//
|
|
||||||
// return PendingTransaction.fromTransactionDescription(
|
// return PendingTransaction.fromTransactionDescription(
|
||||||
// transactionDescription);
|
// transactionDescription);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:cake_wallet/monero/monero_wallet.dart';
|
import 'package:cake_wallet/monero/monero_wallet.dart';
|
||||||
import 'package:cake_wallet/core/wallet_credentials.dart';
|
import 'package:cake_wallet/core/wallet_credentials.dart';
|
||||||
import 'package:cake_wallet/core/wallet_service.dart';
|
import 'package:cake_wallet/core/wallet_service.dart';
|
||||||
|
@ -60,7 +62,7 @@ class MoneroWalletService extends WalletService<
|
||||||
|
|
||||||
return wallet;
|
return wallet;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// TODO: Implement Exception fop wallet list service.
|
// TODO: Implement Exception for wallet list service.
|
||||||
print('MoneroWalletsManager Error: $e');
|
print('MoneroWalletsManager Error: $e');
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
|
@ -72,7 +74,7 @@ class MoneroWalletService extends WalletService<
|
||||||
final path = await pathForWallet(name: name, type: WalletType.monero);
|
final path = await pathForWallet(name: name, type: WalletType.monero);
|
||||||
return monero_wallet_manager.isWalletExist(path: path);
|
return monero_wallet_manager.isWalletExist(path: path);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// TODO: Implement Exception fop wallet list service.
|
// TODO: Implement Exception for wallet list service.
|
||||||
print('MoneroWalletsManager Error: $e');
|
print('MoneroWalletsManager Error: $e');
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
|
@ -83,26 +85,21 @@ class MoneroWalletService extends WalletService<
|
||||||
try {
|
try {
|
||||||
final path = await pathForWallet(name: name, type: WalletType.monero);
|
final path = await pathForWallet(name: name, type: WalletType.monero);
|
||||||
monero_wallet_manager.openWallet(path: path, password: password);
|
monero_wallet_manager.openWallet(path: path, password: password);
|
||||||
|
|
||||||
// final id = walletTypeToString(WalletType.monero).toLowerCase() + '_' + name;
|
|
||||||
// final walletInfo = walletInfoSource.values
|
|
||||||
// .firstWhere((info) => info.id == id, orElse: () => null);
|
|
||||||
|
|
||||||
final wallet = MoneroWallet(filename: monero_wallet.getFilename());
|
final wallet = MoneroWallet(filename: monero_wallet.getFilename());
|
||||||
await wallet.init();
|
await wallet.init();
|
||||||
|
|
||||||
return wallet;
|
return wallet;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// TODO: Implement Exception fop wallet list service.
|
// TODO: Implement Exception for wallet list service.
|
||||||
print('MoneroWalletsManager Error: $e');
|
print('MoneroWalletsManager Error: $e');
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> remove(String wallet) async {
|
@override
|
||||||
// TODO: implement remove
|
Future<void> remove(String wallet) async =>
|
||||||
throw UnimplementedError();
|
File(await pathForWalletDir(name: wallet, type: WalletType.bitcoin))
|
||||||
}
|
.delete(recursive: true);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<MoneroWallet> restoreFromKeys(
|
Future<MoneroWallet> restoreFromKeys(
|
||||||
|
@ -125,7 +122,7 @@ class MoneroWalletService extends WalletService<
|
||||||
|
|
||||||
return wallet;
|
return wallet;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// TODO: Implement Exception fop wallet list service.
|
// TODO: Implement Exception for wallet list service.
|
||||||
print('MoneroWalletsManager Error: $e');
|
print('MoneroWalletsManager Error: $e');
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
|
@ -149,7 +146,7 @@ class MoneroWalletService extends WalletService<
|
||||||
|
|
||||||
return wallet;
|
return wallet;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// TODO: Implement Exception fop wallet list service.
|
// TODO: Implement Exception for wallet list service.
|
||||||
print('MoneroWalletsManager Error: $e');
|
print('MoneroWalletsManager Error: $e');
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,8 @@ class PaletteDark {
|
||||||
static const Color distantBlue = Color.fromRGBO(72, 85, 131, 1.0);
|
static const Color distantBlue = Color.fromRGBO(72, 85, 131, 1.0);
|
||||||
static const Color moderateVioletBlue = Color.fromRGBO(62, 73, 113, 1.0);
|
static const Color moderateVioletBlue = Color.fromRGBO(62, 73, 113, 1.0);
|
||||||
static const Color deepVioletBlue = Color.fromRGBO(52, 66, 104, 1.0);
|
static const Color deepVioletBlue = Color.fromRGBO(52, 66, 104, 1.0);
|
||||||
|
static const Color lightPurpleBlue = Color.fromRGBO(120, 133, 170, 1.0);
|
||||||
|
static const Color indicatorVioletBlue = Color.fromRGBO(59, 72, 119, 1.0);
|
||||||
|
|
||||||
// FIXME: Rename.
|
// FIXME: Rename.
|
||||||
static const Color eee = Color.fromRGBO(236, 239, 245, 1.0);
|
static const Color eee = Color.fromRGBO(236, 239, 245, 1.0);
|
||||||
|
|
|
@ -24,7 +24,8 @@ import 'package:cake_wallet/store/dashboard/fiat_convertation_store.dart';
|
||||||
// FIXME: move me
|
// FIXME: move me
|
||||||
Future<void> loadCurrentWallet() async {
|
Future<void> loadCurrentWallet() async {
|
||||||
final appStore = getIt.get<AppStore>();
|
final appStore = getIt.get<AppStore>();
|
||||||
final name = getIt.get<SharedPreferences>().getString('current_wallet_name');
|
final name = 'test';
|
||||||
|
getIt.get<SharedPreferences>().getString('current_wallet_name');
|
||||||
final typeRaw =
|
final typeRaw =
|
||||||
getIt.get<SharedPreferences>().getInt('current_wallet_type') ?? 0;
|
getIt.get<SharedPreferences>().getInt('current_wallet_type') ?? 0;
|
||||||
final type = deserializeFromInt(typeRaw);
|
final type = deserializeFromInt(typeRaw);
|
||||||
|
|
|
@ -3,22 +3,28 @@ import 'package:flutter/services.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
|
||||||
class BiometricAuth {
|
class BiometricAuth {
|
||||||
|
final _localAuth = LocalAuthentication();
|
||||||
|
|
||||||
Future<bool> isAuthenticated() async {
|
Future<bool> isAuthenticated() async {
|
||||||
final LocalAuthentication _localAuth = LocalAuthentication();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return await _localAuth.authenticateWithBiometrics(
|
return await _localAuth.authenticateWithBiometrics(
|
||||||
localizedReason: S.current.biometric_auth_reason,
|
localizedReason: S.current.biometric_auth_reason,
|
||||||
useErrorDialogs: true,
|
useErrorDialogs: true,
|
||||||
stickyAuth: false
|
stickyAuth: false);
|
||||||
);
|
} on PlatformException catch (e) {
|
||||||
} on PlatformException
|
|
||||||
catch(e) {
|
|
||||||
print(e);
|
print(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
Future<bool> canCheckBiometrics() async {
|
||||||
|
try {
|
||||||
|
return await _localAuth.canCheckBiometrics;
|
||||||
|
} on PlatformException catch (e) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
38
lib/src/domain/common/contact_model.dart
Normal file
38
lib/src/domain/common/contact_model.dart
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
// import 'package:hive/hive.dart';
|
||||||
|
// import 'package:mobx/mobx.dart';
|
||||||
|
// import 'package:cake_wallet/src/domain/common/contact.dart';
|
||||||
|
// import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
|
||||||
|
|
||||||
|
// part 'contact_model.g.dart';
|
||||||
|
|
||||||
|
// class ContactModel = ContactModelBase with _$ContactModel;
|
||||||
|
|
||||||
|
// abstract class ContactModelBase with Store {
|
||||||
|
// ContactModelBase(this._contacts, {Contact contact}) : _contact = contact {
|
||||||
|
// name = _contact?.name;
|
||||||
|
// address = _contact?.address;
|
||||||
|
// currency = _contact?.type;
|
||||||
|
|
||||||
|
// _contacts.watch(key: contact.key).listen((event) {
|
||||||
|
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @observable
|
||||||
|
// String name;
|
||||||
|
|
||||||
|
// @observable
|
||||||
|
// String address;
|
||||||
|
|
||||||
|
// @observable
|
||||||
|
// CryptoCurrency currency;
|
||||||
|
|
||||||
|
// // @computed
|
||||||
|
// // bool get isReady =>
|
||||||
|
// // (name?.isNotEmpty ?? false) &&
|
||||||
|
// // (currency?.toString()?.isNotEmpty ?? false) &&
|
||||||
|
// // (address?.isNotEmpty ?? false);
|
||||||
|
|
||||||
|
// final Box<ContactBase> _contacts;
|
||||||
|
// final Contact _contact;
|
||||||
|
// }
|
|
@ -107,7 +107,7 @@ Future<void> changeMoneroCurrentNodeToDefault(
|
||||||
}
|
}
|
||||||
|
|
||||||
Node getBitcoinDefaultElectrumServer({@required Box<Node> nodes}) {
|
Node getBitcoinDefaultElectrumServer({@required Box<Node> nodes}) {
|
||||||
final uri = 'bitcoin.electrumx.multicoin.co:50002';
|
final uri = 'electrumx.cakewallet.com:50002';
|
||||||
|
|
||||||
return nodes.values
|
return nodes.values
|
||||||
.firstWhere((Node node) => node.uri == uri, orElse: () => null) ??
|
.firstWhere((Node node) => node.uri == uri, orElse: () => null) ??
|
||||||
|
|
|
@ -30,7 +30,7 @@ class Language with ChangeNotifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<String> localeDetection() async {
|
static Future<String> localeDetection() async {
|
||||||
String locale = await Devicelocale.currentLocale;
|
var locale = await Devicelocale.currentLocale;
|
||||||
locale = Intl.shortLocale(locale);
|
locale = Intl.shortLocale(locale);
|
||||||
|
|
||||||
return languages.keys.contains(locale) ? locale : 'en';
|
return languages.keys.contains(locale) ? locale : 'en';
|
||||||
|
|
|
@ -5,19 +5,20 @@ import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/view_model/auth_state.dart';
|
import 'package:cake_wallet/view_model/auth_state.dart';
|
||||||
import 'package:cake_wallet/view_model/auth_view_model.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/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';
|
import 'package:cake_wallet/src/domain/common/biometric_auth.dart';
|
||||||
|
|
||||||
typedef OnAuthenticationFinished = void Function(bool, AuthPageState);
|
typedef OnAuthenticationFinished = void Function(bool, AuthPageState);
|
||||||
|
|
||||||
class AuthPage extends StatefulWidget {
|
class AuthPage extends StatefulWidget {
|
||||||
AuthPage(
|
AuthPage(
|
||||||
{this.onAuthenticationFinished,
|
{@required this.allowBiometricalAuthentication,
|
||||||
|
this.onAuthenticationFinished,
|
||||||
this.authViewModel,
|
this.authViewModel,
|
||||||
this.closable = true});
|
this.closable = true});
|
||||||
|
|
||||||
final AuthViewModel authViewModel;
|
final AuthViewModel authViewModel;
|
||||||
final OnAuthenticationFinished onAuthenticationFinished;
|
final OnAuthenticationFinished onAuthenticationFinished;
|
||||||
|
final bool allowBiometricalAuthentication;
|
||||||
final bool closable;
|
final bool closable;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -95,6 +96,27 @@ class AuthPageState extends State<AuthPage> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (widget.allowBiometricalAuthentication) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
|
print('post');
|
||||||
|
await Future<void>.delayed(Duration(milliseconds: 100));
|
||||||
|
print('after timeout');
|
||||||
|
final biometricAuth = BiometricAuth();
|
||||||
|
final isAuth = await biometricAuth.isAuthenticated();
|
||||||
|
|
||||||
|
if (isAuth) {
|
||||||
|
widget.authViewModel.biometricAuth();
|
||||||
|
_key.currentState.showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(S.of(context).authenticated),
|
||||||
|
backgroundColor: Colors.green,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,27 +133,7 @@ class AuthPageState extends State<AuthPage> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// final authStore = Provider.of<AuthStore>(context);
|
print('start');
|
||||||
// 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(
|
return Scaffold(
|
||||||
key: _key,
|
key: _key,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
import 'package:cake_wallet/palette.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
@ -132,6 +133,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
|
||||||
_fileText,
|
_fileText,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12.0,
|
fontSize: 12.0,
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
color: Theme.of(context).primaryTextTheme.title.color
|
color: Theme.of(context).primaryTextTheme.title.color
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
|
@ -169,7 +171,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
|
||||||
xmrtoUrl,
|
xmrtoUrl,
|
||||||
textAlign: TextAlign.left,
|
textAlign: TextAlign.left,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.blue,
|
color: Palette.blueCraiola,
|
||||||
fontSize: 14.0,
|
fontSize: 14.0,
|
||||||
fontWeight: FontWeight.normal,
|
fontWeight: FontWeight.normal,
|
||||||
decoration: TextDecoration.underline),
|
decoration: TextDecoration.underline),
|
||||||
|
@ -190,7 +192,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
|
||||||
changenowUrl,
|
changenowUrl,
|
||||||
textAlign: TextAlign.left,
|
textAlign: TextAlign.left,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.blue,
|
color: Palette.blueCraiola,
|
||||||
fontSize: 14.0,
|
fontSize: 14.0,
|
||||||
fontWeight: FontWeight.normal,
|
fontWeight: FontWeight.normal,
|
||||||
decoration: TextDecoration.underline),
|
decoration: TextDecoration.underline),
|
||||||
|
@ -211,7 +213,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
|
||||||
morphUrl,
|
morphUrl,
|
||||||
textAlign: TextAlign.left,
|
textAlign: TextAlign.left,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.blue,
|
color: Palette.blueCraiola,
|
||||||
fontSize: 14.0,
|
fontSize: 14.0,
|
||||||
fontWeight: FontWeight.normal,
|
fontWeight: FontWeight.normal,
|
||||||
decoration: TextDecoration.underline),
|
decoration: TextDecoration.underline),
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:cake_wallet/palette.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/standard_list.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
@ -27,93 +29,85 @@ class FaqFormState extends State<FaqForm> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final addIcon = Icon(Icons.add, color: Theme.of(context).primaryTextTheme.title.color);
|
final addIcon = Icon(Icons.add, color: Theme.of(context).primaryTextTheme.title.color);
|
||||||
final removeIcon = Icon(Icons.remove, color: Colors.green);
|
final removeIcon = Icon(Icons.remove, color: Palette.blueCraiola);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: EdgeInsets.only(top: 12),
|
padding: EdgeInsets.only(top: 12, left: 24),
|
||||||
child: Container(
|
child: FutureBuilder(
|
||||||
color: Theme.of(context).accentTextTheme.headline.color,
|
builder: (context, snapshot) {
|
||||||
child: FutureBuilder(
|
final faqItems = jsonDecode(snapshot.data.toString()) as List;
|
||||||
builder: (context, snapshot) {
|
|
||||||
final faqItems = jsonDecode(snapshot.data.toString()) as List;
|
|
||||||
|
|
||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
setIconsAndColors(context, faqItems.length, addIcon);
|
setIconsAndColors(context, faqItems.length, addIcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
child: ListView.separated(
|
child: Column(
|
||||||
shrinkWrap: true,
|
children: <Widget>[
|
||||||
physics: NeverScrollableScrollPhysics(),
|
StandardListSeparator(),
|
||||||
itemBuilder: (BuildContext context, int index) {
|
ListView.separated(
|
||||||
final itemTitle = faqItems[index]["question"].toString();
|
shrinkWrap: true,
|
||||||
final itemChild = faqItems[index]["answer"].toString();
|
physics: NeverScrollableScrollPhysics(),
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
final itemTitle = faqItems[index]["question"].toString();
|
||||||
|
final itemChild = faqItems[index]["answer"].toString();
|
||||||
|
|
||||||
return ExpansionTile(
|
return ListTileTheme(
|
||||||
title: Padding(
|
contentPadding: EdgeInsets.fromLTRB(0, 6, 24, 6),
|
||||||
padding: EdgeInsets.only(left: 8, top: 12, bottom: 12),
|
child: ExpansionTile(
|
||||||
child: Text(
|
title: Text(
|
||||||
itemTitle,
|
itemTitle,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w500,
|
||||||
color: colors[index]
|
color: colors[index]
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
trailing: icons[index],
|
||||||
),
|
onExpansionChanged: (value) {
|
||||||
trailing: Padding(
|
setState(() {
|
||||||
padding: EdgeInsets.only(right: 24),
|
if (value) {
|
||||||
child: Container(
|
icons[index] = removeIcon;
|
||||||
width: double.minPositive,
|
colors[index] = Palette.blueCraiola;
|
||||||
child: Center(
|
} else {
|
||||||
child: icons[index]
|
icons[index] = addIcon;
|
||||||
),
|
colors[index] = Theme.of(context).primaryTextTheme.title.color;
|
||||||
),
|
}
|
||||||
),
|
});
|
||||||
backgroundColor: Theme.of(context).accentTextTheme.headline.backgroundColor,
|
},
|
||||||
onExpansionChanged: (value) {
|
|
||||||
setState(() {
|
|
||||||
if (value) {
|
|
||||||
icons[index] = removeIcon;
|
|
||||||
colors[index] = Colors.green;
|
|
||||||
} else {
|
|
||||||
icons[index] = addIcon;
|
|
||||||
colors[index] = Theme.of(context).primaryTextTheme.title.color;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
children: <Widget>[
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Expanded(
|
Row(
|
||||||
child: Container(
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
padding: EdgeInsets.only(
|
children: <Widget>[
|
||||||
left: 24.0,
|
Expanded(
|
||||||
right: 24.0,
|
child: Container(
|
||||||
bottom: 8
|
padding: EdgeInsets.only(
|
||||||
),
|
right: 24.0,
|
||||||
child: Text(
|
),
|
||||||
itemChild,
|
child: Text(
|
||||||
style: TextStyle(
|
itemChild,
|
||||||
fontSize: 12,
|
style: TextStyle(
|
||||||
color: Theme.of(context).primaryTextTheme.title.color
|
fontSize: 14,
|
||||||
),
|
fontWeight: FontWeight.normal,
|
||||||
),
|
color: Theme.of(context).primaryTextTheme.title.color
|
||||||
))
|
),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
],
|
||||||
|
)
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
],
|
);
|
||||||
);
|
},
|
||||||
},
|
separatorBuilder: (_, __) =>
|
||||||
separatorBuilder: (_, __) =>
|
StandardListSeparator(),
|
||||||
Container(color: Theme.of(context).dividerColor, height: 1.0),
|
itemCount: faqItems == null ? 0 : faqItems.length,
|
||||||
itemCount: faqItems == null ? 0 : faqItems.length,
|
)
|
||||||
),
|
],
|
||||||
);
|
),
|
||||||
},
|
);
|
||||||
future: rootBundle.loadString(getFaqPath(context)),
|
},
|
||||||
),
|
future: rootBundle.loadString(getFaqPath(context)),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
Text(title,
|
Text(title,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.w500,
|
||||||
color: Theme.of(context).primaryTextTheme.title.color)),
|
color: Theme.of(context).primaryTextTheme.title.color)),
|
||||||
Spacer(flex: 3),
|
Spacer(flex: 3),
|
||||||
Container(
|
Container(
|
||||||
|
@ -126,7 +126,11 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: isFilled
|
color: isFilled
|
||||||
? Theme.of(context).primaryTextTheme.title.color
|
? Theme.of(context).primaryTextTheme.title.color
|
||||||
: Theme.of(context).primaryTextTheme.caption.color,
|
: Theme.of(context)
|
||||||
|
.accentTextTheme
|
||||||
|
.body1
|
||||||
|
.color
|
||||||
|
.withOpacity(0.25),
|
||||||
));
|
));
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
@ -143,7 +147,11 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
_changePinLengthText(),
|
_changePinLengthText(),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14.0,
|
fontSize: 14.0,
|
||||||
color: Theme.of(context).primaryTextTheme.caption.color),
|
fontWeight: FontWeight.normal,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.accentTextTheme
|
||||||
|
.body1
|
||||||
|
.decorationColor),
|
||||||
))
|
))
|
||||||
],
|
],
|
||||||
Spacer(flex: 1),
|
Spacer(flex: 1),
|
||||||
|
@ -227,7 +235,7 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
child: Text('$index',
|
child: Text('$index',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 30.0,
|
fontSize: 30.0,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.w600,
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.primaryTextTheme
|
.primaryTextTheme
|
||||||
.title
|
.title
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'package:cake_wallet/src/screens/settings/widgets/language_row.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/standard_list.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
@ -16,29 +18,13 @@ class ChangeLanguage extends BasePage {
|
||||||
final settingsStore = Provider.of<SettingsStore>(context);
|
final settingsStore = Provider.of<SettingsStore>(context);
|
||||||
final currentLanguage = Provider.of<Language>(context);
|
final currentLanguage = Provider.of<Language>(context);
|
||||||
|
|
||||||
final currentColor = Colors.green;
|
|
||||||
final notCurrentColor = Theme.of(context).primaryTextTheme.title.color;
|
|
||||||
|
|
||||||
final shortDivider = Container(
|
|
||||||
height: 1,
|
|
||||||
padding: EdgeInsets.only(left: 24),
|
|
||||||
color: Theme.of(context).accentTextTheme.title.backgroundColor,
|
|
||||||
child: Container(
|
|
||||||
height: 1,
|
|
||||||
color: Theme.of(context).dividerColor,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
final longDivider = Container(
|
|
||||||
height: 1,
|
|
||||||
color: Theme.of(context).dividerColor,
|
|
||||||
);
|
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: EdgeInsets.only(top: 10.0),
|
padding: EdgeInsets.only(top: 10.0),
|
||||||
child: ListView.builder(
|
child: SectionStandardList(
|
||||||
itemCount: languages.values.length,
|
sectionCount: 1,
|
||||||
itemBuilder: (BuildContext context, int index) {
|
context: context,
|
||||||
|
itemCounter: (int sectionIndex) => languages.values.length,
|
||||||
|
itemBuilder: (_, sectionIndex, index) {
|
||||||
final item = languages.values.elementAt(index);
|
final item = languages.values.elementAt(index);
|
||||||
final code = languages.keys.elementAt(index);
|
final code = languages.keys.elementAt(index);
|
||||||
|
|
||||||
|
@ -46,52 +32,30 @@ class ChangeLanguage extends BasePage {
|
||||||
? false
|
? false
|
||||||
: code == settingsStore.languageCode;
|
: code == settingsStore.languageCode;
|
||||||
|
|
||||||
return Column(
|
return LanguageRow(
|
||||||
children: <Widget>[
|
title: item,
|
||||||
index == 0 ? longDivider : Offstage(),
|
isSelected: isCurrent,
|
||||||
Container(
|
handler: (context) async {
|
||||||
padding: EdgeInsets.only(top: 4, bottom: 4),
|
if (!isCurrent) {
|
||||||
color: Theme.of(context).accentTextTheme.title.backgroundColor,
|
await showDialog<void>(
|
||||||
child: ListTile(
|
context: context,
|
||||||
contentPadding: EdgeInsets.only(left: 24, right: 24),
|
builder: (BuildContext context) {
|
||||||
title: Text(
|
return AlertWithTwoActions(
|
||||||
item,
|
alertTitle: S.of(context).change_language,
|
||||||
style: TextStyle(
|
alertContent: S.of(context).change_language_to(item),
|
||||||
fontSize: 14.0,
|
leftButtonText: S.of(context).change,
|
||||||
fontWeight: FontWeight.w600,
|
rightButtonText: S.of(context).cancel,
|
||||||
color: isCurrent ? currentColor : notCurrentColor
|
actionLeftButton: () {
|
||||||
),
|
settingsStore.saveLanguageCode(
|
||||||
),
|
languageCode: code);
|
||||||
trailing: isCurrent
|
currentLanguage.setCurrentLanguage(code);
|
||||||
? Icon(Icons.done, color: currentColor)
|
Navigator.of(context).pop();
|
||||||
: Offstage(),
|
},
|
||||||
onTap: () async {
|
actionRightButton: () => Navigator.of(context).pop()
|
||||||
if (!isCurrent) {
|
);
|
||||||
await showDialog<void>(
|
});
|
||||||
context: context,
|
}
|
||||||
builder: (BuildContext context) {
|
},
|
||||||
return AlertWithTwoActions(
|
|
||||||
alertTitle: S.of(context).change_language,
|
|
||||||
alertContent: S.of(context).change_language_to(item),
|
|
||||||
leftButtonText: S.of(context).change,
|
|
||||||
rightButtonText: S.of(context).cancel,
|
|
||||||
actionLeftButton: () {
|
|
||||||
settingsStore.saveLanguageCode(
|
|
||||||
languageCode: code);
|
|
||||||
currentLanguage.setCurrentLanguage(code);
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
actionRightButton: () => Navigator.of(context).pop()
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
item == languages.values.last
|
|
||||||
? longDivider
|
|
||||||
: shortDivider
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'package:cake_wallet/src/screens/settings/widgets/settings_version_cell.dart';
|
||||||
|
import 'package:cake_wallet/view_model/settings/version_list_item.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||||
|
@ -41,6 +43,7 @@ class SettingsPage extends BasePage {
|
||||||
return SettingsPickerCell<dynamic>(
|
return SettingsPickerCell<dynamic>(
|
||||||
title: item.title,
|
title: item.title,
|
||||||
selectedItem: item.selectedItem(),
|
selectedItem: item.selectedItem(),
|
||||||
|
isAlwaysShowScrollThumb: item.isAlwaysShowScrollThumb,
|
||||||
items: item.items,
|
items: item.items,
|
||||||
onItemSelected: (dynamic value) => item.onItemSelected(value),
|
onItemSelected: (dynamic value) => item.onItemSelected(value),
|
||||||
);
|
);
|
||||||
|
@ -57,7 +60,8 @@ class SettingsPage extends BasePage {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item is RegularListItem) {
|
if (item is RegularListItem) {
|
||||||
return SettingsCellWithArrow(title: item.title);
|
return SettingsCellWithArrow(
|
||||||
|
title: item.title, handler: item.handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item is LinkListItem) {
|
if (item is LinkListItem) {
|
||||||
|
@ -68,6 +72,14 @@ class SettingsPage extends BasePage {
|
||||||
linkTitle: item.linkTitle);
|
linkTitle: item.linkTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item is VersionListItem) {
|
||||||
|
return Observer(builder: (_) {
|
||||||
|
return SettingsVersionCell(
|
||||||
|
title:
|
||||||
|
S.of(context).version(settingsViewModel.currentVersion));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return Container();
|
return Container();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
30
lib/src/screens/settings/widgets/language_row.dart
Normal file
30
lib/src/screens/settings/widgets/language_row.dart
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import 'package:cake_wallet/palette.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/standard_list.dart';
|
||||||
|
|
||||||
|
class LanguageRow extends StandardListRow {
|
||||||
|
LanguageRow({@required String title, @required this.isSelected, @required Function(BuildContext context) handler}) :
|
||||||
|
super(title: title, isSelected: isSelected, onTap: handler);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final bool isSelected;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget buildCenter(BuildContext context, {@required bool hasLeftOffset}) {
|
||||||
|
return Expanded(
|
||||||
|
child: Row(mainAxisAlignment: MainAxisAlignment.start, children: [
|
||||||
|
if (hasLeftOffset) SizedBox(width: 10),
|
||||||
|
Text(title,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: titleColor(context)))
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget buildTrailing(BuildContext context) =>
|
||||||
|
isSelected
|
||||||
|
? Icon(Icons.done, color: Palette.blueCraiola)
|
||||||
|
: Offstage();
|
||||||
|
}
|
|
@ -2,11 +2,11 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:cake_wallet/src/widgets/standard_list.dart';
|
import 'package:cake_wallet/src/widgets/standard_list.dart';
|
||||||
|
|
||||||
class SettingsCellWithArrow extends StandardListRow {
|
class SettingsCellWithArrow extends StandardListRow {
|
||||||
SettingsCellWithArrow({@required String title})
|
SettingsCellWithArrow({@required String title, @required Function(BuildContext context) handler})
|
||||||
: super(title: title, isSelected: false);
|
: super(title: title, isSelected: false, onTap: handler);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildTrailing(BuildContext context) =>
|
Widget buildTrailing(BuildContext context) =>
|
||||||
Image.asset('assets/images/select_arrow.png',
|
Image.asset('assets/images/select_arrow.png',
|
||||||
color: Theme.of(context).primaryTextTheme.caption.color);
|
color: Theme.of(context).primaryTextTheme.overline.color);
|
||||||
}
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
|
import 'package:cake_wallet/palette.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cake_wallet/src/widgets/standard_list.dart';
|
import 'package:cake_wallet/src/widgets/standard_list.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class SettingsLinkProviderCell extends StandardListRow {
|
class SettingsLinkProviderCell extends StandardListRow {
|
||||||
SettingsLinkProviderCell(
|
SettingsLinkProviderCell(
|
||||||
|
@ -7,7 +9,7 @@ class SettingsLinkProviderCell extends StandardListRow {
|
||||||
@required this.icon,
|
@required this.icon,
|
||||||
@required this.link,
|
@required this.link,
|
||||||
@required this.linkTitle})
|
@required this.linkTitle})
|
||||||
: super(title: title, isSelected: false);
|
: super(title: title, isSelected: false, onTap: (BuildContext context) => _launchUrl(link) );
|
||||||
|
|
||||||
final String icon;
|
final String icon;
|
||||||
final String link;
|
final String link;
|
||||||
|
@ -20,5 +22,11 @@ class SettingsLinkProviderCell extends StandardListRow {
|
||||||
@override
|
@override
|
||||||
Widget buildTrailing(BuildContext context) => Text(linkTitle,
|
Widget buildTrailing(BuildContext context) => Text(linkTitle,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14.0, fontWeight: FontWeight.w500, color: Colors.blue));
|
fontSize: 14.0,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Palette.blueCraiola));
|
||||||
|
|
||||||
|
static void _launchUrl(String url) async {
|
||||||
|
if (await canLaunch(url)) await launch(url);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -8,7 +8,8 @@ class SettingsPickerCell<ItemType> extends StandardListRow {
|
||||||
{@required String title,
|
{@required String title,
|
||||||
this.selectedItem,
|
this.selectedItem,
|
||||||
this.items,
|
this.items,
|
||||||
this.onItemSelected})
|
this.onItemSelected,
|
||||||
|
this.isAlwaysShowScrollThumb})
|
||||||
: super(
|
: super(
|
||||||
title: title,
|
title: title,
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
|
@ -22,12 +23,15 @@ class SettingsPickerCell<ItemType> extends StandardListRow {
|
||||||
selectedAtIndex: selectedAtIndex,
|
selectedAtIndex: selectedAtIndex,
|
||||||
title: S.current.please_select,
|
title: S.current.please_select,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
onItemSelected: (ItemType item) => onItemSelected?.call(item)));
|
isAlwaysShowScrollThumb: isAlwaysShowScrollThumb,
|
||||||
|
onItemSelected: (ItemType item) =>
|
||||||
|
onItemSelected?.call(item)));
|
||||||
});
|
});
|
||||||
|
|
||||||
final ItemType selectedItem;
|
final ItemType selectedItem;
|
||||||
final List<ItemType> items;
|
final List<ItemType> items;
|
||||||
final void Function(ItemType item) onItemSelected;
|
final void Function(ItemType item) onItemSelected;
|
||||||
|
final bool isAlwaysShowScrollThumb;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildTrailing(BuildContext context) {
|
Widget buildTrailing(BuildContext context) {
|
||||||
|
@ -37,7 +41,7 @@ class SettingsPickerCell<ItemType> extends StandardListRow {
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14.0,
|
fontSize: 14.0,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Theme.of(context).primaryTextTheme.caption.color),
|
color: Theme.of(context).primaryTextTheme.overline.color),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,9 @@ class SettingsSwitcherCell extends StandardListRow {
|
||||||
: super(title: title, isSelected: false);
|
: super(title: title, isSelected: false);
|
||||||
|
|
||||||
final bool value;
|
final bool value;
|
||||||
final void Function(bool value) onValueChange;
|
final void Function(BuildContext context, bool value) onValueChange;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildTrailing(BuildContext context) =>
|
Widget buildTrailing(BuildContext context) => StandartSwitch(
|
||||||
StandartSwitch(value: value, onTaped: () => onValueChange(!value));
|
value: value, onTaped: () => onValueChange(context, !value));
|
||||||
}
|
}
|
||||||
|
|
28
lib/src/screens/settings/widgets/settings_version_cell.dart
Normal file
28
lib/src/screens/settings/widgets/settings_version_cell.dart
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class SettingsVersionCell extends StatelessWidget {
|
||||||
|
SettingsVersionCell({@required this.title});
|
||||||
|
|
||||||
|
final String title;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.only(bottom: 24),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
color: Theme.of(context).primaryTextTheme.overline.color
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -53,7 +53,7 @@ class _SetupPinCodeFormState<WidgetType extends SetupPinCodeForm>
|
||||||
state.clear();
|
state.clear();
|
||||||
} else {
|
} else {
|
||||||
if (listEquals<int>(state.pin, _originalPin)) {
|
if (listEquals<int>(state.pin, _originalPin)) {
|
||||||
final String pin = state.pin.fold("", (ac, val) => ac + '$val');
|
final String pin = state.pin.fold('', (ac, val) => ac + '$val');
|
||||||
_userStore.set(password: pin);
|
_userStore.set(password: pin);
|
||||||
_settingsStore.setDefaultPinLength(pinLength: state.pinLength);
|
_settingsStore.setDefaultPinLength(pinLength: state.pinLength);
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||||
import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart';
|
import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
|
@ -36,10 +37,14 @@ class WalletMenu {
|
||||||
];
|
];
|
||||||
|
|
||||||
final List<Image> listImages = [
|
final List<Image> listImages = [
|
||||||
Image.asset('assets/images/load.png', height: 24, width: 24, color: Colors.white),
|
Image.asset('assets/images/load.png',
|
||||||
Image.asset('assets/images/eye_action.png', height: 24, width: 24, color: Colors.white),
|
height: 24, width: 24, color: Colors.white),
|
||||||
Image.asset('assets/images/trash.png', height: 24, width: 24, color: Colors.white),
|
Image.asset('assets/images/eye_action.png',
|
||||||
Image.asset('assets/images/scanner.png', height: 24, width: 24, color: Colors.white)
|
height: 24, width: 24, color: Colors.white),
|
||||||
|
Image.asset('assets/images/trash.png',
|
||||||
|
height: 24, width: 24, color: Colors.white),
|
||||||
|
Image.asset('assets/images/scanner.png',
|
||||||
|
height: 24, width: 24, color: Colors.white)
|
||||||
];
|
];
|
||||||
|
|
||||||
List<String> generateItemsForWalletMenu(bool isCurrentWallet) {
|
List<String> generateItemsForWalletMenu(bool isCurrentWallet) {
|
||||||
|
@ -87,10 +92,11 @@ class WalletMenu {
|
||||||
return images;
|
return images;
|
||||||
}
|
}
|
||||||
|
|
||||||
void action(int index, WalletListItem wallet, bool isCurrentWallet) {
|
Future<void> action(
|
||||||
|
int index, WalletListItem wallet, bool isCurrentWallet) async {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
Navigator.of(context).pushNamed(Routes.auth, arguments:
|
await Navigator.of(context).pushNamed(Routes.auth, arguments:
|
||||||
(bool isAuthenticatedSuccessfully, AuthPageState auth) async {
|
(bool isAuthenticatedSuccessfully, AuthPageState auth) async {
|
||||||
if (!isAuthenticatedSuccessfully) {
|
if (!isAuthenticatedSuccessfully) {
|
||||||
return;
|
return;
|
||||||
|
@ -110,7 +116,7 @@ class WalletMenu {
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
Navigator.of(context).pushNamed(Routes.auth, arguments:
|
await Navigator.of(context).pushNamed(Routes.auth, arguments:
|
||||||
(bool isAuthenticatedSuccessfully, AuthPageState auth) async {
|
(bool isAuthenticatedSuccessfully, AuthPageState auth) async {
|
||||||
if (!isAuthenticatedSuccessfully) {
|
if (!isAuthenticatedSuccessfully) {
|
||||||
return;
|
return;
|
||||||
|
@ -120,7 +126,23 @@ class WalletMenu {
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
Navigator.of(context).pushNamed(Routes.auth, arguments:
|
final isComfirmed = await showDialog<bool>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertWithTwoActions(
|
||||||
|
alertTitle: 'Remove wallet',
|
||||||
|
alertContent: S.of(context).confirm_delete_wallet,
|
||||||
|
leftButtonText: S.of(context).cancel,
|
||||||
|
rightButtonText: S.of(context).remove,
|
||||||
|
actionLeftButton: () => Navigator.of(context).pop(false),
|
||||||
|
actionRightButton: () => Navigator.of(context).pop(true));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isComfirmed == null || !isComfirmed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Navigator.of(context).pushNamed(Routes.auth, arguments:
|
||||||
(bool isAuthenticatedSuccessfully, AuthPageState auth) async {
|
(bool isAuthenticatedSuccessfully, AuthPageState auth) async {
|
||||||
if (!isAuthenticatedSuccessfully) {
|
if (!isAuthenticatedSuccessfully) {
|
||||||
return;
|
return;
|
||||||
|
@ -139,7 +161,7 @@ class WalletMenu {
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
Navigator.of(context).pushNamed(Routes.rescan);
|
await Navigator.of(context).pushNamed(Routes.rescan);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -123,9 +123,7 @@ class PickerState<Item> extends State<Picker> {
|
||||||
mainAxisAlignment: widget.mainAxisAlignment,
|
mainAxisAlignment: widget.mainAxisAlignment,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
image != null
|
image ?? Offstage(),
|
||||||
? image
|
|
||||||
: Offstage(),
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
left: image != null ? 12 : 0
|
left: image != null ? 12 : 0
|
||||||
|
|
|
@ -206,85 +206,84 @@ class SeedWidgetState extends State<SeedWidget> {
|
||||||
fit: FlexFit.tight,
|
fit: FlexFit.tight,
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: Container(
|
child: Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: double.infinity,
|
height: double.infinity,
|
||||||
padding: EdgeInsets.all(0),
|
padding: EdgeInsets.all(0),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.only(
|
borderRadius: BorderRadius.only(
|
||||||
bottomLeft: Radius.circular(24),
|
bottomLeft: Radius.circular(24),
|
||||||
bottomRight: Radius.circular(24)),
|
bottomRight: Radius.circular(24)),
|
||||||
gradient: LinearGradient(colors: [
|
gradient: LinearGradient(colors: [
|
||||||
Theme.of(context).primaryTextTheme.subhead.color,
|
Theme.of(context).primaryTextTheme.subhead.color,
|
||||||
Theme.of(context).primaryTextTheme.subhead.decorationColor,
|
Theme.of(context).primaryTextTheme.subhead.decorationColor,
|
||||||
],
|
], begin: Alignment.topLeft, end: Alignment.bottomRight)),
|
||||||
begin: Alignment.topLeft,
|
child: Column(
|
||||||
end: Alignment.bottomRight)
|
children: <Widget>[
|
||||||
),
|
CupertinoNavigationBar(
|
||||||
child: Column(
|
leading: widget.leading,
|
||||||
children: <Widget>[
|
middle: widget.middle,
|
||||||
CupertinoNavigationBar(
|
backgroundColor: Colors.transparent,
|
||||||
leading: widget.leading,
|
border: null,
|
||||||
middle: widget.middle,
|
),
|
||||||
backgroundColor: Colors.transparent,
|
Expanded(
|
||||||
border: null,
|
child: Container(
|
||||||
),
|
padding: EdgeInsets.all(24),
|
||||||
Expanded(
|
alignment: Alignment.topLeft,
|
||||||
child: Container(
|
child: SingleChildScrollView(
|
||||||
padding: EdgeInsets.all(24),
|
child: Column(
|
||||||
alignment: Alignment.topLeft,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
child: SingleChildScrollView(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
child: Column(
|
children: <Widget>[
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
Text(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
S.of(context).restore_active_seed,
|
||||||
children: <Widget>[
|
style: TextStyle(
|
||||||
Text(
|
fontSize: 14,
|
||||||
S.of(context).restore_active_seed,
|
fontWeight: FontWeight.w500,
|
||||||
style: TextStyle(
|
color: Theme.of(context)
|
||||||
fontSize: 14,
|
.textTheme
|
||||||
fontWeight: FontWeight.w500,
|
.overline
|
||||||
color:
|
.backgroundColor),
|
||||||
Theme.of(context).textTheme.overline.backgroundColor),
|
),
|
||||||
),
|
Padding(
|
||||||
Padding(
|
padding: EdgeInsets.only(top: 5),
|
||||||
padding: EdgeInsets.only(top: 5),
|
child: Wrap(
|
||||||
child: Wrap(
|
children: items.map((item) {
|
||||||
children: items.map((item) {
|
final isValid =
|
||||||
final isValid = widget.validator.isValid(item);
|
widget.validator.isValid(item);
|
||||||
final isSelected = selectedItem == item;
|
final isSelected = selectedItem == item;
|
||||||
|
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () => onMnemonicTap(item),
|
onTap: () => onMnemonicTap(item),
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
color: isValid
|
||||||
|
? Colors.transparent
|
||||||
|
: Palette.red),
|
||||||
|
margin: EdgeInsets.only(
|
||||||
|
right: 7, bottom: 8),
|
||||||
|
child: Text(
|
||||||
|
item.toString(),
|
||||||
|
style: TextStyle(
|
||||||
color: isValid
|
color: isValid
|
||||||
? Colors.transparent
|
? Colors.white
|
||||||
: Palette.red),
|
: Colors.grey,
|
||||||
margin: EdgeInsets.only(right: 7, bottom: 8),
|
fontSize: 16,
|
||||||
child: Text(
|
fontWeight: isSelected
|
||||||
item.toString(),
|
? FontWeight.w900
|
||||||
style: TextStyle(
|
: FontWeight.w600,
|
||||||
color: isValid
|
decoration: isSelected
|
||||||
? Colors.white
|
? TextDecoration.underline
|
||||||
: Colors.grey,
|
: TextDecoration.none),
|
||||||
fontSize: 16,
|
)),
|
||||||
fontWeight: isSelected
|
);
|
||||||
? FontWeight.w900
|
}).toList(),
|
||||||
: FontWeight.w600,
|
))
|
||||||
decoration: isSelected
|
],
|
||||||
? TextDecoration.underline
|
|
||||||
: TextDecoration.none),
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
)
|
))
|
||||||
],
|
],
|
||||||
)
|
)),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Flexible(
|
Flexible(
|
||||||
fit: FlexFit.tight,
|
fit: FlexFit.tight,
|
||||||
|
@ -372,11 +371,17 @@ class SeedWidgetState extends State<SeedWidget> {
|
||||||
errorText: _errorMessage,
|
errorText: _errorMessage,
|
||||||
focusedBorder: UnderlineInputBorder(
|
focusedBorder: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: Theme.of(context).accentTextTheme.subtitle.backgroundColor,
|
color: Theme.of(context)
|
||||||
|
.accentTextTheme
|
||||||
|
.subtitle
|
||||||
|
.backgroundColor,
|
||||||
width: 1.0)),
|
width: 1.0)),
|
||||||
enabledBorder: UnderlineInputBorder(
|
enabledBorder: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: Theme.of(context).accentTextTheme.subtitle.backgroundColor,
|
color: Theme.of(context)
|
||||||
|
.accentTextTheme
|
||||||
|
.subtitle
|
||||||
|
.backgroundColor,
|
||||||
width: 1.0))),
|
width: 1.0))),
|
||||||
enableInteractiveSelection: false,
|
enableInteractiveSelection: false,
|
||||||
),
|
),
|
||||||
|
|
|
@ -41,18 +41,17 @@ class StandardListRow extends StatelessWidget {
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.normal,
|
fontWeight: FontWeight.normal,
|
||||||
color: _titleColor(context)))
|
color: titleColor(context)))
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildTrailing(BuildContext context) => null;
|
Widget buildTrailing(BuildContext context) => null;
|
||||||
|
|
||||||
Color _titleColor(BuildContext context) => isSelected
|
Color titleColor(BuildContext context) => isSelected
|
||||||
? Palette.blueCraiola
|
? Palette.blueCraiola
|
||||||
: Theme.of(context).primaryTextTheme.title.color;
|
: Theme.of(context).primaryTextTheme.title.color;
|
||||||
|
|
||||||
Color _backgroundColor(BuildContext context) {
|
Color _backgroundColor(BuildContext context) {
|
||||||
// return Theme.of(context).accentTextTheme.subtitle.decorationColor;
|
|
||||||
return Theme.of(context).backgroundColor;
|
return Theme.of(context).backgroundColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,16 +113,20 @@ class SectionStandardList extends StatelessWidget {
|
||||||
{@required this.itemCounter,
|
{@required this.itemCounter,
|
||||||
@required this.itemBuilder,
|
@required this.itemBuilder,
|
||||||
@required this.sectionCount,
|
@required this.sectionCount,
|
||||||
|
this.hasTopSeparator = false,
|
||||||
BuildContext context})
|
BuildContext context})
|
||||||
: totalRows = transform(context, sectionCount, itemCounter, itemBuilder);
|
: totalRows = transform(hasTopSeparator, context, sectionCount,
|
||||||
|
itemCounter, itemBuilder);
|
||||||
|
|
||||||
final int sectionCount;
|
final int sectionCount;
|
||||||
|
final bool hasTopSeparator;
|
||||||
final int Function(int sectionIndex) itemCounter;
|
final int Function(int sectionIndex) itemCounter;
|
||||||
final Widget Function(BuildContext context, int sectionIndex, int itemIndex)
|
final Widget Function(BuildContext context, int sectionIndex, int itemIndex)
|
||||||
itemBuilder;
|
itemBuilder;
|
||||||
final List<Widget> totalRows;
|
final List<Widget> totalRows;
|
||||||
|
|
||||||
static List<Widget> transform(
|
static List<Widget> transform(
|
||||||
|
bool hasTopSeparator,
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
int sectionCount,
|
int sectionCount,
|
||||||
int Function(int sectionIndex) itemCounter,
|
int Function(int sectionIndex) itemCounter,
|
||||||
|
@ -132,9 +135,9 @@ class SectionStandardList extends StatelessWidget {
|
||||||
final items = <Widget>[];
|
final items = <Widget>[];
|
||||||
|
|
||||||
for (var sectionIndex = 0; sectionIndex < sectionCount; sectionIndex++) {
|
for (var sectionIndex = 0; sectionIndex < sectionCount; sectionIndex++) {
|
||||||
/*if (sectionIndex == 0) {
|
if ((sectionIndex == 0)&&(hasTopSeparator)) {
|
||||||
items.add(StandardListSeparator());
|
items.add(StandardListSeparator(padding: EdgeInsets.only(left: 24)));
|
||||||
}*/
|
}
|
||||||
|
|
||||||
final itemCount = itemCounter(sectionIndex);
|
final itemCount = itemCounter(sectionIndex);
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ class StandartSwitchState extends State<StandartSwitch> {
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: widget.value
|
color: widget.value
|
||||||
? Colors.green
|
? Colors.green
|
||||||
: PaletteDark.distantBlue,
|
: Theme.of(context).accentTextTheme.display4.color,
|
||||||
borderRadius: BorderRadius.all(Radius.circular(14.0))),
|
borderRadius: BorderRadius.all(Radius.circular(14.0))),
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 24.0,
|
width: 24.0,
|
||||||
|
|
|
@ -47,6 +47,11 @@ abstract class SettingsStoreBase with Store {
|
||||||
this.nodes = ObservableMap<WalletType, Node>.of(nodes);
|
this.nodes = ObservableMap<WalletType, Node>.of(nodes);
|
||||||
_sharedPreferences = sharedPreferences;
|
_sharedPreferences = sharedPreferences;
|
||||||
_nodeSource = nodeSource;
|
_nodeSource = nodeSource;
|
||||||
|
|
||||||
|
reaction(
|
||||||
|
(_) => allowBiometricalAuthentication,
|
||||||
|
(bool biometricalAuthentication) => sharedPreferences.setBool(
|
||||||
|
allowBiometricalAuthenticationKey, biometricalAuthentication));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const currentNodeIdKey = 'current_node_id';
|
static const currentNodeIdKey = 'current_node_id';
|
||||||
|
@ -62,9 +67,6 @@ abstract class SettingsStoreBase with Store {
|
||||||
static const currentPinLength = 'current_pin_length';
|
static const currentPinLength = 'current_pin_length';
|
||||||
static const currentLanguageCode = 'language_code';
|
static const currentLanguageCode = 'language_code';
|
||||||
|
|
||||||
// @observable
|
|
||||||
// Node node;
|
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
FiatCurrency fiatCurrency;
|
FiatCurrency fiatCurrency;
|
||||||
|
|
||||||
|
|
|
@ -160,6 +160,13 @@ class Themes {
|
||||||
color: Palette.darkGray, // hint text (new wallet page)
|
color: Palette.darkGray, // hint text (new wallet page)
|
||||||
decorationColor: Palette.periwinkleCraiola // underline (new wallet page)
|
decorationColor: Palette.periwinkleCraiola // underline (new wallet page)
|
||||||
),
|
),
|
||||||
|
display4: TextStyle(
|
||||||
|
color: Palette.darkGray, // switch background (settings page)
|
||||||
|
),
|
||||||
|
body1: TextStyle(
|
||||||
|
color: Palette.darkGray, // indicators (PIN code)
|
||||||
|
decorationColor: Palette.darkGray // switch (PIN code)
|
||||||
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
||||||
|
@ -331,6 +338,13 @@ class Themes {
|
||||||
color: PaletteDark.cyanBlue, // hint text (new wallet page)
|
color: PaletteDark.cyanBlue, // hint text (new wallet page)
|
||||||
decorationColor: PaletteDark.darkGrey // underline (new wallet page)
|
decorationColor: PaletteDark.darkGrey // underline (new wallet page)
|
||||||
),
|
),
|
||||||
|
display4: TextStyle(
|
||||||
|
color: PaletteDark.deepVioletBlue, // switch background (settings page)
|
||||||
|
),
|
||||||
|
body1: TextStyle(
|
||||||
|
color: PaletteDark.indicatorVioletBlue, // indicators (PIN code)
|
||||||
|
decorationColor: PaletteDark.lightPurpleBlue // switch (PIN code)
|
||||||
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,15 @@ class PickerListItem<ItemType> extends SettingsListItem {
|
||||||
{@required String title,
|
{@required String title,
|
||||||
@required this.selectedItem,
|
@required this.selectedItem,
|
||||||
@required this.items,
|
@required this.items,
|
||||||
void Function(ItemType item) onItemSelected})
|
void Function(ItemType item) onItemSelected,
|
||||||
|
this.isAlwaysShowScrollThumb = false})
|
||||||
: _onItemSelected = onItemSelected,
|
: _onItemSelected = onItemSelected,
|
||||||
super(title);
|
super(title);
|
||||||
|
|
||||||
final ItemType Function() selectedItem;
|
final ItemType Function() selectedItem;
|
||||||
final List<ItemType> items;
|
final List<ItemType> items;
|
||||||
final void Function(ItemType item) _onItemSelected;
|
final void Function(ItemType item) _onItemSelected;
|
||||||
|
final bool isAlwaysShowScrollThumb;
|
||||||
|
|
||||||
void onItemSelected(dynamic item) {
|
void onItemSelected(dynamic item) {
|
||||||
if (item is ItemType) {
|
if (item is ItemType) {
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import 'package:cake_wallet/core/wallet_base.dart';
|
import 'package:cake_wallet/core/wallet_base.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/common/biometric_auth.dart';
|
||||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||||
import 'package:cake_wallet/di.dart';
|
import 'package:cake_wallet/di.dart';
|
||||||
import 'package:cake_wallet/store/theme_changer_store.dart';
|
import 'package:cake_wallet/store/theme_changer_store.dart';
|
||||||
import 'package:cake_wallet/themes.dart';
|
import 'package:cake_wallet/themes.dart';
|
||||||
|
import 'package:cake_wallet/view_model/settings/version_list_item.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
|
@ -19,6 +21,7 @@ import 'package:cake_wallet/view_model/settings/picker_list_item.dart';
|
||||||
import 'package:cake_wallet/view_model/settings/regular_list_item.dart';
|
import 'package:cake_wallet/view_model/settings/regular_list_item.dart';
|
||||||
import 'package:cake_wallet/view_model/settings/settings_list_item.dart';
|
import 'package:cake_wallet/view_model/settings/settings_list_item.dart';
|
||||||
import 'package:cake_wallet/view_model/settings/switcher_list_item.dart';
|
import 'package:cake_wallet/view_model/settings/switcher_list_item.dart';
|
||||||
|
import 'package:package_info/package_info.dart';
|
||||||
|
|
||||||
part 'settings_view_model.g.dart';
|
part 'settings_view_model.g.dart';
|
||||||
|
|
||||||
|
@ -27,7 +30,11 @@ class SettingsViewModel = SettingsViewModelBase with _$SettingsViewModel;
|
||||||
abstract class SettingsViewModelBase with Store {
|
abstract class SettingsViewModelBase with Store {
|
||||||
SettingsViewModelBase(this._settingsStore, WalletBase wallet)
|
SettingsViewModelBase(this._settingsStore, WalletBase wallet)
|
||||||
: itemHeaders = {},
|
: itemHeaders = {},
|
||||||
_walletType = wallet.type {
|
_walletType = wallet.type,
|
||||||
|
_biometricAuth = BiometricAuth() {
|
||||||
|
currentVersion = '';
|
||||||
|
PackageInfo.fromPlatform().then(
|
||||||
|
(PackageInfo packageInfo) => currentVersion = packageInfo.version);
|
||||||
sections = [
|
sections = [
|
||||||
[
|
[
|
||||||
PickerListItem(
|
PickerListItem(
|
||||||
|
@ -37,17 +44,22 @@ abstract class SettingsViewModelBase with Store {
|
||||||
PickerListItem(
|
PickerListItem(
|
||||||
title: S.current.settings_currency,
|
title: S.current.settings_currency,
|
||||||
items: FiatCurrency.all,
|
items: FiatCurrency.all,
|
||||||
selectedItem: () => fiatCurrency),
|
isAlwaysShowScrollThumb: true,
|
||||||
|
selectedItem: () => fiatCurrency,
|
||||||
|
onItemSelected: (FiatCurrency currency) =>
|
||||||
|
setFiatCurrency(currency)),
|
||||||
PickerListItem(
|
PickerListItem(
|
||||||
title: S.current.settings_fee_priority,
|
title: S.current.settings_fee_priority,
|
||||||
items: _transactionPriorities(wallet.type),
|
items: _transactionPriorities(wallet.type),
|
||||||
selectedItem: () => transactionPriority,
|
selectedItem: () => transactionPriority,
|
||||||
|
isAlwaysShowScrollThumb: true,
|
||||||
onItemSelected: (TransactionPriority priority) =>
|
onItemSelected: (TransactionPriority priority) =>
|
||||||
_settingsStore.transactionPriority = priority),
|
_settingsStore.transactionPriority = priority),
|
||||||
SwitcherListItem(
|
SwitcherListItem(
|
||||||
title: S.current.settings_save_recipient_address,
|
title: S.current.settings_save_recipient_address,
|
||||||
value: () => shouldSaveRecipientAddress,
|
value: () => shouldSaveRecipientAddress,
|
||||||
onValueChange: (bool value) => setShouldSaveRecipientAddress(value))
|
onValueChange: (_, bool value) =>
|
||||||
|
setShouldSaveRecipientAddress(value))
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
RegularListItem(
|
RegularListItem(
|
||||||
|
@ -72,12 +84,32 @@ abstract class SettingsViewModelBase with Store {
|
||||||
SwitcherListItem(
|
SwitcherListItem(
|
||||||
title: S.current.settings_allow_biometrical_authentication,
|
title: S.current.settings_allow_biometrical_authentication,
|
||||||
value: () => allowBiometricalAuthentication,
|
value: () => allowBiometricalAuthentication,
|
||||||
onValueChange: (bool value) =>
|
onValueChange: (BuildContext context, bool value) {
|
||||||
setAllowBiometricalAuthentication(value)),
|
if (value) {
|
||||||
|
Navigator.of(context).pushNamed(Routes.auth, arguments:
|
||||||
|
(bool isAuthenticatedSuccessfully,
|
||||||
|
AuthPageState auth) async {
|
||||||
|
if (isAuthenticatedSuccessfully) {
|
||||||
|
if (await _biometricAuth.canCheckBiometrics() &&
|
||||||
|
await _biometricAuth.isAuthenticated()) {
|
||||||
|
setAllowBiometricalAuthentication(
|
||||||
|
isAuthenticatedSuccessfully);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setAllowBiometricalAuthentication(
|
||||||
|
isAuthenticatedSuccessfully);
|
||||||
|
}
|
||||||
|
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setAllowBiometricalAuthentication(value);
|
||||||
|
}
|
||||||
|
}),
|
||||||
SwitcherListItem(
|
SwitcherListItem(
|
||||||
title: S.current.settings_dark_mode,
|
title: S.current.settings_dark_mode,
|
||||||
value: () => _settingsStore.isDarkTheme,
|
value: () => _settingsStore.isDarkTheme,
|
||||||
onValueChange: (bool value) {
|
onValueChange: (_, bool value) {
|
||||||
_settingsStore.isDarkTheme = value;
|
_settingsStore.isDarkTheme = value;
|
||||||
getIt
|
getIt
|
||||||
.get<ThemeChangerStore>()
|
.get<ThemeChangerStore>()
|
||||||
|
@ -119,11 +151,20 @@ abstract class SettingsViewModelBase with Store {
|
||||||
title: S.current.settings_terms_and_conditions,
|
title: S.current.settings_terms_and_conditions,
|
||||||
handler: (BuildContext context) =>
|
handler: (BuildContext context) =>
|
||||||
Navigator.of(context).pushNamed(Routes.disclaimer),
|
Navigator.of(context).pushNamed(Routes.disclaimer),
|
||||||
|
),
|
||||||
|
RegularListItem(
|
||||||
|
title: S.current.faq,
|
||||||
|
handler: (BuildContext context) =>
|
||||||
|
Navigator.pushNamed(context, Routes.faq),
|
||||||
)
|
)
|
||||||
]
|
],
|
||||||
|
[VersionListItem(title: currentVersion)]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@observable
|
||||||
|
String currentVersion;
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
Node get node => _settingsStore.getCurrentNode(_walletType);
|
Node get node => _settingsStore.getCurrentNode(_walletType);
|
||||||
|
|
||||||
|
@ -151,10 +192,18 @@ abstract class SettingsViewModelBase with Store {
|
||||||
_settingsStore.allowBiometricalAuthentication;
|
_settingsStore.allowBiometricalAuthentication;
|
||||||
|
|
||||||
final Map<String, String> itemHeaders;
|
final Map<String, String> itemHeaders;
|
||||||
|
List<List<SettingsListItem>> sections;
|
||||||
final SettingsStore _settingsStore;
|
final SettingsStore _settingsStore;
|
||||||
final WalletType _walletType;
|
final WalletType _walletType;
|
||||||
List<List<SettingsListItem>> sections;
|
final BiometricAuth _biometricAuth;
|
||||||
|
|
||||||
|
@action
|
||||||
|
void setBalanceDisplayMode(BalanceDisplayMode value) =>
|
||||||
|
_settingsStore.balanceDisplayMode = value;
|
||||||
|
|
||||||
|
@action
|
||||||
|
void setFiatCurrency(FiatCurrency value) =>
|
||||||
|
_settingsStore.fiatCurrency = value;
|
||||||
@action
|
@action
|
||||||
void setShouldSaveRecipientAddress(bool value) =>
|
void setShouldSaveRecipientAddress(bool value) =>
|
||||||
_settingsStore.shouldSaveRecipientAddress = value;
|
_settingsStore.shouldSaveRecipientAddress = value;
|
||||||
|
@ -190,11 +239,6 @@ abstract class SettingsViewModelBase with Store {
|
||||||
@action
|
@action
|
||||||
void _showTrades() => actionlistDisplayMode.add(ActionListDisplayMode.trades);
|
void _showTrades() => actionlistDisplayMode.add(ActionListDisplayMode.trades);
|
||||||
|
|
||||||
//
|
|
||||||
// @observable
|
|
||||||
// int defaultPinLength;
|
|
||||||
// bool isDarkTheme;
|
|
||||||
|
|
||||||
static List<TransactionPriority> _transactionPriorities(WalletType type) {
|
static List<TransactionPriority> _transactionPriorities(WalletType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case WalletType.monero:
|
case WalletType.monero:
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:cake_wallet/view_model/settings/settings_list_item.dart';
|
import 'package:cake_wallet/view_model/settings/settings_list_item.dart';
|
||||||
|
|
||||||
class SwitcherListItem extends SettingsListItem {
|
class SwitcherListItem extends SettingsListItem {
|
||||||
SwitcherListItem(
|
SwitcherListItem(
|
||||||
{@required String title,
|
{@required String title,
|
||||||
@required this.value,
|
@required this.value,
|
||||||
@required this.onValueChange})
|
@required this.onValueChange})
|
||||||
: super(title);
|
: super(title);
|
||||||
|
|
||||||
final bool Function() value;
|
final bool Function() value;
|
||||||
final void Function(bool value) onValueChange;
|
final void Function(BuildContext context, bool value) onValueChange;
|
||||||
}
|
}
|
||||||
|
|
6
lib/view_model/settings/version_list_item.dart
Normal file
6
lib/view_model/settings/version_list_item.dart
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:cake_wallet/view_model/settings/settings_list_item.dart';
|
||||||
|
|
||||||
|
class VersionListItem extends SettingsListItem {
|
||||||
|
VersionListItem({@required String title}) : super(title);
|
||||||
|
}
|
|
@ -27,7 +27,7 @@ abstract class WalletCreationVMBase with Store {
|
||||||
|
|
||||||
final bool isRecovery;
|
final bool isRecovery;
|
||||||
|
|
||||||
Box<WalletInfo> _walletInfoSource;
|
final Box<WalletInfo> _walletInfoSource;
|
||||||
|
|
||||||
Future<void> create({dynamic options}) async {
|
Future<void> create({dynamic options}) async {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"welcome" : "Welcome to",
|
"welcome" : "Welcome to",
|
||||||
"cake_wallet" : "Cake Wallet",
|
"cake_wallet" : "Cake Wallet",
|
||||||
"first_wallet_text" : "Awesome wallet for Monero",
|
"first_wallet_text" : "Awesome wallet for Monero and Bitcoin",
|
||||||
"please_make_selection" : "Please make selection below to create or recover your wallet.",
|
"please_make_selection" : "Please make selection below to create or recover your wallet.",
|
||||||
"create_new" : "Create New Wallet",
|
"create_new" : "Create New Wallet",
|
||||||
"restore_wallet" : "Restore Wallet",
|
"restore_wallet" : "Restore Wallet",
|
||||||
|
|
Loading…
Reference in a new issue