Merge branch '4.1.0' into CAKE-216-exchange-status-bug
BIN
assets/images/2.0x/transfer.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
assets/images/2.0x/upload.png
Normal file
After Width: | Height: | Size: 760 B |
BIN
assets/images/3.0x/transfer.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/images/3.0x/upload.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 408 B After Width: | Height: | Size: 629 B |
Before Width: | Height: | Size: 341 B After Width: | Height: | Size: 440 B |
|
@ -354,7 +354,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 7;
|
||||
DEVELOPMENT_TEAM = 32J6BB6VUS;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
|
@ -371,7 +371,7 @@
|
|||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
MARKETING_VERSION = 4.0.9;
|
||||
MARKETING_VERSION = 4.1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
|
@ -494,7 +494,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 7;
|
||||
DEVELOPMENT_TEAM = 32J6BB6VUS;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
|
@ -511,7 +511,7 @@
|
|||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
MARKETING_VERSION = 4.0.9;
|
||||
MARKETING_VERSION = 4.1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
|
@ -528,7 +528,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 7;
|
||||
DEVELOPMENT_TEAM = 32J6BB6VUS;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
|
@ -545,7 +545,7 @@
|
|||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
MARKETING_VERSION = 4.0.9;
|
||||
MARKETING_VERSION = 4.1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
|
|
25
lib/bitcoin/address_to_output_script.dart
Normal file
|
@ -0,0 +1,25 @@
|
|||
import 'dart:typed_data';
|
||||
import 'package:bs58check/bs58check.dart' as bs58check;
|
||||
import 'package:bitcoin_flutter/src/utils/constants/op.dart';
|
||||
import 'package:bitcoin_flutter/src/utils/script.dart' as bscript;
|
||||
import 'package:bitcoin_flutter/src/address.dart';
|
||||
|
||||
|
||||
Uint8List p2shAddressToOutputScript(String address) {
|
||||
final decodeBase58 = bs58check.decode(address);
|
||||
final hash = decodeBase58.sublist(1);
|
||||
return bscript.compile(<dynamic>[OPS['OP_HASH160'], hash, OPS['OP_EQUAL']]);
|
||||
}
|
||||
|
||||
Uint8List addressToOutputScript(String address) {
|
||||
try {
|
||||
// FIXME: improve validation for p2sh addresses
|
||||
if (address.startsWith('3')) {
|
||||
return p2shAddressToOutputScript(address);
|
||||
}
|
||||
|
||||
return Address.addressToOutputScript(address);
|
||||
} catch (_) {
|
||||
return Uint8List(0);
|
||||
}
|
||||
}
|
|
@ -1,11 +1,16 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:cake_wallet/entities/balance_display_mode.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_amount_format.dart';
|
||||
import 'package:cake_wallet/entities/balance.dart';
|
||||
|
||||
class BitcoinBalance extends Balance {
|
||||
const BitcoinBalance({@required this.confirmed, @required this.unconfirmed}) : super();
|
||||
const BitcoinBalance({@required this.confirmed, @required this.unconfirmed})
|
||||
: super(const [
|
||||
BalanceDisplayMode.availableBalance,
|
||||
BalanceDisplayMode.fullBalance
|
||||
]);
|
||||
|
||||
factory BitcoinBalance.fromJSON(String jsonSource) {
|
||||
if (jsonSource == null) {
|
||||
|
@ -24,12 +29,29 @@ class BitcoinBalance extends Balance {
|
|||
|
||||
int get total => confirmed + unconfirmed;
|
||||
|
||||
int get availableBalance => confirmed + (unconfirmed < 0 ? unconfirmed : 0);
|
||||
|
||||
String get confirmedFormatted => bitcoinAmountToString(amount: confirmed);
|
||||
|
||||
String get unconfirmedFormatted => bitcoinAmountToString(amount: unconfirmed);
|
||||
|
||||
String get totalFormatted => bitcoinAmountToString(amount: total);
|
||||
|
||||
String get availableBalanceFormatted =>
|
||||
bitcoinAmountToString(amount: availableBalance);
|
||||
|
||||
@override
|
||||
String formattedBalance(BalanceDisplayMode mode) {
|
||||
switch (mode) {
|
||||
case BalanceDisplayMode.fullBalance:
|
||||
return totalFormatted;
|
||||
case BalanceDisplayMode.availableBalance:
|
||||
return availableBalanceFormatted;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String toJSON() =>
|
||||
json.encode({'confirmed': confirmed, 'unconfirmed': unconfirmed});
|
||||
}
|
||||
|
|
2308
lib/bitcoin/bitcoin_mnemonic.dart
Normal file
5
lib/bitcoin/bitcoin_mnemonic_is_incorrect_exception.dart
Normal file
|
@ -0,0 +1,5 @@
|
|||
class BitcoinMnemonicIsIncorrectException implements Exception {
|
||||
@override
|
||||
String toString() =>
|
||||
'Bitcoin mnemonic has incorrect format. Mnemonic should contain 12 words separated by space.';
|
||||
}
|
|
@ -65,7 +65,7 @@ abstract class BitcoinTransactionHistoryBase
|
|||
|
||||
return historiesWithDetails.fold<Map<String, BitcoinTransactionInfo>>(
|
||||
<String, BitcoinTransactionInfo>{}, (acc, tx) {
|
||||
acc[tx.id] = tx;
|
||||
acc[tx.id] = acc[tx.id]?.updated(tx) ?? tx;
|
||||
return acc;
|
||||
});
|
||||
}
|
||||
|
@ -103,10 +103,6 @@ abstract class BitcoinTransactionHistoryBase
|
|||
|
||||
Future<void> save() async {
|
||||
final data = json.encode({'height': _height, 'transactions': transactions});
|
||||
|
||||
print('data');
|
||||
print(data);
|
||||
|
||||
await writeData(path: path, password: _password, data: data);
|
||||
}
|
||||
|
||||
|
@ -168,7 +164,9 @@ abstract class BitcoinTransactionHistoryBase
|
|||
});
|
||||
|
||||
_height = content['height'] as int;
|
||||
} catch (_) {}
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
void _updateOrInsert(BitcoinTransactionInfo transaction) {
|
||||
|
|
|
@ -12,6 +12,7 @@ class BitcoinTransactionInfo extends TransactionInfo {
|
|||
{@required String id,
|
||||
@required int height,
|
||||
@required int amount,
|
||||
@required int fee,
|
||||
@required TransactionDirection direction,
|
||||
@required bool isPending,
|
||||
@required DateTime date,
|
||||
|
@ -19,6 +20,7 @@ class BitcoinTransactionInfo extends TransactionInfo {
|
|||
this.id = id;
|
||||
this.height = height;
|
||||
this.amount = amount;
|
||||
this.fee = fee;
|
||||
this.direction = direction;
|
||||
this.date = date;
|
||||
this.isPending = isPending;
|
||||
|
@ -36,37 +38,42 @@ class BitcoinTransactionInfo extends TransactionInfo {
|
|||
: DateTime.now();
|
||||
final confirmations = obj['confirmations'] as int ?? 0;
|
||||
var direction = TransactionDirection.incoming;
|
||||
var inputsAmount = 0;
|
||||
var amount = 0;
|
||||
var totalOutAmount = 0;
|
||||
|
||||
for (dynamic vin in vins) {
|
||||
final vout = vin['vout'] as int;
|
||||
final out = vin['tx']['vout'][vout] as Map;
|
||||
final outAddresses =
|
||||
(out['scriptPubKey']['addresses'] as List<Object>)?.toSet();
|
||||
inputsAmount += doubleToBitcoinAmount(out['value'] as double ?? 0);
|
||||
|
||||
if (outAddresses?.intersection(addressesSet)?.isNotEmpty ?? false) {
|
||||
direction = TransactionDirection.outgoing;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
final amount = vout.fold(0, (int acc, dynamic out) {
|
||||
for (dynamic out in vout) {
|
||||
final outAddresses =
|
||||
out['scriptPubKey']['addresses'] as List<Object> ?? [];
|
||||
final ntrs = outAddresses.toSet().intersection(addressesSet);
|
||||
var amount = acc;
|
||||
final value = doubleToBitcoinAmount(out['value'] as double ?? 0.0);
|
||||
totalOutAmount += value;
|
||||
|
||||
if ((direction == TransactionDirection.incoming && ntrs.isNotEmpty) ||
|
||||
(direction == TransactionDirection.outgoing && ntrs.isEmpty)) {
|
||||
amount += doubleToBitcoinAmount(out['value'] as double ?? 0.0);
|
||||
amount += value;
|
||||
}
|
||||
}
|
||||
|
||||
return amount;
|
||||
});
|
||||
final fee = inputsAmount - totalOutAmount;
|
||||
|
||||
return BitcoinTransactionInfo(
|
||||
id: id,
|
||||
height: height,
|
||||
isPending: false,
|
||||
fee: fee,
|
||||
direction: direction,
|
||||
amount: amount,
|
||||
date: date,
|
||||
|
@ -101,6 +108,7 @@ class BitcoinTransactionInfo extends TransactionInfo {
|
|||
id: tx.getId(),
|
||||
height: height,
|
||||
isPending: false,
|
||||
fee: null,
|
||||
direction: TransactionDirection.incoming,
|
||||
amount: amount,
|
||||
date: date,
|
||||
|
@ -112,6 +120,7 @@ class BitcoinTransactionInfo extends TransactionInfo {
|
|||
id: data['id'] as String,
|
||||
height: data['height'] as int,
|
||||
amount: data['amount'] as int,
|
||||
fee: data['fee'] as int,
|
||||
direction: parseTransactionDirectionFromInt(data['direction'] as int),
|
||||
date: DateTime.fromMillisecondsSinceEpoch(data['date'] as int),
|
||||
isPending: data['isPending'] as bool,
|
||||
|
@ -124,12 +133,29 @@ class BitcoinTransactionInfo extends TransactionInfo {
|
|||
String amountFormatted() =>
|
||||
'${formatAmount(bitcoinAmountToString(amount: amount))} BTC';
|
||||
|
||||
@override
|
||||
String feeFormatted() => fee != null
|
||||
? '${formatAmount(bitcoinAmountToString(amount: fee))} BTC'
|
||||
: '';
|
||||
|
||||
@override
|
||||
String fiatAmount() => _fiatAmount ?? '';
|
||||
|
||||
@override
|
||||
void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount);
|
||||
|
||||
BitcoinTransactionInfo updated(BitcoinTransactionInfo info) {
|
||||
return BitcoinTransactionInfo(
|
||||
id: id,
|
||||
height: info.height,
|
||||
amount: info.amount,
|
||||
fee: info.fee,
|
||||
direction: direction ?? info.direction,
|
||||
date: date ?? info.date,
|
||||
isPending: isPending ?? info.isPending,
|
||||
confirmations: info.confirmations);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final m = <String, dynamic>{};
|
||||
m['id'] = id;
|
||||
|
@ -139,6 +165,7 @@ class BitcoinTransactionInfo extends TransactionInfo {
|
|||
m['date'] = date.millisecondsSinceEpoch;
|
||||
m['isPending'] = isPending;
|
||||
m['confirmations'] = confirmations;
|
||||
m['fee'] = fee;
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:cake_wallet/bitcoin/address_to_output_script.dart';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_mnemonic.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:bip39/bip39.dart' as bip39;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:rxdart/rxdart.dart';
|
||||
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||
|
@ -42,8 +43,9 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
|
|||
BitcoinBalance initialBalance})
|
||||
: balance =
|
||||
initialBalance ?? BitcoinBalance(confirmed: 0, unconfirmed: 0),
|
||||
hd = bitcoin.HDWallet.fromSeed(bip39.mnemonicToSeed(mnemonic),
|
||||
network: bitcoin.bitcoin),
|
||||
hd = bitcoin.HDWallet.fromSeed(mnemonicToSeedBytes(mnemonic),
|
||||
network: bitcoin.bitcoin)
|
||||
.derivePath("m/0'/0"),
|
||||
addresses = initialAddresses != null
|
||||
? ObservableList<BitcoinAddressRecord>.of(initialAddresses)
|
||||
: ObservableList<BitcoinAddressRecord>(),
|
||||
|
@ -58,6 +60,7 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
|
|||
{@required String password,
|
||||
@required String name,
|
||||
@required String dirPath,
|
||||
@required WalletInfo walletInfo,
|
||||
String jsonSource}) {
|
||||
final data = json.decode(jsonSource) as Map;
|
||||
final mnemonic = data['mnemonic'] as String;
|
||||
|
@ -83,7 +86,8 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
|
|||
name: name,
|
||||
accountIndex: accountIndex,
|
||||
initialAddresses: addresses,
|
||||
initialBalance: balance);
|
||||
initialBalance: balance,
|
||||
walletInfo: walletInfo);
|
||||
}
|
||||
|
||||
static BitcoinWallet build(
|
||||
|
@ -91,6 +95,7 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
|
|||
@required String password,
|
||||
@required String name,
|
||||
@required String dirPath,
|
||||
@required WalletInfo walletInfo,
|
||||
List<BitcoinAddressRecord> initialAddresses,
|
||||
BitcoinBalance initialBalance,
|
||||
int accountIndex = 0}) {
|
||||
|
@ -107,7 +112,8 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
|
|||
accountIndex: accountIndex,
|
||||
initialAddresses: initialAddresses,
|
||||
initialBalance: initialBalance,
|
||||
transactionHistory: history);
|
||||
transactionHistory: history,
|
||||
walletInfo: walletInfo);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -170,6 +176,22 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
|
|||
return address;
|
||||
}
|
||||
|
||||
Future<List<BitcoinAddressRecord>> generateNewAddresses(int count) async {
|
||||
final list = <BitcoinAddressRecord>[];
|
||||
|
||||
for (var i = 0; i < count; i++) {
|
||||
_accountIndex += 1;
|
||||
final address = BitcoinAddressRecord(_getAddress(index: _accountIndex),
|
||||
index: _accountIndex, label: null);
|
||||
list.add(address);
|
||||
}
|
||||
|
||||
addresses.addAll(list);
|
||||
await save();
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
Future<void> updateAddress(String address, {String label}) async {
|
||||
for (final addr in addresses) {
|
||||
if (addr.address == address) {
|
||||
|
@ -185,8 +207,10 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
|
|||
Future<void> startSync() async {
|
||||
try {
|
||||
syncStatus = StartingSyncStatus();
|
||||
transactionHistory.updateAsync(
|
||||
onFinished: () => print('transactionHistory update finished!'));
|
||||
transactionHistory.updateAsync(onFinished: () {
|
||||
print('transactionHistory update finished!');
|
||||
transactionHistory.save();
|
||||
});
|
||||
_subscribeForUpdates();
|
||||
await _updateBalance();
|
||||
syncStatus = SyncedSyncStatus();
|
||||
|
@ -238,9 +262,8 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
|
|||
final utxs = await unptsFutures;
|
||||
|
||||
for (final utx in utxs) {
|
||||
final inAmount = utx.value > totalAmount ? totalAmount : utx.value;
|
||||
leftAmount = leftAmount - inAmount;
|
||||
totalInputAmount += inAmount;
|
||||
leftAmount = leftAmount - utx.value;
|
||||
totalInputAmount += utx.value;
|
||||
inputs.add(utx);
|
||||
|
||||
if (leftAmount <= 0) {
|
||||
|
@ -279,7 +302,8 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
|
|||
}
|
||||
});
|
||||
|
||||
txb.addOutput(transactionCredentials.address, amount);
|
||||
txb.addOutput(
|
||||
addressToOutputScript(transactionCredentials.address), amount);
|
||||
|
||||
if (changeValue > 0) {
|
||||
txb.addOutput(changeAddress, changeValue);
|
||||
|
@ -310,8 +334,10 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
|
|||
bitcoinAmountToDouble(amount: _feeMultiplier(priority));
|
||||
|
||||
@override
|
||||
Future<void> save() async =>
|
||||
await write(path: path, password: _password, data: toJSON());
|
||||
Future<void> save() async {
|
||||
await write(path: path, password: _password, data: toJSON());
|
||||
await transactionHistory.save();
|
||||
}
|
||||
|
||||
bitcoin.ECPair keyPairFor({@required int index}) =>
|
||||
generateKeyPair(hd: hd, index: index);
|
||||
|
@ -321,13 +347,18 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
|
|||
// FIXME: Unimplemented
|
||||
}
|
||||
|
||||
@override
|
||||
void close() async{
|
||||
await eclient.close();
|
||||
}
|
||||
|
||||
void _subscribeForUpdates() {
|
||||
scriptHashes.forEach((sh) async {
|
||||
await _scripthashesUpdateSubject[sh]?.close();
|
||||
_scripthashesUpdateSubject[sh] = eclient.scripthashUpdate(sh);
|
||||
_scripthashesUpdateSubject[sh].listen((event) async {
|
||||
transactionHistory.updateAsync();
|
||||
await _updateBalance();
|
||||
transactionHistory.updateAsync();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -358,9 +389,9 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
|
|||
case TransactionPriority.slow:
|
||||
return 6000;
|
||||
case TransactionPriority.regular:
|
||||
return 9000;
|
||||
return 22080;
|
||||
case TransactionPriority.fast:
|
||||
return 15000;
|
||||
return 24000;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
import 'package:cake_wallet/core/wallet_credentials.dart';
|
||||
import 'package:cake_wallet/entities/wallet_info.dart';
|
||||
|
||||
class BitcoinNewWalletCredentials extends WalletCredentials {
|
||||
BitcoinNewWalletCredentials({String name}) : super(name: name);
|
||||
BitcoinNewWalletCredentials({String name, WalletInfo walletInfo})
|
||||
: super(name: name, walletInfo: walletInfo);
|
||||
}
|
||||
|
||||
class BitcoinRestoreWalletFromSeedCredentials extends WalletCredentials {
|
||||
BitcoinRestoreWalletFromSeedCredentials(
|
||||
{String name, String password, this.mnemonic})
|
||||
: super(name: name, password: password);
|
||||
{String name, String password, this.mnemonic, WalletInfo walletInfo})
|
||||
: super(name: name, password: password, walletInfo: walletInfo);
|
||||
|
||||
final String mnemonic;
|
||||
}
|
||||
|
||||
class BitcoinRestoreWalletFromWIFCredentials extends WalletCredentials {
|
||||
BitcoinRestoreWalletFromWIFCredentials(
|
||||
{String name, String password, this.wif})
|
||||
: super(name: name, password: password);
|
||||
{String name, String password, this.wif, WalletInfo walletInfo})
|
||||
: super(name: name, password: password, walletInfo: walletInfo);
|
||||
|
||||
final String wif;
|
||||
}
|
||||
|
|
|
@ -1,25 +1,34 @@
|
|||
import 'dart:io';
|
||||
import 'package:bip39/bip39.dart' as bip39;
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_mnemonic.dart';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_mnemonic_is_incorrect_exception.dart';
|
||||
import 'package:cake_wallet/bitcoin/file.dart';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_wallet_creation_credentials.dart';
|
||||
import 'package:cake_wallet/core/wallet_base.dart';
|
||||
import 'package:cake_wallet/core/wallet_service.dart';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart';
|
||||
import 'package:cake_wallet/entities/pathForWallet.dart';
|
||||
import 'package:cake_wallet/entities/wallet_info.dart';
|
||||
import 'package:cake_wallet/entities/wallet_type.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
|
||||
class BitcoinWalletService extends WalletService<
|
||||
BitcoinNewWalletCredentials,
|
||||
BitcoinRestoreWalletFromSeedCredentials,
|
||||
BitcoinRestoreWalletFromWIFCredentials> {
|
||||
BitcoinWalletService(this.walletInfoSource);
|
||||
|
||||
final Box<WalletInfo> walletInfoSource;
|
||||
|
||||
@override
|
||||
Future<BitcoinWallet> create(BitcoinNewWalletCredentials credentials) async {
|
||||
final dirPath = await pathForWalletDir(
|
||||
type: WalletType.bitcoin, name: credentials.name);
|
||||
final wallet = BitcoinWalletBase.build(
|
||||
dirPath: dirPath,
|
||||
mnemonic: bip39.generateMnemonic(),
|
||||
mnemonic: generateMnemonic(),
|
||||
password: credentials.password,
|
||||
name: credentials.name);
|
||||
name: credentials.name,
|
||||
walletInfo: credentials.walletInfo);
|
||||
await wallet.save();
|
||||
await wallet.init();
|
||||
|
||||
|
@ -37,11 +46,15 @@ class BitcoinWalletService extends WalletService<
|
|||
await pathForWalletDir(name: name, type: WalletType.bitcoin);
|
||||
final walletPath = '$walletDirPath/$name';
|
||||
final walletJSONRaw = await read(path: walletPath, password: password);
|
||||
final walletInfo = walletInfoSource.values.firstWhere(
|
||||
(info) => info.id == WalletBase.idFor(name, WalletType.bitcoin),
|
||||
orElse: () => null);
|
||||
final wallet = BitcoinWalletBase.fromJSON(
|
||||
password: password,
|
||||
name: name,
|
||||
dirPath: walletDirPath,
|
||||
jsonSource: walletJSONRaw);
|
||||
jsonSource: walletJSONRaw,
|
||||
walletInfo: walletInfo);
|
||||
await wallet.init();
|
||||
|
||||
return wallet;
|
||||
|
@ -62,15 +75,21 @@ class BitcoinWalletService extends WalletService<
|
|||
@override
|
||||
Future<BitcoinWallet> restoreFromSeed(
|
||||
BitcoinRestoreWalletFromSeedCredentials credentials) async {
|
||||
if (!validateMnemonic(credentials.mnemonic)) {
|
||||
throw BitcoinMnemonicIsIncorrectException();
|
||||
}
|
||||
|
||||
final dirPath = await pathForWalletDir(
|
||||
type: WalletType.bitcoin, name: credentials.name);
|
||||
final wallet = BitcoinWalletBase.build(
|
||||
dirPath: dirPath,
|
||||
name: credentials.name,
|
||||
password: credentials.password,
|
||||
mnemonic: credentials.mnemonic);
|
||||
mnemonic: credentials.mnemonic,
|
||||
walletInfo: credentials.walletInfo);
|
||||
await wallet.save();
|
||||
await wallet.init();
|
||||
await wallet.generateNewAddresses(32);
|
||||
|
||||
return wallet;
|
||||
}
|
||||
|
|
|
@ -22,8 +22,9 @@ String jsonrpcparams(List<Object> params) {
|
|||
}
|
||||
|
||||
String jsonrpc(
|
||||
{String method, List<Object> params, int id, double version = 2.0}) =>
|
||||
'{"jsonrpc": "$version", "method": "$method", "id": "$id", "params": ${json.encode(params)}}\n';
|
||||
{String method, List<Object> params, int id, double version = 2.0}) =>
|
||||
'{"jsonrpc": "$version", "method": "$method", "id": "$id", "params": ${json
|
||||
.encode(params)}}\n';
|
||||
|
||||
class SocketTask {
|
||||
SocketTask({this.completer, this.isSubscription, this.subject});
|
||||
|
@ -49,6 +50,7 @@ class ElectrumClient {
|
|||
final Map<String, SocketTask> _tasks;
|
||||
bool _isConnected;
|
||||
Timer _aliveTimer;
|
||||
String unterminatedString;
|
||||
|
||||
Future<void> connectToUri(String uri) async {
|
||||
final splittedUri = uri.split(':');
|
||||
|
@ -73,26 +75,31 @@ class ElectrumClient {
|
|||
|
||||
socket.listen((Uint8List event) {
|
||||
try {
|
||||
final jsoned =
|
||||
json.decode(utf8.decode(event.toList())) as Map<String, Object>;
|
||||
print(jsoned);
|
||||
final method = jsoned['method'];
|
||||
final id = jsoned['id'] as String;
|
||||
final params = jsoned['result'];
|
||||
_handleResponse(utf8.decode(event.toList()));
|
||||
} on FormatException catch (e) {
|
||||
final msg = e.message.toLowerCase();
|
||||
|
||||
if (method is String) {
|
||||
_methodHandler(method: method, request: jsoned);
|
||||
return;
|
||||
if (msg == 'Unterminated string'.toLowerCase()) {
|
||||
unterminatedString = e.source as String;
|
||||
}
|
||||
|
||||
_finish(id, params);
|
||||
if (msg == 'Unexpected character'.toLowerCase()) {
|
||||
unterminatedString += e.source as String;
|
||||
}
|
||||
|
||||
if (isJSONStringCorrect(unterminatedString)) {
|
||||
_handleResponse(unterminatedString);
|
||||
unterminatedString = null;
|
||||
}
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
}, onError: (Object error) {
|
||||
print(error.toString());
|
||||
_setIsConnected(false);
|
||||
}, onDone: () => _setIsConnected(false));
|
||||
}, onDone: () {
|
||||
_setIsConnected(false);
|
||||
});
|
||||
keepAlive();
|
||||
}
|
||||
|
||||
|
@ -103,7 +110,7 @@ class ElectrumClient {
|
|||
|
||||
Future<void> ping() async {
|
||||
try {
|
||||
// await callWithTimeout(method: 'server.ping');
|
||||
await callWithTimeout(method: 'server.ping');
|
||||
_setIsConnected(true);
|
||||
} on RequestFailedTimeoutException catch (_) {
|
||||
_setIsConnected(false);
|
||||
|
@ -146,7 +153,7 @@ class ElectrumClient {
|
|||
});
|
||||
|
||||
Future<List<Map<String, dynamic>>> getListUnspentWithAddress(
|
||||
String address) =>
|
||||
String address) =>
|
||||
call(
|
||||
method: 'blockchain.scripthash.listunspent',
|
||||
params: [scriptHash(address)]).then((dynamic result) {
|
||||
|
@ -197,7 +204,7 @@ class ElectrumClient {
|
|||
});
|
||||
|
||||
Future<Map<String, Object>> getTransactionRaw(
|
||||
{@required String hash}) async =>
|
||||
{@required String hash}) async =>
|
||||
call(method: 'blockchain.transaction.get', params: [hash, true])
|
||||
.then((dynamic result) {
|
||||
if (result is Map<String, Object>) {
|
||||
|
@ -209,20 +216,24 @@ class ElectrumClient {
|
|||
|
||||
Future<Map<String, Object>> getTransactionExpanded(
|
||||
{@required String hash}) async {
|
||||
final originalTx = await getTransactionRaw(hash: hash);
|
||||
final vins = originalTx['vin'] as List<Object>;
|
||||
try {
|
||||
final originalTx = await getTransactionRaw(hash: hash);
|
||||
final vins = originalTx['vin'] as List<Object>;
|
||||
|
||||
for (dynamic vin in vins) {
|
||||
if (vin is Map<String, Object>) {
|
||||
vin['tx'] = await getTransactionRaw(hash: vin['txid'] as String);
|
||||
for (dynamic vin in vins) {
|
||||
if (vin is Map<String, Object>) {
|
||||
vin['tx'] = await getTransactionRaw(hash: vin['txid'] as String);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return originalTx;
|
||||
return originalTx;
|
||||
} catch (_) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> broadcastTransaction(
|
||||
{@required String transactionRaw}) async =>
|
||||
{@required String transactionRaw}) async =>
|
||||
call(method: 'blockchain.transaction.broadcast', params: [transactionRaw])
|
||||
.then((dynamic result) {
|
||||
if (result is String) {
|
||||
|
@ -233,14 +244,14 @@ class ElectrumClient {
|
|||
});
|
||||
|
||||
Future<Map<String, dynamic>> getMerkle(
|
||||
{@required String hash, @required int height}) async =>
|
||||
{@required String hash, @required int height}) async =>
|
||||
await call(
|
||||
method: 'blockchain.transaction.get_merkle',
|
||||
params: [hash, height]) as Map<String, dynamic>;
|
||||
|
||||
Future<Map<String, dynamic>> getHeader({@required int height}) async =>
|
||||
await call(method: 'blockchain.block.get_header', params: [height])
|
||||
as Map<String, dynamic>;
|
||||
as Map<String, dynamic>;
|
||||
|
||||
Future<double> estimatefee({@required int p}) =>
|
||||
call(method: 'blockchain.estimatefee', params: [p])
|
||||
|
@ -256,16 +267,17 @@ class ElectrumClient {
|
|||
return 0;
|
||||
});
|
||||
|
||||
BehaviorSubject<Object> scripthashUpdate(String scripthash) =>
|
||||
subscribe<Object>(
|
||||
id: 'blockchain.scripthash.subscribe:$scripthash',
|
||||
method: 'blockchain.scripthash.subscribe',
|
||||
params: [scripthash]);
|
||||
BehaviorSubject<Object> scripthashUpdate(String scripthash) {
|
||||
_id += 1;
|
||||
return subscribe<Object>(
|
||||
id: 'blockchain.scripthash.subscribe:$scripthash',
|
||||
method: 'blockchain.scripthash.subscribe',
|
||||
params: [scripthash]);
|
||||
}
|
||||
|
||||
BehaviorSubject<T> subscribe<T>(
|
||||
{@required String id,
|
||||
@required String method,
|
||||
List<Object> params = const []}) {
|
||||
BehaviorSubject<T> subscribe<T>({@required String id,
|
||||
@required String method,
|
||||
List<Object> params = const []}) {
|
||||
final subscription = BehaviorSubject<T>();
|
||||
_regisrySubscription(id, subscription);
|
||||
socket.write(jsonrpc(method: method, id: _id, params: params));
|
||||
|
@ -273,7 +285,8 @@ class ElectrumClient {
|
|||
return subscription;
|
||||
}
|
||||
|
||||
Future<dynamic> call({String method, List<Object> params = const []}) {
|
||||
Future<dynamic> call({String method, List<Object> params = const []}) async {
|
||||
await Future<void>.delayed(Duration(milliseconds: 100));
|
||||
final completer = Completer<dynamic>();
|
||||
_id += 1;
|
||||
final id = _id;
|
||||
|
@ -283,10 +296,9 @@ class ElectrumClient {
|
|||
return completer.future;
|
||||
}
|
||||
|
||||
Future<dynamic> callWithTimeout(
|
||||
{String method,
|
||||
List<Object> params = const [],
|
||||
int timeout = 2000}) async {
|
||||
Future<dynamic> callWithTimeout({String method,
|
||||
List<Object> params = const [],
|
||||
int timeout = 2000}) async {
|
||||
final completer = Completer<dynamic>();
|
||||
_id += 1;
|
||||
final id = _id;
|
||||
|
@ -307,8 +319,15 @@ class ElectrumClient {
|
|||
socket.write(jsonrpc(method: method, id: _id, params: params));
|
||||
}
|
||||
|
||||
void _regisryTask(int id, Completer completer) => _tasks[id.toString()] =
|
||||
SocketTask(completer: completer, isSubscription: false);
|
||||
Future<void> close() async {
|
||||
_aliveTimer.cancel();
|
||||
await socket.close();
|
||||
onConnectionStatusChange = null;
|
||||
}
|
||||
|
||||
void _regisryTask(int id, Completer completer) =>
|
||||
_tasks[id.toString()] =
|
||||
SocketTask(completer: completer, isSubscription: false);
|
||||
|
||||
void _regisrySubscription(String id, BehaviorSubject subject) =>
|
||||
_tasks[id] = SocketTask(subject: subject, isSubscription: true);
|
||||
|
@ -351,6 +370,31 @@ class ElectrumClient {
|
|||
|
||||
_isConnected = isConnected;
|
||||
}
|
||||
|
||||
void _handleResponse(String response) {
|
||||
print('Response: $response');
|
||||
final jsoned = json.decode(response) as Map<String, Object>;
|
||||
// print(jsoned);
|
||||
final method = jsoned['method'];
|
||||
final id = jsoned['id'] as String;
|
||||
final result = jsoned['result'];
|
||||
|
||||
if (method is String) {
|
||||
_methodHandler(method: method, request: jsoned);
|
||||
return;
|
||||
}
|
||||
|
||||
_finish(id, result);
|
||||
}
|
||||
}
|
||||
// FIXME: move me
|
||||
bool isJSONStringCorrect(String source) {
|
||||
try {
|
||||
json.decode(source);
|
||||
return true;
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class RequestFailedTimeoutException implements Exception {
|
||||
|
|
|
@ -16,6 +16,7 @@ class PendingBitcoinTransaction with PendingTransaction {
|
|||
final int amount;
|
||||
final int fee;
|
||||
|
||||
@override
|
||||
String get id => _tx.getId();
|
||||
|
||||
@override
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import 'package:bip39/src/wordlists/english.dart' as bitcoin_english;
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_mnemonic.dart' as bitcoin_electrum;
|
||||
import 'package:cake_wallet/core/validator.dart';
|
||||
import 'package:cake_wallet/entities/mnemonic_item.dart';
|
||||
import 'package:cake_wallet/entities/wallet_type.dart';
|
||||
|
@ -64,7 +64,7 @@ class SeedValidator extends Validator<MnemonicItem> {
|
|||
|
||||
static List<String> getBitcoinWordList(String language) {
|
||||
assert(language.toLowerCase() == LanguageList.english.toLowerCase());
|
||||
return bitcoin_english.WORDLIST;
|
||||
return bitcoin_electrum.englishWordlist;
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -52,4 +52,6 @@ abstract class WalletBase<BalaceType> {
|
|||
Future<void> save();
|
||||
|
||||
Future<void> rescan({int height});
|
||||
|
||||
void close();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:cake_wallet/entities/wallet_info.dart';
|
||||
|
||||
abstract class WalletCredentials {
|
||||
WalletCredentials({this.name, this.password, this.height});
|
||||
WalletCredentials({this.name, this.password, this.height, this.walletInfo});
|
||||
|
||||
final String name;
|
||||
final int height;
|
||||
|
|
25
lib/di.dart
|
@ -16,6 +16,7 @@ import 'package:cake_wallet/src/screens/contact/contact_page.dart';
|
|||
import 'package:cake_wallet/src/screens/exchange_trade/exchange_confirm_page.dart';
|
||||
import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_page.dart';
|
||||
import 'package:cake_wallet/src/screens/faq/faq_page.dart';
|
||||
import 'package:cake_wallet/src/screens/new_wallet/new_wallet_type_page.dart';
|
||||
import 'package:cake_wallet/src/screens/nodes/node_create_or_edit_page.dart';
|
||||
import 'package:cake_wallet/src/screens/nodes/nodes_list_page.dart';
|
||||
import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
|
||||
|
@ -293,17 +294,16 @@ Future setup(
|
|||
getIt.get<MoneroAccountEditOrCreateViewModel>()));*/
|
||||
|
||||
getIt.registerFactoryParam<MoneroAccountEditOrCreateViewModel,
|
||||
AccountListItem, void>(
|
||||
(AccountListItem account, _) =>
|
||||
MoneroAccountEditOrCreateViewModel((
|
||||
getIt.get<AppStore>().wallet as MoneroWallet).accountList,
|
||||
accountListItem: account));
|
||||
AccountListItem, void>(
|
||||
(AccountListItem account, _) => MoneroAccountEditOrCreateViewModel(
|
||||
(getIt.get<AppStore>().wallet as MoneroWallet).accountList,
|
||||
accountListItem: account));
|
||||
|
||||
getIt.registerFactoryParam<MoneroAccountEditOrCreatePage,
|
||||
AccountListItem, void>((AccountListItem account, _) =>
|
||||
MoneroAccountEditOrCreatePage(
|
||||
getIt.registerFactoryParam<MoneroAccountEditOrCreatePage, AccountListItem,
|
||||
void>(
|
||||
(AccountListItem account, _) => MoneroAccountEditOrCreatePage(
|
||||
moneroAccountCreationViewModel:
|
||||
getIt.get<MoneroAccountEditOrCreateViewModel>(param1: account)));
|
||||
getIt.get<MoneroAccountEditOrCreateViewModel>(param1: account)));
|
||||
|
||||
getIt.registerFactory(() {
|
||||
final appStore = getIt.get<AppStore>();
|
||||
|
@ -378,7 +378,7 @@ Future setup(
|
|||
|
||||
getIt.registerFactory(() => MoneroWalletService(walletInfoSource));
|
||||
|
||||
getIt.registerFactory(() => BitcoinWalletService());
|
||||
getIt.registerFactory(() => BitcoinWalletService(walletInfoSource));
|
||||
|
||||
getIt.registerFactoryParam<WalletService, WalletType, void>(
|
||||
(WalletType param1, __) {
|
||||
|
@ -423,6 +423,11 @@ Future setup(
|
|||
getIt.get<SettingsStore>().shouldSaveRecipientAddress,
|
||||
transactionDescriptionBox));
|
||||
|
||||
getIt.registerFactoryParam<NewWalletTypePage,
|
||||
void Function(BuildContext, WalletType), bool>(
|
||||
(para1, param2) => NewWalletTypePage(getIt.get<WalletNewVM>(),
|
||||
onTypeSelected: para1, isNewWallet: param2));
|
||||
|
||||
getIt.registerFactory(() => PreSeedPage());
|
||||
|
||||
getIt.registerFactoryParam<TradeDetailsViewModel, Trade, void>((trade, _) =>
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
import 'package:cake_wallet/entities/balance_display_mode.dart';
|
||||
|
||||
abstract class Balance {
|
||||
const Balance();
|
||||
const Balance(this.availableModes);
|
||||
|
||||
final List<BalanceDisplayMode> availableModes;
|
||||
|
||||
String formattedBalance(BalanceDisplayMode mode);
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ Future defaultSettingsMigration(
|
|||
FiatCurrency.usd.toString());
|
||||
await sharedPreferences.setInt(
|
||||
PreferencesKey.currentTransactionPriorityKey,
|
||||
TransactionPriority.standart.raw);
|
||||
TransactionPriority.standard.raw);
|
||||
await sharedPreferences.setInt(
|
||||
PreferencesKey.currentBalanceDisplayModeKey,
|
||||
BalanceDisplayMode.availableBalance.raw);
|
||||
|
|
|
@ -19,5 +19,5 @@ Future<void> loadCurrentWallet() async {
|
|||
await getIt.get<KeyService>().getWalletPassword(walletName: name);
|
||||
final _service = getIt.get<WalletService>(param1: type);
|
||||
final wallet = await _service.openWallet(name, password);
|
||||
appStore.wallet = wallet;
|
||||
appStore.changeCurrentWallet(wallet);
|
||||
}
|
||||
|
|
|
@ -39,9 +39,9 @@ Future<List<Node>> loadElectrumServerList() async {
|
|||
|
||||
Future resetToDefault(Box<Node> nodeSource) async {
|
||||
final moneroNodes = await loadDefaultNodes();
|
||||
// final bitcoinElectrumServerList = await loadElectrumServerList();
|
||||
// final nodes = moneroNodes + bitcoinElectrumServerList;
|
||||
final bitcoinElectrumServerList = await loadElectrumServerList();
|
||||
final nodes = moneroNodes + bitcoinElectrumServerList;
|
||||
|
||||
await nodeSource.clear();
|
||||
await nodeSource.addAll(moneroNodes);
|
||||
await nodeSource.addAll(nodes);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ class PreferencesKey {
|
|||
static const shouldSaveRecipientAddressKey = 'save_recipient_address';
|
||||
static const allowBiometricalAuthenticationKey =
|
||||
'allow_biometrical_authentication';
|
||||
static const currentDarkTheme = 'dark_theme';
|
||||
static const currentTheme = 'current_theme';
|
||||
static const displayActionListModeKey = 'display_list_mode';
|
||||
static const currentPinLength = 'current_pin_length';
|
||||
static const currentLanguageCode = 'language_code';
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:cake_wallet/utils/mobx.dart';
|
|||
abstract class TransactionInfo extends Object with Keyable {
|
||||
String id;
|
||||
int amount;
|
||||
int fee;
|
||||
TransactionDirection direction;
|
||||
bool isPending;
|
||||
DateTime date;
|
||||
|
@ -11,6 +12,7 @@ abstract class TransactionInfo extends Object with Keyable {
|
|||
int confirmations;
|
||||
String amountFormatted();
|
||||
String fiatAmount();
|
||||
String feeFormatted();
|
||||
void changeFiatAmount(String amount);
|
||||
|
||||
@override
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cake_wallet/entities/wallet_type.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/entities/enumerable_item.dart';
|
||||
|
||||
|
@ -17,7 +18,23 @@ class TransactionPriority extends EnumerableItem<int> with Serializable<int> {
|
|||
static const medium = TransactionPriority(title: 'Medium', raw: 2);
|
||||
static const fast = TransactionPriority(title: 'Fast', raw: 3);
|
||||
static const fastest = TransactionPriority(title: 'Fastest', raw: 4);
|
||||
static const standart = slow;
|
||||
static const standard = slow;
|
||||
|
||||
|
||||
static List<TransactionPriority> forWalletType(WalletType type) {
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
return TransactionPriority.all;
|
||||
case WalletType.bitcoin:
|
||||
return [
|
||||
TransactionPriority.slow,
|
||||
TransactionPriority.regular,
|
||||
TransactionPriority.fast
|
||||
];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
static TransactionPriority deserialize({int raw}) {
|
||||
switch (raw) {
|
||||
|
|
|
@ -48,3 +48,14 @@ String walletTypeToString(WalletType type) {
|
|||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
String walletTypeToDisplayName(WalletType type) {
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
return 'Monero';
|
||||
case WalletType.bitcoin:
|
||||
return 'Bitcoin (Electrum)';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,11 +27,14 @@ class XMRTOExchangeProvider extends ExchangeProvider {
|
|||
static const _orderParameterUriSuffix = '/order_parameter_query';
|
||||
static const _orderStatusUriSuffix = '/order_status_query/';
|
||||
static const _orderCreateUriSuffix = '/order_create/';
|
||||
static const _headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': userAgent
|
||||
};
|
||||
|
||||
static Future<bool> _checkIsAvailable() async {
|
||||
const url = originalApiUri + _orderParameterUriSuffix;
|
||||
final response =
|
||||
await get(url, headers: {'Content-Type': 'application/json'});
|
||||
final response = await get(url, headers: _headers);
|
||||
return !(response.statusCode == 403);
|
||||
}
|
||||
|
||||
|
@ -91,9 +94,8 @@ class XMRTOExchangeProvider extends ExchangeProvider {
|
|||
Future<Trade> createTrade({TradeRequest request}) async {
|
||||
final _request = request as XMRTOTradeRequest;
|
||||
final url = originalApiUri + _orderCreateUriSuffix;
|
||||
final _amount = _request.isBTCRequest
|
||||
? _request.receiveAmount
|
||||
: _request.amount;
|
||||
final _amount =
|
||||
_request.isBTCRequest ? _request.receiveAmount : _request.amount;
|
||||
|
||||
final _amountCurrency = _request.isBTCRequest
|
||||
? _request.to.toString()
|
||||
|
@ -112,8 +114,8 @@ class XMRTOExchangeProvider extends ExchangeProvider {
|
|||
'amount_currency': _amountCurrency,
|
||||
'btc_dest_address': _request.address
|
||||
};
|
||||
final response = await post(url,
|
||||
headers: {'Content-Type': 'application/json'}, body: json.encode(body));
|
||||
final response =
|
||||
await post(url, headers: _headers, body: json.encode(body));
|
||||
|
||||
if (response.statusCode != 201) {
|
||||
if (response.statusCode == 400) {
|
||||
|
@ -141,13 +143,10 @@ class XMRTOExchangeProvider extends ExchangeProvider {
|
|||
|
||||
@override
|
||||
Future<Trade> findTradeById({@required String id}) async {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': userAgent
|
||||
};
|
||||
final url = originalApiUri + _orderStatusUriSuffix;
|
||||
final body = {'uuid': id};
|
||||
final response = await post(url, headers: headers, body: json.encode(body));
|
||||
final response =
|
||||
await post(url, headers: _headers, body: json.encode(body));
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
if (response.statusCode == 400) {
|
||||
|
@ -210,8 +209,7 @@ class XMRTOExchangeProvider extends ExchangeProvider {
|
|||
Future<double> _fetchRates() async {
|
||||
try {
|
||||
final url = originalApiUri + _orderParameterUriSuffix;
|
||||
final response =
|
||||
await get(url, headers: {'Content-Type': 'application/json'});
|
||||
final response = await get(url, headers: _headers);
|
||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||
final price = double.parse(responseJSON['price'] as String);
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ class S implements WidgetsLocalizations {
|
|||
String get authentication => "Authentication";
|
||||
String get available_balance => "Available Balance";
|
||||
String get biometric_auth_reason => "Scan your fingerprint to authenticate";
|
||||
String get bright_theme => "Bright";
|
||||
String get buy => "Buy";
|
||||
String get cake_wallet => "Cake Wallet";
|
||||
String get cancel => "Cancel";
|
||||
|
@ -57,6 +58,7 @@ class S implements WidgetsLocalizations {
|
|||
String get choose_account => "Choose account";
|
||||
String get choose_wallet_currency => "Please choose wallet currency:";
|
||||
String get clear => "Clear";
|
||||
String get color_theme => "Color theme";
|
||||
String get confirm => "Confirm";
|
||||
String get confirm_delete_template => "This action will delete this template. Do you wish to continue?";
|
||||
String get confirm_delete_wallet => "This action will delete this wallet. Do you wish to continue?";
|
||||
|
@ -71,6 +73,7 @@ class S implements WidgetsLocalizations {
|
|||
String get create_new => "Create New Wallet";
|
||||
String get create_new_account => "Create new account";
|
||||
String get creating_new_wallet => "Creating new wallet";
|
||||
String get dark_theme => "Dark";
|
||||
String get delete => "Delete";
|
||||
String get digit_pin => "-digit PIN";
|
||||
String get edit => "Edit";
|
||||
|
@ -107,6 +110,7 @@ class S implements WidgetsLocalizations {
|
|||
String get id => "ID: ";
|
||||
String get incoming => "Incoming";
|
||||
String get incorrect_seed => "The text entered is not valid.";
|
||||
String get light_theme => "Light";
|
||||
String get loading_your_wallet => "Loading your wallet";
|
||||
String get login => "Login";
|
||||
String get new_node_testing => "New node testing";
|
||||
|
@ -208,13 +212,13 @@ class S implements WidgetsLocalizations {
|
|||
String get send_error_currency => "Currency can only contain numbers";
|
||||
String get send_error_minimum_value => "Minimum value of amount is 0.01";
|
||||
String get send_estimated_fee => "Estimated fee:";
|
||||
String get send_fee => "Fee:";
|
||||
String get send_fee => "Fee";
|
||||
String get send_got_it => "Got it";
|
||||
String get send_name => "Name";
|
||||
String get send_new => "New";
|
||||
String get send_payment_id => "Payment ID (optional)";
|
||||
String get send_sending => "Sending...";
|
||||
String get send_success => "Your Monero was successfully sent";
|
||||
String send_success(String crypto) => "Your ${crypto} was successfully sent";
|
||||
String get send_templates => "Templates";
|
||||
String get send_title => "Send";
|
||||
String get send_xmr => "Send XMR";
|
||||
|
@ -394,9 +398,11 @@ class $de extends S {
|
|||
@override
|
||||
String get biometric_auth_reason => "Scannen Sie Ihren Fingerabdruck zur Authentifizierung";
|
||||
@override
|
||||
String get dark_theme => "Dunkel";
|
||||
@override
|
||||
String get transaction_sent => "Transaktion gesendet!";
|
||||
@override
|
||||
String get send_fee => "Gebühr:";
|
||||
String get send_fee => "Gebühr";
|
||||
@override
|
||||
String get password => "Passwort";
|
||||
@override
|
||||
|
@ -636,7 +642,7 @@ class $de extends S {
|
|||
@override
|
||||
String get trade_details_created_at => "Hergestellt in";
|
||||
@override
|
||||
String get send_success => "Ihr Monero wurde erfolgreich gesendet";
|
||||
String send_success(String crypto) => "Ihr ${crypto} wurde erfolgreich gesendet";
|
||||
@override
|
||||
String get settings_wallets => "Brieftaschen";
|
||||
@override
|
||||
|
@ -646,6 +652,8 @@ class $de extends S {
|
|||
@override
|
||||
String get filters => "Filter";
|
||||
@override
|
||||
String get color_theme => "Farbthema";
|
||||
@override
|
||||
String get settings_current_node => "Aktueller Knoten";
|
||||
@override
|
||||
String get copy_id => "ID kopieren";
|
||||
|
@ -886,12 +894,16 @@ class $de extends S {
|
|||
@override
|
||||
String get trade_state_confirming => "Bestätigung";
|
||||
@override
|
||||
String get bright_theme => "Hell";
|
||||
@override
|
||||
String get send => "Senden";
|
||||
@override
|
||||
String get send_title => "Senden Sie";
|
||||
@override
|
||||
String get error_text_keys => "Walletschlüssel können nur 64 hexadezimale Zeichen enthalten";
|
||||
@override
|
||||
String get light_theme => "Licht";
|
||||
@override
|
||||
String get settings_save_recipient_address => "Empfängeradresse speichern";
|
||||
@override
|
||||
String get change_exchange_provider => "Wechseln Sie den Exchange-Anbieter";
|
||||
|
@ -1086,6 +1098,8 @@ class $hi extends S {
|
|||
@override
|
||||
String get biometric_auth_reason => "प्रमाणित करने के लिए अपने फ़िंगरप्रिंट को स्कैन करें";
|
||||
@override
|
||||
String get dark_theme => "अंधेरा";
|
||||
@override
|
||||
String get transaction_sent => "भेजा गया लेन-देन";
|
||||
@override
|
||||
String get send_fee => "शुल्क:";
|
||||
|
@ -1328,7 +1342,7 @@ class $hi extends S {
|
|||
@override
|
||||
String get trade_details_created_at => "पर बनाया गया";
|
||||
@override
|
||||
String get send_success => "आपका Monero सफलतापूर्वक भेजा गया";
|
||||
String send_success(String crypto) => "आपका ${crypto} सफलतापूर्वक भेजा गया";
|
||||
@override
|
||||
String get settings_wallets => "पर्स";
|
||||
@override
|
||||
|
@ -1338,6 +1352,8 @@ class $hi extends S {
|
|||
@override
|
||||
String get filters => "फ़िल्टर";
|
||||
@override
|
||||
String get color_theme => "रंग विषय";
|
||||
@override
|
||||
String get settings_current_node => "वर्तमान नोड";
|
||||
@override
|
||||
String get copy_id => "प्रतिलिपि ID";
|
||||
|
@ -1578,12 +1594,16 @@ class $hi extends S {
|
|||
@override
|
||||
String get trade_state_confirming => "पुष्टि";
|
||||
@override
|
||||
String get bright_theme => "उज्ज्वल";
|
||||
@override
|
||||
String get send => "संदेश";
|
||||
@override
|
||||
String get send_title => "संदेश";
|
||||
@override
|
||||
String get error_text_keys => "वॉलेट कीज़ में हेक्स में केवल 64 वर्ण हो सकते हैं";
|
||||
@override
|
||||
String get light_theme => "रोशनी";
|
||||
@override
|
||||
String get settings_save_recipient_address => "प्राप्तकर्ता का पता सहेजें";
|
||||
@override
|
||||
String get change_exchange_provider => "एक्सचेंज प्रदाता बदलें";
|
||||
|
@ -1778,9 +1798,11 @@ class $ru extends S {
|
|||
@override
|
||||
String get biometric_auth_reason => "Отсканируйте свой отпечаток пальца для аутентификации";
|
||||
@override
|
||||
String get dark_theme => "Темная";
|
||||
@override
|
||||
String get transaction_sent => "Tранзакция отправлена!";
|
||||
@override
|
||||
String get send_fee => "Комиссия:";
|
||||
String get send_fee => "Комиссия";
|
||||
@override
|
||||
String get password => "Пароль";
|
||||
@override
|
||||
|
@ -2020,7 +2042,7 @@ class $ru extends S {
|
|||
@override
|
||||
String get trade_details_created_at => "Создано";
|
||||
@override
|
||||
String get send_success => "Ваш Monero был успешно отправлен";
|
||||
String send_success(String crypto) => "Ваш ${crypto} был успешно отправлен";
|
||||
@override
|
||||
String get settings_wallets => "Кошельки";
|
||||
@override
|
||||
|
@ -2030,6 +2052,8 @@ class $ru extends S {
|
|||
@override
|
||||
String get filters => "Фильтр";
|
||||
@override
|
||||
String get color_theme => "Цветовая тема";
|
||||
@override
|
||||
String get settings_current_node => "Текущая нода";
|
||||
@override
|
||||
String get copy_id => "Скопировать ID";
|
||||
|
@ -2270,12 +2294,16 @@ class $ru extends S {
|
|||
@override
|
||||
String get trade_state_confirming => "Подтверждение";
|
||||
@override
|
||||
String get bright_theme => "Яркая";
|
||||
@override
|
||||
String get send => "Отправить";
|
||||
@override
|
||||
String get send_title => "Отправить";
|
||||
@override
|
||||
String get error_text_keys => "Ключи кошелька могут содержать только 64 символа в hex";
|
||||
@override
|
||||
String get light_theme => "Светлая";
|
||||
@override
|
||||
String get settings_save_recipient_address => "Сохранять адрес получателя";
|
||||
@override
|
||||
String get change_exchange_provider => "Изменить провайдера обмена";
|
||||
|
@ -2470,9 +2498,11 @@ class $ko extends S {
|
|||
@override
|
||||
String get biometric_auth_reason => "지문을 스캔하여 인증";
|
||||
@override
|
||||
String get dark_theme => "어두운";
|
||||
@override
|
||||
String get transaction_sent => "거래가 전송되었습니다!";
|
||||
@override
|
||||
String get send_fee => "회비:";
|
||||
String get send_fee => "회비";
|
||||
@override
|
||||
String get password => "암호";
|
||||
@override
|
||||
|
@ -2712,7 +2742,7 @@ class $ko extends S {
|
|||
@override
|
||||
String get trade_details_created_at => "에 작성";
|
||||
@override
|
||||
String get send_success => "Monero가 성공적으로 전송되었습니다";
|
||||
String send_success(String crypto) => "${crypto}가 성공적으로 전송되었습니다";
|
||||
@override
|
||||
String get settings_wallets => "지갑";
|
||||
@override
|
||||
|
@ -2722,6 +2752,8 @@ class $ko extends S {
|
|||
@override
|
||||
String get filters => "필터";
|
||||
@override
|
||||
String get color_theme => "색상 테마";
|
||||
@override
|
||||
String get settings_current_node => "현재 노드";
|
||||
@override
|
||||
String get copy_id => "부 ID";
|
||||
|
@ -2962,12 +2994,16 @@ class $ko extends S {
|
|||
@override
|
||||
String get trade_state_confirming => "확인 중";
|
||||
@override
|
||||
String get bright_theme => "선명한";
|
||||
@override
|
||||
String get send => "보내다";
|
||||
@override
|
||||
String get send_title => "보내다";
|
||||
@override
|
||||
String get error_text_keys => "지갑 키는 16 진수로 64 자만 포함 할 수 있습니다";
|
||||
@override
|
||||
String get light_theme => "빛";
|
||||
@override
|
||||
String get settings_save_recipient_address => "수신자 주소 저장";
|
||||
@override
|
||||
String get change_exchange_provider => "교환 공급자 변경";
|
||||
|
@ -3162,9 +3198,11 @@ class $pt extends S {
|
|||
@override
|
||||
String get biometric_auth_reason => "Digitalize sua impressão digital para autenticar";
|
||||
@override
|
||||
String get dark_theme => "Sombria";
|
||||
@override
|
||||
String get transaction_sent => "Transação enviada!";
|
||||
@override
|
||||
String get send_fee => "Taxa:";
|
||||
String get send_fee => "Taxa";
|
||||
@override
|
||||
String get password => "Senha";
|
||||
@override
|
||||
|
@ -3404,7 +3442,7 @@ class $pt extends S {
|
|||
@override
|
||||
String get trade_details_created_at => "Criada em";
|
||||
@override
|
||||
String get send_success => "Seu Monero foi enviado com sucesso";
|
||||
String send_success(String crypto) => "Seu ${crypto} foi enviado com sucesso";
|
||||
@override
|
||||
String get settings_wallets => "Carteiras";
|
||||
@override
|
||||
|
@ -3414,6 +3452,8 @@ class $pt extends S {
|
|||
@override
|
||||
String get filters => "Filtro";
|
||||
@override
|
||||
String get color_theme => "Tema de cor";
|
||||
@override
|
||||
String get settings_current_node => "Nó atual";
|
||||
@override
|
||||
String get copy_id => "Copiar ID";
|
||||
|
@ -3654,12 +3694,16 @@ class $pt extends S {
|
|||
@override
|
||||
String get trade_state_confirming => "Confirmando";
|
||||
@override
|
||||
String get bright_theme => "Brilhante";
|
||||
@override
|
||||
String get send => "Enviar";
|
||||
@override
|
||||
String get send_title => "Enviar";
|
||||
@override
|
||||
String get error_text_keys => "As chaves da carteira podem conter apenas 64 caracteres em hexadecimal";
|
||||
@override
|
||||
String get light_theme => "Luz";
|
||||
@override
|
||||
String get settings_save_recipient_address => "Salvar endereço do destinatário";
|
||||
@override
|
||||
String get change_exchange_provider => "Alterar o provedor de troca";
|
||||
|
@ -3854,9 +3898,11 @@ class $uk extends S {
|
|||
@override
|
||||
String get biometric_auth_reason => "Відскануйте свій відбиток пальця для аутентифікації";
|
||||
@override
|
||||
String get dark_theme => "Темна";
|
||||
@override
|
||||
String get transaction_sent => "Tранзакцію відправлено!";
|
||||
@override
|
||||
String get send_fee => "Комісія:";
|
||||
String get send_fee => "Комісія";
|
||||
@override
|
||||
String get password => "Пароль";
|
||||
@override
|
||||
|
@ -4096,7 +4142,7 @@ class $uk extends S {
|
|||
@override
|
||||
String get trade_details_created_at => "Створено";
|
||||
@override
|
||||
String get send_success => "Ваш Monero успішно надісланий";
|
||||
String send_success(String crypto) => "Ваш ${crypto} успішно надісланий";
|
||||
@override
|
||||
String get settings_wallets => "Гаманці";
|
||||
@override
|
||||
|
@ -4106,6 +4152,8 @@ class $uk extends S {
|
|||
@override
|
||||
String get filters => "Фільтр";
|
||||
@override
|
||||
String get color_theme => "Кольорова тема";
|
||||
@override
|
||||
String get settings_current_node => "Поточний вузол";
|
||||
@override
|
||||
String get copy_id => "Скопіювати ID";
|
||||
|
@ -4346,12 +4394,16 @@ class $uk extends S {
|
|||
@override
|
||||
String get trade_state_confirming => "Підтвердження";
|
||||
@override
|
||||
String get bright_theme => "Яскрава";
|
||||
@override
|
||||
String get send => "Відправити";
|
||||
@override
|
||||
String get send_title => "Відправити";
|
||||
@override
|
||||
String get error_text_keys => "Ключі гаманця можуть містити тільки 64 символів в hex";
|
||||
@override
|
||||
String get light_theme => "Світла";
|
||||
@override
|
||||
String get settings_save_recipient_address => "Зберігати адресу отримувача";
|
||||
@override
|
||||
String get change_exchange_provider => "Змінити провайдера обміну";
|
||||
|
@ -4546,9 +4598,11 @@ class $ja extends S {
|
|||
@override
|
||||
String get biometric_auth_reason => "प指紋をスキャンして認証する";
|
||||
@override
|
||||
String get dark_theme => "闇";
|
||||
@override
|
||||
String get transaction_sent => "トランザクションが送信されました!";
|
||||
@override
|
||||
String get send_fee => "費用:";
|
||||
String get send_fee => "費用";
|
||||
@override
|
||||
String get password => "パスワード";
|
||||
@override
|
||||
|
@ -4788,7 +4842,7 @@ class $ja extends S {
|
|||
@override
|
||||
String get trade_details_created_at => "で作成";
|
||||
@override
|
||||
String get send_success => "Moneroが送信されました";
|
||||
String send_success(String crypto) => "${crypto}が送信されました";
|
||||
@override
|
||||
String get settings_wallets => "財布";
|
||||
@override
|
||||
|
@ -4798,6 +4852,8 @@ class $ja extends S {
|
|||
@override
|
||||
String get filters => "フィルタ";
|
||||
@override
|
||||
String get color_theme => "カラーテーマ";
|
||||
@override
|
||||
String get settings_current_node => "現在のノード";
|
||||
@override
|
||||
String get copy_id => "IDをコピー";
|
||||
|
@ -5038,12 +5094,16 @@ class $ja extends S {
|
|||
@override
|
||||
String get trade_state_confirming => "確認中";
|
||||
@override
|
||||
String get bright_theme => "明るい";
|
||||
@override
|
||||
String get send => "送る";
|
||||
@override
|
||||
String get send_title => "を送信";
|
||||
@override
|
||||
String get error_text_keys => "ウォレットキーには、16進数で64文字しか含めることができません";
|
||||
@override
|
||||
String get light_theme => "光";
|
||||
@override
|
||||
String get settings_save_recipient_address => "受信者のアドレスを保存";
|
||||
@override
|
||||
String get change_exchange_provider => "Exchangeプロバイダーの変更";
|
||||
|
@ -5242,9 +5302,11 @@ class $pl extends S {
|
|||
@override
|
||||
String get biometric_auth_reason => "Zeskanuj swój odcisk palca, aby go uwierzytelnić";
|
||||
@override
|
||||
String get dark_theme => "Ciemny";
|
||||
@override
|
||||
String get transaction_sent => "Transakcja wysłana!";
|
||||
@override
|
||||
String get send_fee => "Opłata:";
|
||||
String get send_fee => "Opłata";
|
||||
@override
|
||||
String get password => "Hasło";
|
||||
@override
|
||||
|
@ -5484,7 +5546,7 @@ class $pl extends S {
|
|||
@override
|
||||
String get trade_details_created_at => "Utworzono w";
|
||||
@override
|
||||
String get send_success => "Twoje Monero zostało pomyślnie wysłane";
|
||||
String send_success(String crypto) => "Twoje ${crypto} zostało pomyślnie wysłane";
|
||||
@override
|
||||
String get settings_wallets => "Portfele";
|
||||
@override
|
||||
|
@ -5494,6 +5556,8 @@ class $pl extends S {
|
|||
@override
|
||||
String get filters => "Filtr";
|
||||
@override
|
||||
String get color_theme => "Motyw kolorystyczny";
|
||||
@override
|
||||
String get settings_current_node => "Bieżący węzeł";
|
||||
@override
|
||||
String get copy_id => "ID kopii";
|
||||
|
@ -5734,12 +5798,16 @@ class $pl extends S {
|
|||
@override
|
||||
String get trade_state_confirming => "Potwierdzam";
|
||||
@override
|
||||
String get bright_theme => "Jasny";
|
||||
@override
|
||||
String get send => "Wysłać";
|
||||
@override
|
||||
String get send_title => "Wyślij";
|
||||
@override
|
||||
String get error_text_keys => "Klucze portfela mogą zawierać tylko 64 znaki w systemie szesnastkowym";
|
||||
@override
|
||||
String get light_theme => "Lekki";
|
||||
@override
|
||||
String get settings_save_recipient_address => "Zapisz adres odbiorcy";
|
||||
@override
|
||||
String get change_exchange_provider => "Zmień dostawcę programu Exchange";
|
||||
|
@ -5934,9 +6002,11 @@ class $es extends S {
|
|||
@override
|
||||
String get biometric_auth_reason => "Escanee su huella digital para autenticar";
|
||||
@override
|
||||
String get dark_theme => "Oscura";
|
||||
@override
|
||||
String get transaction_sent => "Transacción enviada!";
|
||||
@override
|
||||
String get send_fee => "Cuota:";
|
||||
String get send_fee => "Cuota";
|
||||
@override
|
||||
String get password => "Contraseña";
|
||||
@override
|
||||
|
@ -6176,7 +6246,7 @@ class $es extends S {
|
|||
@override
|
||||
String get trade_details_created_at => "Creado en";
|
||||
@override
|
||||
String get send_success => "Su Monero fue enviado con éxito";
|
||||
String send_success(String crypto) => "Su ${crypto} fue enviado con éxito";
|
||||
@override
|
||||
String get settings_wallets => "Carteras";
|
||||
@override
|
||||
|
@ -6186,6 +6256,8 @@ class $es extends S {
|
|||
@override
|
||||
String get filters => "Filtrar";
|
||||
@override
|
||||
String get color_theme => "Tema de color";
|
||||
@override
|
||||
String get settings_current_node => "Nodo actual";
|
||||
@override
|
||||
String get copy_id => "Copiar ID";
|
||||
|
@ -6426,12 +6498,16 @@ class $es extends S {
|
|||
@override
|
||||
String get trade_state_confirming => "Confirmando";
|
||||
@override
|
||||
String get bright_theme => "Brillante";
|
||||
@override
|
||||
String get send => "Enviar";
|
||||
@override
|
||||
String get send_title => "Enviar";
|
||||
@override
|
||||
String get error_text_keys => "Las llaves de billetera solo pueden contener 64 caracteres en hexadecimal";
|
||||
@override
|
||||
String get light_theme => "Ligera";
|
||||
@override
|
||||
String get settings_save_recipient_address => "Guardar dirección del destinatario";
|
||||
@override
|
||||
String get change_exchange_provider => "Cambiar proveedor de intercambio";
|
||||
|
@ -6626,9 +6702,11 @@ class $nl extends S {
|
|||
@override
|
||||
String get biometric_auth_reason => "Scan uw vingerafdruk om te verifiëren";
|
||||
@override
|
||||
String get dark_theme => "Donker";
|
||||
@override
|
||||
String get transaction_sent => "Transactie verzonden!";
|
||||
@override
|
||||
String get send_fee => "Vergoeding:";
|
||||
String get send_fee => "Vergoeding";
|
||||
@override
|
||||
String get password => "Wachtwoord";
|
||||
@override
|
||||
|
@ -6868,7 +6946,7 @@ class $nl extends S {
|
|||
@override
|
||||
String get trade_details_created_at => "Gemaakt bij";
|
||||
@override
|
||||
String get send_success => "Uw Monero is succesvol verzonden";
|
||||
String send_success(String crypto) => "Uw ${crypto} is succesvol verzonden";
|
||||
@override
|
||||
String get settings_wallets => "Portemonnee";
|
||||
@override
|
||||
|
@ -6878,6 +6956,8 @@ class $nl extends S {
|
|||
@override
|
||||
String get filters => "Filter";
|
||||
@override
|
||||
String get color_theme => "Kleur thema";
|
||||
@override
|
||||
String get settings_current_node => "Huidige knooppunt";
|
||||
@override
|
||||
String get copy_id => "ID kopiëren";
|
||||
|
@ -7118,12 +7198,16 @@ class $nl extends S {
|
|||
@override
|
||||
String get trade_state_confirming => "Bevestiging";
|
||||
@override
|
||||
String get bright_theme => "Helder";
|
||||
@override
|
||||
String get send => "Sturen";
|
||||
@override
|
||||
String get send_title => "Stuur";
|
||||
@override
|
||||
String get error_text_keys => "Portefeuillesleutels kunnen maximaal 64 tekens bevatten in hexadecimale volgorde";
|
||||
@override
|
||||
String get light_theme => "Licht";
|
||||
@override
|
||||
String get settings_save_recipient_address => "Adres ontvanger opslaan";
|
||||
@override
|
||||
String get change_exchange_provider => "Wijzig Exchange Provider";
|
||||
|
@ -7318,9 +7402,11 @@ class $zh extends S {
|
|||
@override
|
||||
String get biometric_auth_reason => "掃描指紋以進行身份驗證";
|
||||
@override
|
||||
String get dark_theme => "黑暗";
|
||||
@override
|
||||
String get transaction_sent => "交易已发送";
|
||||
@override
|
||||
String get send_fee => "費用:";
|
||||
String get send_fee => "費用";
|
||||
@override
|
||||
String get password => "密码";
|
||||
@override
|
||||
|
@ -7560,7 +7646,7 @@ class $zh extends S {
|
|||
@override
|
||||
String get trade_details_created_at => "创建于";
|
||||
@override
|
||||
String get send_success => "你Monero已成功發送";
|
||||
String send_success(String crypto) => "你${crypto}已成功發送";
|
||||
@override
|
||||
String get settings_wallets => "皮夹";
|
||||
@override
|
||||
|
@ -7570,6 +7656,8 @@ class $zh extends S {
|
|||
@override
|
||||
String get filters => "過濾";
|
||||
@override
|
||||
String get color_theme => "顏色主題";
|
||||
@override
|
||||
String get settings_current_node => "当前节点";
|
||||
@override
|
||||
String get copy_id => "复印ID";
|
||||
|
@ -7810,12 +7898,16 @@ class $zh extends S {
|
|||
@override
|
||||
String get trade_state_confirming => "确认中";
|
||||
@override
|
||||
String get bright_theme => "亮";
|
||||
@override
|
||||
String get send => "发送";
|
||||
@override
|
||||
String get send_title => "發送";
|
||||
@override
|
||||
String get error_text_keys => "钱包密钥只能包含16个字符的十六进制字符";
|
||||
@override
|
||||
String get light_theme => "光";
|
||||
@override
|
||||
String get settings_save_recipient_address => "保存收件人地址";
|
||||
@override
|
||||
String get change_exchange_provider => "更改交易所提供商";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
|
@ -83,7 +84,6 @@ void main() async {
|
|||
)))));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> initialSetup(
|
||||
{@required SharedPreferences sharedPreferences,
|
||||
@required Box<Node> nodes,
|
||||
|
@ -123,27 +123,25 @@ class App extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final settingsStore = getIt.get<AppStore>().settingsStore;
|
||||
|
||||
if (settingsStore.theme == null) {
|
||||
settingsStore.isDarkTheme = false;
|
||||
}
|
||||
|
||||
final statusBarColor = Colors.transparent;
|
||||
final statusBarBrightness =
|
||||
settingsStore.isDarkTheme ? Brightness.light : Brightness.dark;
|
||||
final statusBarIconBrightness =
|
||||
settingsStore.isDarkTheme ? Brightness.light : Brightness.dark;
|
||||
final authenticationStore = getIt.get<AuthenticationStore>();
|
||||
final initialRoute = authenticationStore.state == AuthenticationState.denied
|
||||
? Routes.disclaimer
|
||||
: Routes.login;
|
||||
|
||||
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
|
||||
statusBarColor: statusBarColor,
|
||||
statusBarBrightness: statusBarBrightness,
|
||||
statusBarIconBrightness: statusBarIconBrightness));
|
||||
|
||||
return Observer(builder: (BuildContext context) {
|
||||
final currentTheme = settingsStore.currentTheme;
|
||||
final statusBarBrightness = currentTheme.type == ThemeType.dark
|
||||
? Brightness.light
|
||||
: Brightness.dark;
|
||||
final statusBarIconBrightness = currentTheme.type == ThemeType.dark
|
||||
? Brightness.light
|
||||
: Brightness.dark;
|
||||
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
|
||||
statusBarColor: statusBarColor,
|
||||
statusBarBrightness: statusBarBrightness,
|
||||
statusBarIconBrightness: statusBarIconBrightness));
|
||||
|
||||
return Root(
|
||||
authenticationStore: authenticationStore,
|
||||
navigatorKey: navigatorKey,
|
||||
|
|
|
@ -1,20 +1,42 @@
|
|||
import 'package:cake_wallet/entities/balance.dart';
|
||||
import 'package:cake_wallet/entities/balance_display_mode.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:cake_wallet/monero/monero_amount_format.dart';
|
||||
|
||||
class MoneroBalance {
|
||||
class MoneroBalance extends Balance {
|
||||
MoneroBalance({@required this.fullBalance, @required this.unlockedBalance})
|
||||
: formattedFullBalance = moneroAmountToString(amount: fullBalance),
|
||||
formattedUnlockedBalance =
|
||||
moneroAmountToString(amount: unlockedBalance);
|
||||
moneroAmountToString(amount: unlockedBalance),
|
||||
super(const [
|
||||
BalanceDisplayMode.availableBalance,
|
||||
BalanceDisplayMode.fullBalance
|
||||
]);
|
||||
|
||||
MoneroBalance.fromString(
|
||||
{@required this.formattedFullBalance,
|
||||
@required this.formattedUnlockedBalance})
|
||||
@required this.formattedUnlockedBalance})
|
||||
: fullBalance = moneroParseAmount(amount: formattedFullBalance),
|
||||
unlockedBalance = moneroParseAmount(amount: formattedUnlockedBalance);
|
||||
unlockedBalance = moneroParseAmount(amount: formattedUnlockedBalance),
|
||||
super(const [
|
||||
BalanceDisplayMode.availableBalance,
|
||||
BalanceDisplayMode.fullBalance
|
||||
]);
|
||||
|
||||
final int fullBalance;
|
||||
final int unlockedBalance;
|
||||
final String formattedFullBalance;
|
||||
final String formattedUnlockedBalance;
|
||||
}
|
||||
|
||||
@override
|
||||
String formattedBalance(BalanceDisplayMode mode) {
|
||||
switch (mode) {
|
||||
case BalanceDisplayMode.fullBalance:
|
||||
return formattedFullBalance;
|
||||
case BalanceDisplayMode.availableBalance:
|
||||
return formattedUnlockedBalance;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
|
|||
balance = MoneroBalance(
|
||||
fullBalance: monero_wallet.getFullBalance(accountIndex: account.id),
|
||||
unlockedBalance:
|
||||
monero_wallet.getUnlockedBalance(accountIndex: account.id));
|
||||
monero_wallet.getUnlockedBalance(accountIndex: account.id));
|
||||
subaddressList.update(accountIndex: account.id);
|
||||
subaddress = subaddressList.subaddresses.first;
|
||||
address = subaddress.address;
|
||||
|
@ -120,6 +120,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void close() {
|
||||
_listener?.stop();
|
||||
_onAccountChangeReaction?.reaction?.dispose();
|
||||
|
@ -315,9 +316,8 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> _askForUpdateTransactionHistory() async {
|
||||
await transactionHistory.update();
|
||||
}
|
||||
Future<void> _askForUpdateTransactionHistory() async =>
|
||||
await transactionHistory.update();
|
||||
|
||||
int _getFullBalance() =>
|
||||
monero_wallet.getFullBalance(accountIndex: account.id);
|
||||
|
@ -326,13 +326,13 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
|
|||
monero_wallet.getUnlockedBalance(accountIndex: account.id);
|
||||
|
||||
Future<void> _afterSyncSave() async {
|
||||
if (_isSavingAfterSync) {
|
||||
return;
|
||||
}
|
||||
|
||||
_isSavingAfterSync = true;
|
||||
|
||||
try {
|
||||
if (_isSavingAfterSync) {
|
||||
return;
|
||||
}
|
||||
|
||||
_isSavingAfterSync = true;
|
||||
|
||||
final nowTimestamp = DateTime.now().millisecondsSinceEpoch;
|
||||
final sum = _lastAutosaveTimestamp + _autoAfterSyncSaveInterval;
|
||||
|
||||
|
@ -350,13 +350,13 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
|
|||
}
|
||||
|
||||
Future<void> _afterNewTransactionSave() async {
|
||||
if (_isSavingAfterNewTransaction) {
|
||||
return;
|
||||
}
|
||||
|
||||
_isSavingAfterNewTransaction = true;
|
||||
|
||||
try {
|
||||
if (_isSavingAfterNewTransaction) {
|
||||
return;
|
||||
}
|
||||
|
||||
_isSavingAfterNewTransaction = true;
|
||||
|
||||
await save();
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
|
@ -366,30 +366,38 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
|
|||
}
|
||||
|
||||
void _onNewBlock(int height, int blocksLeft, double ptc) async {
|
||||
if (walletInfo.isRecovery) {
|
||||
await _askForUpdateTransactionHistory();
|
||||
_askForUpdateBalance();
|
||||
accountList.update();
|
||||
}
|
||||
|
||||
if (blocksLeft < 100) {
|
||||
await _askForUpdateTransactionHistory();
|
||||
_askForUpdateBalance();
|
||||
accountList.update();
|
||||
syncStatus = SyncedSyncStatus();
|
||||
await _afterSyncSave();
|
||||
|
||||
try {
|
||||
if (walletInfo.isRecovery) {
|
||||
await setAsRecovered();
|
||||
await _askForUpdateTransactionHistory();
|
||||
_askForUpdateBalance();
|
||||
accountList.update();
|
||||
}
|
||||
} else {
|
||||
syncStatus = SyncingSyncStatus(blocksLeft, ptc);
|
||||
|
||||
if (blocksLeft < 100) {
|
||||
await _askForUpdateTransactionHistory();
|
||||
_askForUpdateBalance();
|
||||
accountList.update();
|
||||
syncStatus = SyncedSyncStatus();
|
||||
await _afterSyncSave();
|
||||
|
||||
if (walletInfo.isRecovery) {
|
||||
await setAsRecovered();
|
||||
}
|
||||
} else {
|
||||
syncStatus = SyncingSyncStatus(blocksLeft, ptc);
|
||||
}
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
void _onNewTransaction() {
|
||||
_askForUpdateTransactionHistory();
|
||||
_askForUpdateBalance();
|
||||
Timer(Duration(seconds: 1), () => _afterNewTransactionSave());
|
||||
try {
|
||||
_askForUpdateTransactionHistory();
|
||||
_askForUpdateBalance();
|
||||
Timer(Duration(seconds: 1), () => _afterNewTransactionSave());
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ class Palette {
|
|||
static const Color green = Color.fromRGBO(39, 206, 80, 1.0);
|
||||
static const Color red = Color.fromRGBO(255, 51, 51, 1.0);
|
||||
static const Color darkRed = Color.fromRGBO(204, 38, 38, 1.0);
|
||||
static const Color blueAlice = Color.fromRGBO(231, 240, 253, 1.0);
|
||||
static const Color blueAlice = Color.fromRGBO(229, 247, 255, 1.0);
|
||||
static const Color lightBlue = Color.fromRGBO(172, 203, 238, 1.0);
|
||||
static const Color lavender = Color.fromRGBO(237, 245, 252, 1.0);
|
||||
static const Color oceanBlue = Color.fromRGBO(30, 52, 78, 1.0);
|
||||
|
@ -13,7 +13,6 @@ class Palette {
|
|||
static const Color blue = Color.fromRGBO(88, 143, 252, 1.0);
|
||||
static const Color darkLavender = Color.fromRGBO(229, 238, 250, 1.0);
|
||||
static const Color nightBlue = Color.fromRGBO(46, 57, 96, 1.0);
|
||||
|
||||
static const Color moderateOrangeYellow = Color.fromRGBO(245, 134, 82, 1.0);
|
||||
static const Color moderateOrange = Color.fromRGBO(235, 117, 63, 1.0);
|
||||
static const Color shineGreen = Color.fromRGBO(76, 189, 87, 1.0);
|
||||
|
@ -22,9 +21,8 @@ class Palette {
|
|||
static const Color royalBlue = Color.fromRGBO(43, 114, 221, 1.0);
|
||||
static const Color lightRed = Color.fromRGBO(227, 87, 87, 1.0);
|
||||
static const Color persianRed = Color.fromRGBO(206, 55, 55, 1.0);
|
||||
|
||||
// NEW DESIGN
|
||||
static const Color blueCraiola = Color.fromRGBO(69, 110, 255, 1.0);
|
||||
static const Color blueGreyCraiola = Color.fromRGBO(106, 177, 207, 1.0);
|
||||
static const Color darkBlueCraiola = Color.fromRGBO(53, 86, 136, 1.0);
|
||||
static const Color pinkFlamingo = Color.fromRGBO(240, 60, 243, 1.0);
|
||||
static const Color redHat = Color.fromRGBO(209, 68, 37, 1.0);
|
||||
|
@ -43,26 +41,17 @@ class Palette {
|
|||
static const Color alizarinRed = Color.fromRGBO(233, 45, 45, 1.0);
|
||||
static const Color moderateSlateBlue = Color.fromRGBO(129, 93, 251, 1.0);
|
||||
static const Color brightOrange = Color.fromRGBO(255, 102, 0, 1.0);
|
||||
|
||||
// FIXME: Rename.
|
||||
static const Color eee = Color.fromRGBO(236, 239, 245, 1.0);
|
||||
static const Color xxx = Color.fromRGBO(72, 89, 109, 1);
|
||||
static const Color dullGray = Color.fromRGBO(98, 98, 98, 1.0);
|
||||
static const Color protectiveBlue = Color.fromRGBO(33, 148, 255, 1.0);
|
||||
}
|
||||
|
||||
class PaletteDark {
|
||||
//static const Color distantBlue = Color.fromRGBO(70, 85, 133, 1.0); // mainBackgroundColor
|
||||
static const Color lightDistantBlue = Color.fromRGBO(81, 96, 147, 1.0); // borderCardColor
|
||||
static const Color gray = Color.fromRGBO(140, 153, 201, 1.0); // walletCardText
|
||||
//static const Color violetBlue = Color.fromRGBO(51, 63, 104, 1.0); // walletCardAddressField
|
||||
//static const Color moderateBlue = Color.fromRGBO(63, 77, 122, 1.0); // walletCardSubAddressField
|
||||
//static const Color darkNightBlue = Color.fromRGBO(33, 43, 73, 1.0); // historyPanel
|
||||
static const Color pigeonBlue = Color.fromRGBO(91, 112, 146, 1.0); // historyPanelText
|
||||
static const Color moderateNightBlue = Color.fromRGBO(39, 53, 96, 1.0); // historyPanelButton
|
||||
static const Color headerNightBlue = Color.fromRGBO(41, 52, 84, 1.0); // menuHeader
|
||||
//static const Color lightNightBlue = Color.fromRGBO(48, 59, 95, 1.0); // menuList
|
||||
static const Color moderatePurpleBlue = Color.fromRGBO(57, 74, 95, 1.0); // selectButtonText
|
||||
|
||||
// NEW DESIGN
|
||||
static const Color lightDistantBlue = Color.fromRGBO(81, 96, 147, 1.0);
|
||||
static const Color gray = Color.fromRGBO(140, 153, 201, 1.0);
|
||||
static const Color pigeonBlue = Color.fromRGBO(91, 112, 146, 1.0);
|
||||
static const Color moderateNightBlue = Color.fromRGBO(39, 53, 96, 1.0);
|
||||
static const Color headerNightBlue = Color.fromRGBO(41, 52, 84, 1.0);
|
||||
static const Color moderatePurpleBlue = Color.fromRGBO(57, 74, 95, 1.0);
|
||||
static const Color backgroundColor = Color.fromRGBO(25, 35, 60, 1.0);
|
||||
static const Color nightBlue = Color.fromRGBO(35, 47, 79, 1.0);
|
||||
static const Color wildNightBlue = Color.fromRGBO(39, 53, 96, 1.0);
|
||||
|
@ -94,8 +83,5 @@ class PaletteDark {
|
|||
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.
|
||||
static const Color eee = Color.fromRGBO(236, 239, 245, 1.0);
|
||||
static const Color xxx = Color.fromRGBO(72, 89, 109, 1);
|
||||
static const Color granite = Color.fromRGBO(48, 51, 60, 1.0);
|
||||
}
|
|
@ -12,12 +12,13 @@ Future<void> startFiatRateUpdate(AppStore appStore, SettingsStore settingsStore,
|
|||
return;
|
||||
}
|
||||
|
||||
fiatConversionStore.price = await FiatConversionService.fetchPrice(
|
||||
appStore.wallet.currency, settingsStore.fiatCurrency);
|
||||
fiatConversionStore.prices[appStore.wallet.currency] =
|
||||
await FiatConversionService.fetchPrice(
|
||||
appStore.wallet.currency, settingsStore.fiatCurrency);
|
||||
|
||||
_timer = Timer.periodic(
|
||||
Duration(seconds: 30),
|
||||
(_) async => fiatConversionStore.price =
|
||||
(_) async => fiatConversionStore.prices[appStore.wallet.currency] =
|
||||
await FiatConversionService.fetchPrice(
|
||||
appStore.wallet.currency, settingsStore.fiatCurrency));
|
||||
}
|
||||
|
|
|
@ -7,12 +7,13 @@ import 'package:cake_wallet/entities/fiat_currency.dart';
|
|||
|
||||
ReactionDisposer _onCurrentFiatCurrencyChangeDisposer;
|
||||
|
||||
void startCurrentFiatChangeReaction(AppStore appStore, SettingsStore settingsStore, FiatConversionStore fiatConversionStore) {
|
||||
void startCurrentFiatChangeReaction(AppStore appStore,
|
||||
SettingsStore settingsStore, FiatConversionStore fiatConversionStore) {
|
||||
_onCurrentFiatCurrencyChangeDisposer?.reaction?.dispose();
|
||||
_onCurrentFiatCurrencyChangeDisposer = reaction(
|
||||
(_) => settingsStore.fiatCurrency, (FiatCurrency fiatCurrency) async {
|
||||
(_) => settingsStore.fiatCurrency, (FiatCurrency fiatCurrency) async {
|
||||
final cryptoCurrency = appStore.wallet.currency;
|
||||
fiatConversionStore.price = await FiatConversionService.fetchPrice(
|
||||
cryptoCurrency, fiatCurrency);
|
||||
fiatConversionStore.prices[appStore.wallet.currency] =
|
||||
await FiatConversionService.fetchPrice(cryptoCurrency, fiatCurrency);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,9 @@ ReactionDisposer _onCurrentNodeChangeReaction;
|
|||
|
||||
void startOnCurrentNodeChangeReaction(AppStore appStore) {
|
||||
_onCurrentNodeChangeReaction?.reaction?.dispose();
|
||||
_onCurrentNodeChangeReaction =
|
||||
reaction((_) => appStore.settingsStore.currentNode, (Node node) async {
|
||||
appStore.settingsStore.nodes.observe((change) async {
|
||||
try {
|
||||
await appStore.wallet.connectToNode(node: node);
|
||||
await appStore.wallet.connectToNode(node: change.newValue);
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import 'package:cake_wallet/core/wallet_base.dart';
|
|||
import 'package:cake_wallet/entities/wallet_type.dart';
|
||||
|
||||
ReactionDisposer _onCurrentWalletChangeReaction;
|
||||
ReactionDisposer _onCurrentWalletChangeFiatRateUpdateReaction;
|
||||
|
||||
void startCurrentWalletChangeReaction(AppStore appStore,
|
||||
SettingsStore settingsStore, FiatConversionStore fiatConversionStore) {
|
||||
|
@ -29,8 +30,16 @@ void startCurrentWalletChangeReaction(AppStore appStore,
|
|||
await getIt.get<SharedPreferences>().setInt(
|
||||
PreferencesKey.currentWalletType, serializeToInt(wallet.type));
|
||||
await wallet.connectToNode(node: node);
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
}
|
||||
});
|
||||
|
||||
fiatConversionStore.price = await FiatConversionService.fetchPrice(
|
||||
_onCurrentWalletChangeFiatRateUpdateReaction =
|
||||
reaction((_) => appStore.wallet, (WalletBase wallet) async {
|
||||
try {
|
||||
fiatConversionStore.prices[wallet.currency] = 0;
|
||||
fiatConversionStore.prices[wallet.currency] = await FiatConversionService.fetchPrice(
|
||||
wallet.currency, settingsStore.fiatCurrency);
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
|
|
|
@ -62,32 +62,21 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
|||
|
||||
case Routes.newWalletFromWelcome:
|
||||
return CupertinoPageRoute<void>(
|
||||
builder: (_) => getIt.get<SetupPinCodePage>(param1:
|
||||
(PinCodeState<PinCodeWidget> context, dynamic _) async {
|
||||
try {
|
||||
context.changeProcessText(
|
||||
S.current.creating_new_wallet);
|
||||
final newWalletVM =
|
||||
getIt.get<WalletNewVM>(param1: WalletType.monero);
|
||||
await newWalletVM.create(
|
||||
options: 'English'); // FIXME: Unnamed constant
|
||||
context.hideProgressText();
|
||||
await Navigator.of(context.context)
|
||||
.pushNamed(Routes.preSeed);
|
||||
} catch (e) {
|
||||
context.changeProcessText('Error: ${e.toString()}');
|
||||
}
|
||||
}),
|
||||
builder: (_) => getIt.get<SetupPinCodePage>(
|
||||
param1: (PinCodeState<PinCodeWidget> context, dynamic _) =>
|
||||
Navigator.of(context.context)
|
||||
.pushNamed(Routes.newWalletType)),
|
||||
fullscreenDialog: true);
|
||||
|
||||
case Routes.newWalletType:
|
||||
return CupertinoPageRoute<void>(
|
||||
builder: (_) => NewWalletTypePage(
|
||||
onTypeSelected: (context, type) => Navigator.of(context)
|
||||
.pushNamed(Routes.newWallet, arguments: type)));
|
||||
builder: (_) => getIt.get<NewWalletTypePage>(
|
||||
param1: (BuildContext context, WalletType _) =>
|
||||
Navigator.of(context).pushNamed(Routes.preSeed, arguments: true),
|
||||
param2: true));
|
||||
|
||||
case Routes.newWallet:
|
||||
final type = WalletType.monero; // settings.arguments as WalletType;
|
||||
final type = settings.arguments as WalletType;
|
||||
final walletNewVM = getIt.get<WalletNewVM>(param1: type);
|
||||
|
||||
return CupertinoPageRoute<void>(
|
||||
|
@ -106,11 +95,11 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
|||
|
||||
case Routes.restoreWalletType:
|
||||
return CupertinoPageRoute<void>(
|
||||
builder: (_) => NewWalletTypePage(
|
||||
onTypeSelected: (context, type) => Navigator.of(context)
|
||||
.pushNamed(Routes.restoreWalletOptions, arguments: type),
|
||||
isNewWallet: false,
|
||||
));
|
||||
builder: (_) => getIt.get<NewWalletTypePage>(
|
||||
param1: (BuildContext context, WalletType type) =>
|
||||
Navigator.of(context)
|
||||
.pushNamed(Routes.restoreWallet, arguments: type),
|
||||
param2: false));
|
||||
|
||||
case Routes.restoreOptions:
|
||||
final type = settings.arguments as WalletType;
|
||||
|
@ -148,7 +137,7 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
|||
return CupertinoPageRoute<void>(
|
||||
builder: (_) => getIt.get<SetupPinCodePage>(
|
||||
param1: (PinCodeState<PinCodeWidget> context, dynamic _) =>
|
||||
Navigator.pushNamed(context.context, Routes.restoreWallet)),
|
||||
Navigator.pushNamed(context.context, Routes.restoreWalletType)),
|
||||
fullscreenDialog: true);
|
||||
|
||||
case Routes.seed:
|
||||
|
@ -159,15 +148,10 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
|||
case Routes.restoreWallet:
|
||||
return MaterialPageRoute<void>(
|
||||
builder: (_) =>
|
||||
getIt.get<WalletRestorePage>(param1: WalletType.monero));
|
||||
getIt.get<WalletRestorePage>(param1: settings.arguments as WalletType));
|
||||
|
||||
case Routes.restoreWalletFromSeed:
|
||||
// final args = settings.arguments as List<dynamic>;
|
||||
final type = WalletType.monero; //args.first as WalletType;
|
||||
// final language = type == WalletType.monero
|
||||
// ? args[1] as String
|
||||
// : LanguageList.english;
|
||||
|
||||
final type = settings.arguments as WalletType;
|
||||
return CupertinoPageRoute<void>(
|
||||
builder: (_) => RestoreWalletFromSeedPage(type: type));
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
|
@ -9,13 +10,13 @@ enum AppBarStyle { regular, withShadow, transparent }
|
|||
|
||||
abstract class BasePage extends StatelessWidget {
|
||||
BasePage()
|
||||
: _scaffoldKey = GlobalKey<ScaffoldState>(),
|
||||
_closeButtonImage = Image.asset('assets/images/close_button.png'),
|
||||
_closeButtonImageDarkTheme =
|
||||
Image.asset('assets/images/close_button_dark_theme.png');
|
||||
: _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
final GlobalKey<ScaffoldState> _scaffoldKey;
|
||||
final Image _closeButtonImage;
|
||||
final Image _closeButtonImageDarkTheme;
|
||||
|
||||
final Image closeButtonImage =
|
||||
Image.asset('assets/images/close_button.png');
|
||||
final Image closeButtonImageDarkTheme =
|
||||
Image.asset('assets/images/close_button_dark_theme.png');
|
||||
|
||||
String get title => null;
|
||||
|
||||
|
@ -37,7 +38,7 @@ abstract class BasePage extends StatelessWidget {
|
|||
|
||||
Widget Function(BuildContext, Widget) get rootWrapper => null;
|
||||
|
||||
bool get isDarkTheme => getIt.get<SettingsStore>().isDarkTheme;
|
||||
ThemeBase get currentTheme => getIt.get<SettingsStore>().currentTheme;
|
||||
|
||||
void onOpenEndDrawer() => _scaffoldKey.currentState.openEndDrawer();
|
||||
|
||||
|
@ -51,8 +52,8 @@ abstract class BasePage extends StatelessWidget {
|
|||
final _backButton = Icon(Icons.arrow_back_ios,
|
||||
color: titleColor ?? Theme.of(context).primaryTextTheme.title.color,
|
||||
size: 16,);
|
||||
final _closeButton =
|
||||
isDarkTheme ? _closeButtonImageDarkTheme : _closeButtonImage;
|
||||
final _closeButton = currentTheme.type == ThemeType.dark
|
||||
? closeButtonImageDarkTheme : closeButtonImage;
|
||||
|
||||
return SizedBox(
|
||||
height: 37,
|
||||
|
@ -88,8 +89,8 @@ abstract class BasePage extends StatelessWidget {
|
|||
Widget floatingActionButton(BuildContext context) => null;
|
||||
|
||||
ObstructingPreferredSizeWidget appBar(BuildContext context) {
|
||||
final appBarColor =
|
||||
isDarkTheme ? backgroundDarkColor : backgroundLightColor;
|
||||
final appBarColor = currentTheme.type == ThemeType.dark
|
||||
? backgroundDarkColor : backgroundLightColor;
|
||||
|
||||
switch (appBarStyle) {
|
||||
case AppBarStyle.regular:
|
||||
|
@ -131,10 +132,12 @@ abstract class BasePage extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final _backgroundColor = currentTheme.type == ThemeType.dark
|
||||
? backgroundDarkColor : backgroundLightColor;
|
||||
|
||||
final root = Scaffold(
|
||||
key: _scaffoldKey,
|
||||
backgroundColor:
|
||||
isDarkTheme ? backgroundDarkColor : backgroundLightColor,
|
||||
backgroundColor: _backgroundColor,
|
||||
resizeToAvoidBottomPadding: resizeToAvoidBottomPadding,
|
||||
extendBodyBehindAppBar: extendBodyBehindAppBar,
|
||||
endDrawer: endDrawer,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||
|
@ -20,7 +21,8 @@ class DashboardPage extends BasePage {
|
|||
});
|
||||
|
||||
@override
|
||||
Color get backgroundLightColor => Colors.transparent;
|
||||
Color get backgroundLightColor => currentTheme.type == ThemeType.bright
|
||||
? Colors.transparent : Colors.white;
|
||||
|
||||
@override
|
||||
Color get backgroundDarkColor => Colors.transparent;
|
||||
|
@ -50,7 +52,8 @@ class DashboardPage extends BasePage {
|
|||
@override
|
||||
Widget trailing(BuildContext context) {
|
||||
final menuButton =
|
||||
Image.asset('assets/images/menu.png', color: Colors.white);
|
||||
Image.asset('assets/images/menu.png',
|
||||
color: Theme.of(context).accentTextTheme.display3.backgroundColor);
|
||||
|
||||
return Container(
|
||||
alignment: Alignment.centerRight,
|
||||
|
@ -65,12 +68,6 @@ class DashboardPage extends BasePage {
|
|||
|
||||
final DashboardViewModel walletViewModel;
|
||||
final WalletAddressListViewModel addressListViewModel;
|
||||
final sendImage = Image.asset('assets/images/upload.png',
|
||||
height: 22.24, width: 24, color: Colors.white);
|
||||
final exchangeImage = Image.asset('assets/images/transfer.png',
|
||||
height: 24.27, width: 22.25, color: Colors.white);
|
||||
final receiveImage = Image.asset('assets/images/download.png',
|
||||
height: 22.24, width: 24, color: Colors.white);
|
||||
final controller = PageController(initialPage: 1);
|
||||
|
||||
var pages = <Widget>[];
|
||||
|
@ -78,6 +75,15 @@ class DashboardPage extends BasePage {
|
|||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
final sendImage = Image.asset('assets/images/upload.png',
|
||||
height: 22.24, width: 24,
|
||||
color: Theme.of(context).accentTextTheme.display3.backgroundColor);
|
||||
final exchangeImage = Image.asset('assets/images/transfer.png',
|
||||
height: 24.27, width: 22.25,
|
||||
color: Theme.of(context).accentTextTheme.display3.backgroundColor);
|
||||
final receiveImage = Image.asset('assets/images/download.png',
|
||||
height: 22.24, width: 24,
|
||||
color: Theme.of(context).accentTextTheme.display3.backgroundColor);
|
||||
_setEffects();
|
||||
|
||||
return SafeArea(
|
||||
|
@ -100,7 +106,8 @@ class DashboardPage extends BasePage {
|
|||
dotWidth: 6.0,
|
||||
dotHeight: 6.0,
|
||||
dotColor: Theme.of(context).indicatorColor,
|
||||
activeDotColor: Colors.white),
|
||||
activeDotColor: Theme.of(context).accentTextTheme.display1
|
||||
.backgroundColor),
|
||||
)),
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 45, right: 45, bottom: 24),
|
||||
|
|
|
@ -9,44 +9,53 @@ import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
|||
// FIXME: terrible design
|
||||
|
||||
class WalletMenu {
|
||||
WalletMenu(this.context, this.reconnect);
|
||||
|
||||
final List<WalletMenuItem> items = [
|
||||
WalletMenuItem(
|
||||
title: S.current.reconnect,
|
||||
image: Image.asset('assets/images/reconnect_menu.png',
|
||||
height: 16, width: 16)),
|
||||
WalletMenuItem(
|
||||
title: S.current.rescan,
|
||||
image: Image.asset('assets/images/filter_icon.png',
|
||||
height: 16, width: 16)),
|
||||
WalletMenuItem(
|
||||
title: S.current.wallets,
|
||||
image: Image.asset('assets/images/wallet_menu.png',
|
||||
height: 16, width: 16)),
|
||||
WalletMenuItem(
|
||||
title: S.current.nodes,
|
||||
image:
|
||||
Image.asset('assets/images/nodes_menu.png', height: 16, width: 16)),
|
||||
WalletMenuItem(
|
||||
title: S.current.show_keys,
|
||||
image:
|
||||
Image.asset('assets/images/key_menu.png', height: 16, width: 16)),
|
||||
WalletMenuItem(
|
||||
title: S.current.address_book_menu,
|
||||
image: Image.asset('assets/images/open_book_menu.png',
|
||||
height: 16, width: 16)),
|
||||
WalletMenuItem(
|
||||
title: S.current.settings_title,
|
||||
image: Image.asset('assets/images/settings_menu.png',
|
||||
height: 16, width: 16)),
|
||||
];
|
||||
WalletMenu(this.context, this.reconnect, this.hasRescan) : items = [] {
|
||||
items.addAll([
|
||||
WalletMenuItem(
|
||||
title: S.current.reconnect,
|
||||
image: Image.asset('assets/images/reconnect_menu.png',
|
||||
height: 16, width: 16)),
|
||||
if (hasRescan)
|
||||
WalletMenuItem(
|
||||
title: S.current.rescan,
|
||||
image: Image.asset('assets/images/filter_icon.png',
|
||||
height: 16, width: 16)),
|
||||
WalletMenuItem(
|
||||
title: S.current.wallets,
|
||||
image: Image.asset('assets/images/wallet_menu.png',
|
||||
height: 16, width: 16)),
|
||||
WalletMenuItem(
|
||||
title: S.current.nodes,
|
||||
image: Image.asset('assets/images/nodes_menu.png',
|
||||
height: 16, width: 16)),
|
||||
WalletMenuItem(
|
||||
title: S.current.show_keys,
|
||||
image:
|
||||
Image.asset('assets/images/key_menu.png', height: 16, width: 16)),
|
||||
WalletMenuItem(
|
||||
title: S.current.address_book_menu,
|
||||
image: Image.asset('assets/images/open_book_menu.png',
|
||||
height: 16, width: 16)),
|
||||
WalletMenuItem(
|
||||
title: S.current.settings_title,
|
||||
image: Image.asset('assets/images/settings_menu.png',
|
||||
height: 16, width: 16)),
|
||||
]);
|
||||
}
|
||||
|
||||
final List<WalletMenuItem> items;
|
||||
final BuildContext context;
|
||||
final Future<void> Function() reconnect;
|
||||
final bool hasRescan;
|
||||
|
||||
void action(int index) {
|
||||
switch (index) {
|
||||
var indx = index;
|
||||
|
||||
if (index > 0 && !hasRescan) {
|
||||
indx += 1;
|
||||
}
|
||||
|
||||
switch (indx) {
|
||||
case 0:
|
||||
_presentReconnectAlert(context);
|
||||
break;
|
||||
|
|
|
@ -39,7 +39,10 @@ class ActionButton extends StatelessWidget {
|
|||
SizedBox(height: 15),
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(fontSize: 14, color: Colors.white),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Theme.of(context).accentTextTheme.display3
|
||||
.backgroundColor),
|
||||
)
|
||||
],
|
||||
),
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_v
|
|||
import 'package:cake_wallet/src/screens/receive/widgets/qr_widget.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
||||
class AddressPage extends StatelessWidget {
|
||||
AddressPage({@required this.addressListViewModel});
|
||||
|
@ -16,10 +17,9 @@ class AddressPage extends StatelessWidget {
|
|||
child: Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Center(
|
||||
child: QRWidget(addressListViewModel: addressListViewModel),
|
||||
)
|
||||
),
|
||||
child: Center(
|
||||
child: QRWidget(addressListViewModel: addressListViewModel),
|
||||
)),
|
||||
GestureDetector(
|
||||
onTap: () => Navigator.of(context).pushNamed(Routes.receive),
|
||||
child: Container(
|
||||
|
@ -27,29 +27,35 @@ class AddressPage extends StatelessWidget {
|
|||
padding: EdgeInsets.only(left: 24, right: 12),
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(25)),
|
||||
border: Border.all(
|
||||
color: Theme.of(context).textTheme.subhead.color,
|
||||
width: 1
|
||||
),
|
||||
color: Theme.of(context).buttonColor
|
||||
),
|
||||
borderRadius: BorderRadius.all(Radius.circular(25)),
|
||||
border: Border.all(
|
||||
color: Theme.of(context).textTheme.subhead.color,
|
||||
width: 1),
|
||||
color: Theme.of(context).buttonColor),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
S.of(context).accounts_subaddresses,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.white
|
||||
),
|
||||
),
|
||||
Observer(
|
||||
builder: (_) => Text(
|
||||
addressListViewModel.hasAccounts
|
||||
? S.of(context).accounts_subaddresses
|
||||
: S.of(context).addresses,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.display3
|
||||
.backgroundColor),
|
||||
)),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
size: 14,
|
||||
color: Colors.white,
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.display3
|
||||
.backgroundColor,
|
||||
)
|
||||
],
|
||||
),
|
||||
|
@ -59,4 +65,4 @@ class AddressPage extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,59 +10,76 @@ class BalancePage extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(24),
|
||||
child: GestureDetector(
|
||||
onTapUp: (_) => dashboardViewModel.balanceViewModel.isReversing = false,
|
||||
onTapDown: (_) => dashboardViewModel.balanceViewModel.isReversing = true,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Observer(builder: (_) {
|
||||
return Text(
|
||||
dashboardViewModel.balanceViewModel.currency.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 40,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).indicatorColor,
|
||||
height: 1),
|
||||
);
|
||||
}),
|
||||
Observer(builder: (_) {
|
||||
return Text(
|
||||
dashboardViewModel.balanceViewModel.displayMode.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).indicatorColor,
|
||||
height: 1),
|
||||
);
|
||||
}),
|
||||
SizedBox(height: 10),
|
||||
Observer(builder: (_) {
|
||||
return AutoSizeText(dashboardViewModel.balanceViewModel.cryptoBalance,
|
||||
return GestureDetector(
|
||||
onTapUp: (_) {
|
||||
if (dashboardViewModel.balanceViewModel.canReverse) {
|
||||
dashboardViewModel.balanceViewModel.isReversing = false;
|
||||
}
|
||||
},
|
||||
onTapDown: (_) {
|
||||
if (dashboardViewModel.balanceViewModel.canReverse) {
|
||||
dashboardViewModel.balanceViewModel.isReversing = true;
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
padding: EdgeInsets.all(24),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Observer(builder: (_) {
|
||||
return Text(
|
||||
dashboardViewModel.balanceViewModel.currency.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 54,
|
||||
fontSize: 40,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white,
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.display2
|
||||
.backgroundColor,
|
||||
height: 1),
|
||||
maxLines: 1,
|
||||
textAlign: TextAlign.center);
|
||||
}),
|
||||
SizedBox(height: 10),
|
||||
Observer(builder: (_) {
|
||||
return Text(dashboardViewModel.balanceViewModel.fiatBalance,
|
||||
);
|
||||
}),
|
||||
Observer(builder: (_) {
|
||||
return Text(
|
||||
dashboardViewModel.balanceViewModel.displayMode.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).indicatorColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.display2
|
||||
.backgroundColor,
|
||||
height: 1),
|
||||
textAlign: TextAlign.center);
|
||||
}),
|
||||
],
|
||||
),
|
||||
)
|
||||
);
|
||||
);
|
||||
}),
|
||||
SizedBox(height: 10),
|
||||
Observer(builder: (_) {
|
||||
return AutoSizeText(
|
||||
dashboardViewModel.balanceViewModel.cryptoBalance,
|
||||
style: TextStyle(
|
||||
fontSize: 40,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.display3
|
||||
.backgroundColor,
|
||||
height: 1),
|
||||
);
|
||||
}),
|
||||
SizedBox(height: 10),
|
||||
Observer(builder: (_) {
|
||||
return Text(dashboardViewModel.balanceViewModel.fiatBalance,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).indicatorColor,
|
||||
height: 1),
|
||||
textAlign: TextAlign.center);
|
||||
}),
|
||||
],
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,14 +27,15 @@ class HeaderRow extends StatelessWidget {
|
|||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.white
|
||||
color: Theme.of(context).accentTextTheme.display3.backgroundColor
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (context) => FilterWidget(dashboardViewModel: dashboardViewModel)
|
||||
builder: (context) =>
|
||||
FilterWidget(dashboardViewModel: dashboardViewModel)
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
|
|
|
@ -66,8 +66,10 @@ class MenuWidgetState extends State<MenuWidget> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final walletMenu =
|
||||
WalletMenu(context, () async => widget.dashboardViewModel.reconnect());
|
||||
final walletMenu = WalletMenu(
|
||||
context,
|
||||
() async => widget.dashboardViewModel.reconnect(),
|
||||
widget.dashboardViewModel.hasRescan);
|
||||
final itemCount = walletMenu.items.length;
|
||||
|
||||
moneroIcon = Image.asset('assets/images/monero_menu.png',
|
||||
|
@ -148,16 +150,19 @@ class MenuWidgetState extends State<MenuWidget> {
|
|||
),
|
||||
if (widget.dashboardViewModel.subname !=
|
||||
null)
|
||||
Observer(builder: (_) => Text(
|
||||
widget.dashboardViewModel.subname,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.overline
|
||||
.decorationColor,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 12),
|
||||
))
|
||||
Observer(
|
||||
builder: (_) => Text(
|
||||
widget.dashboardViewModel
|
||||
.subname,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.overline
|
||||
.decorationColor,
|
||||
fontWeight:
|
||||
FontWeight.w500,
|
||||
fontSize: 12),
|
||||
))
|
||||
],
|
||||
),
|
||||
))
|
||||
|
|
|
@ -48,14 +48,16 @@ class TradeRow extends StatelessWidget {
|
|||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.white
|
||||
color: Theme.of(context).accentTextTheme.
|
||||
display3.backgroundColor
|
||||
)),
|
||||
formattedAmount != null
|
||||
? Text(formattedAmount + ' ' + amountCrypto,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.white
|
||||
color: Theme.of(context).accentTextTheme.
|
||||
display3.backgroundColor
|
||||
))
|
||||
: Container()
|
||||
]),
|
||||
|
|
|
@ -60,12 +60,14 @@ class TransactionRow extends StatelessWidget {
|
|||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.white)),
|
||||
color: Theme.of(context).accentTextTheme.
|
||||
display3.backgroundColor)),
|
||||
Text(formattedAmount,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.white))
|
||||
color: Theme.of(context).accentTextTheme.
|
||||
display3.backgroundColor))
|
||||
]),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
|
|
|
@ -46,7 +46,8 @@ class TransactionsPage extends StatelessWidget {
|
|||
if (item is TransactionListItem) {
|
||||
final transaction = item.transaction;
|
||||
|
||||
return TransactionRow(
|
||||
return Observer(
|
||||
builder: (_) => TransactionRow(
|
||||
onTap: () => Navigator.of(context).pushNamed(
|
||||
Routes.transactionDetails,
|
||||
arguments: transaction),
|
||||
|
@ -55,7 +56,7 @@ class TransactionsPage extends StatelessWidget {
|
|||
.format(transaction.date),
|
||||
formattedAmount: item.formattedCryptoAmount,
|
||||
formattedFiatAmount: item.formattedFiatAmount,
|
||||
isPending: transaction.isPending);
|
||||
isPending: transaction.isPending));
|
||||
}
|
||||
|
||||
if (item is TradeListItem) {
|
||||
|
|
|
@ -95,9 +95,8 @@ class ExchangePage extends BasePage {
|
|||
return KeyboardActions(
|
||||
config: KeyboardActionsConfig(
|
||||
keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
|
||||
keyboardBarColor: isDarkTheme
|
||||
? Color.fromRGBO(48, 51, 60, 1.0)
|
||||
: Color.fromRGBO(98, 98, 98, 1.0),
|
||||
keyboardBarColor: Theme.of(context).accentTextTheme.body2
|
||||
.backgroundColor,
|
||||
nextFocus: false,
|
||||
actions: [
|
||||
KeyboardActionsItem(
|
||||
|
|
|
@ -166,8 +166,8 @@ class ExchangeCardState extends State<ExchangeCard> {
|
|||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.subhead
|
||||
.accentTextTheme
|
||||
.display4
|
||||
.decorationColor),
|
||||
validator: _isAmountEditable
|
||||
? widget.currencyValueValidator
|
||||
|
@ -211,8 +211,8 @@ class ExchangeCardState extends State<ExchangeCard> {
|
|||
fontSize: 10,
|
||||
height: 1.2,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.subhead
|
||||
.accentTextTheme
|
||||
.display4
|
||||
.decorationColor),
|
||||
)
|
||||
: Offstage(),
|
||||
|
@ -224,8 +224,8 @@ class ExchangeCardState extends State<ExchangeCard> {
|
|||
fontSize: 10,
|
||||
height: 1.2,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.subhead
|
||||
.accentTextTheme
|
||||
.display4
|
||||
.decorationColor))
|
||||
: Offstage(),
|
||||
]),
|
||||
|
@ -239,7 +239,10 @@ class ExchangeCardState extends State<ExchangeCard> {
|
|||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color:
|
||||
Theme.of(context).textTheme.subhead.decorationColor),
|
||||
Theme.of(context)
|
||||
.accentTextTheme
|
||||
.display4
|
||||
.decorationColor),
|
||||
))
|
||||
: Offstage(),
|
||||
_isAddressEditable
|
||||
|
@ -263,7 +266,10 @@ class ExchangeCardState extends State<ExchangeCard> {
|
|||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color:
|
||||
Theme.of(context).textTheme.subhead.decorationColor),
|
||||
Theme.of(context)
|
||||
.accentTextTheme
|
||||
.display4
|
||||
.decorationColor),
|
||||
buttonColor: widget.addressButtonsColor,
|
||||
validator: widget.addressTextFieldValidator,
|
||||
),
|
||||
|
|
|
@ -205,16 +205,15 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
|
|||
final sendingState =
|
||||
widget.exchangeTradeViewModel.sendViewModel.state;
|
||||
|
||||
return trade.from == CryptoCurrency.xmr && !(sendingState is TransactionCommitted)
|
||||
return widget.exchangeTradeViewModel.isSendable &&
|
||||
!(sendingState is TransactionCommitted)
|
||||
? LoadingPrimaryButton(
|
||||
isDisabled: trade.inputAddress == null ||
|
||||
trade.inputAddress.isEmpty,
|
||||
isLoading: sendingState is IsExecutingState,
|
||||
onPressed: () =>
|
||||
widget.exchangeTradeViewModel.confirmSending(),
|
||||
text: trade.provider == ExchangeProviderDescription.xmrto
|
||||
? S.of(context).confirm
|
||||
: S.of(context).send_xmr,
|
||||
text: S.of(context).confirm,
|
||||
color: Theme.of(context).accentTextTheme.body2.color,
|
||||
textColor: Colors.white)
|
||||
: Offstage();
|
||||
|
@ -284,7 +283,11 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
|
|||
padding: EdgeInsets.only(
|
||||
top: 220, left: 24, right: 24),
|
||||
child: Text(
|
||||
S.of(context).send_success,
|
||||
S.of(context).send_success(widget
|
||||
.exchangeTradeViewModel
|
||||
.wallet
|
||||
.currency
|
||||
.toString()),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 22,
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
@ -22,17 +21,24 @@ class NewWalletPage extends BasePage {
|
|||
|
||||
final WalletNewVM _walletNewVM;
|
||||
|
||||
final walletNameImage = Image.asset('assets/images/wallet_name.png');
|
||||
final walletNameLightImage =
|
||||
Image.asset('assets/images/wallet_name_light.png');
|
||||
|
||||
@override
|
||||
String get title => S.current.new_wallet;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) => WalletNameForm(_walletNewVM);
|
||||
Widget body(BuildContext context) => WalletNameForm(_walletNewVM,
|
||||
currentTheme.type == ThemeType.dark
|
||||
? walletNameImage : walletNameLightImage);
|
||||
}
|
||||
|
||||
class WalletNameForm extends StatefulWidget {
|
||||
WalletNameForm(this._walletNewVM);
|
||||
WalletNameForm(this._walletNewVM, this.walletImage);
|
||||
|
||||
final WalletNewVM _walletNewVM;
|
||||
final Image walletImage;
|
||||
|
||||
@override
|
||||
_WalletNameFormState createState() => _WalletNameFormState(_walletNewVM);
|
||||
|
@ -43,9 +49,6 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
|||
|
||||
static const aspectRatioImage = 1.22;
|
||||
|
||||
final walletNameImage = Image.asset('assets/images/wallet_name.png');
|
||||
final walletNameLightImage =
|
||||
Image.asset('assets/images/wallet_name_light.png');
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final _languageSelectorKey = GlobalKey<SeedLanguageSelectorState>();
|
||||
ReactionDisposer _stateReaction;
|
||||
|
@ -78,10 +81,6 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final walletImage = getIt.get<SettingsStore>().isDarkTheme
|
||||
? walletNameImage
|
||||
: walletNameLightImage;
|
||||
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: ScrollableWithBottomSection(
|
||||
|
@ -92,7 +91,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
|||
padding: EdgeInsets.only(left: 12, right: 12),
|
||||
child: AspectRatio(
|
||||
aspectRatio: aspectRatioImage,
|
||||
child: FittedBox(child: walletImage, fit: BoxFit.fill)),
|
||||
child: FittedBox(child: widget.walletImage, fit: BoxFit.fill)),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
import 'package:cake_wallet/core/execution_state.dart';
|
||||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/entities/wallet_type.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/utils/show_bar.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_new_vm.dart';
|
||||
import 'package:flushbar/flushbar.dart';
|
||||
import 'package:cake_wallet/entities/wallet_type.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
|
@ -10,25 +17,36 @@ import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
|||
import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
|
||||
|
||||
class NewWalletTypePage extends BasePage {
|
||||
NewWalletTypePage({this.onTypeSelected, this.isNewWallet = true});
|
||||
NewWalletTypePage(this.walletNewVM, {this.onTypeSelected, this.isNewWallet});
|
||||
|
||||
final void Function(BuildContext, WalletType) onTypeSelected;
|
||||
final bool isNewWallet;
|
||||
final WalletNewVM walletNewVM;
|
||||
|
||||
final walletTypeImage = Image.asset('assets/images/wallet_type.png');
|
||||
final walletTypeLightImage =
|
||||
Image.asset('assets/images/wallet_type_light.png');
|
||||
|
||||
@override
|
||||
String get title => isNewWallet
|
||||
? S.current.new_wallet
|
||||
: S.current.wallet_list_restore_wallet;
|
||||
String get title =>
|
||||
isNewWallet ? S.current.new_wallet : S.current.wallet_list_restore_wallet;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) =>
|
||||
WalletTypeForm(onTypeSelected: onTypeSelected);
|
||||
Widget body(BuildContext context) => WalletTypeForm(walletNewVM, isNewWallet,
|
||||
onTypeSelected: onTypeSelected,
|
||||
walletImage: currentTheme.type == ThemeType.dark
|
||||
? walletTypeImage
|
||||
: walletTypeLightImage);
|
||||
}
|
||||
|
||||
class WalletTypeForm extends StatefulWidget {
|
||||
WalletTypeForm({this.onTypeSelected});
|
||||
WalletTypeForm(this.walletNewVM, this.isNewWallet,
|
||||
{this.onTypeSelected, this.walletImage});
|
||||
|
||||
final void Function(BuildContext, WalletType) onTypeSelected;
|
||||
final WalletNewVM walletNewVM;
|
||||
final bool isNewWallet;
|
||||
final Image walletImage;
|
||||
|
||||
@override
|
||||
WalletTypeFormState createState() => WalletTypeFormState();
|
||||
|
@ -42,10 +60,12 @@ class WalletTypeFormState extends State<WalletTypeForm> {
|
|||
final bitcoinIcon =
|
||||
Image.asset('assets/images/bitcoin.png', height: 24, width: 24);
|
||||
final walletTypeImage = Image.asset('assets/images/wallet_type.png');
|
||||
final walletTypeLightImage = Image.asset('assets/images/wallet_type_light.png');
|
||||
final walletTypeLightImage =
|
||||
Image.asset('assets/images/wallet_type_light.png');
|
||||
|
||||
WalletType selected;
|
||||
List<WalletType> types;
|
||||
Flushbar<void> _progressBar;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
@ -55,11 +75,8 @@ class WalletTypeFormState extends State<WalletTypeForm> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final walletImage = getIt.get<SettingsStore>().isDarkTheme
|
||||
? walletTypeImage : walletTypeLightImage;
|
||||
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
padding: EdgeInsets.only(top: 24, bottom: 24),
|
||||
child: ScrollableWithBottomSection(
|
||||
contentPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
|
||||
content: Column(
|
||||
|
@ -69,7 +86,8 @@ class WalletTypeFormState extends State<WalletTypeForm> {
|
|||
padding: EdgeInsets.only(left: 12, right: 12),
|
||||
child: AspectRatio(
|
||||
aspectRatio: aspectRatioImage,
|
||||
child: FittedBox(child: walletImage, fit: BoxFit.fill)),
|
||||
child:
|
||||
FittedBox(child: widget.walletImage, fit: BoxFit.fill)),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 48),
|
||||
|
@ -86,7 +104,7 @@ class WalletTypeFormState extends State<WalletTypeForm> {
|
|||
padding: EdgeInsets.only(top: 24),
|
||||
child: SelectButton(
|
||||
image: _iconFor(type),
|
||||
text: walletTypeToString(type),
|
||||
text: walletTypeToDisplayName(type),
|
||||
isSelected: selected == type,
|
||||
onTap: () => setState(() => selected = type)),
|
||||
))
|
||||
|
@ -94,9 +112,9 @@ class WalletTypeFormState extends State<WalletTypeForm> {
|
|||
),
|
||||
bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
|
||||
bottomSection: PrimaryButton(
|
||||
onPressed: () => widget.onTypeSelected(context, selected),
|
||||
onPressed: () => onTypeSelected(),
|
||||
text: S.of(context).seed_language_next,
|
||||
color: Colors.green,
|
||||
color: Theme.of(context).accentTextTheme.body2.color,
|
||||
textColor: Colors.white,
|
||||
isDisabled: selected == null,
|
||||
),
|
||||
|
@ -114,4 +132,35 @@ class WalletTypeFormState extends State<WalletTypeForm> {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> onTypeSelected() async {
|
||||
if (!widget.isNewWallet) {
|
||||
widget.onTypeSelected(context, selected);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
_changeProcessText(S.of(context).creating_new_wallet);
|
||||
widget.walletNewVM.type = selected;
|
||||
await widget.walletNewVM
|
||||
.create(options: 'English'); // FIXME: Unnamed constant
|
||||
await _progressBar?.dismiss();
|
||||
final state = widget.walletNewVM.state;
|
||||
|
||||
if (state is ExecutedSuccessfullyState) {
|
||||
widget.onTypeSelected(context, selected);
|
||||
}
|
||||
|
||||
if (state is FailureState) {
|
||||
_changeProcessText(
|
||||
S.of(context).creating_new_wallet_error(state.error));
|
||||
}
|
||||
} catch (e) {
|
||||
_changeProcessText(S.of(context).creating_new_wallet_error(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
void _changeProcessText(String text) {
|
||||
_progressBar = createBar<void>(text, duration: null)..show(context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ class SelectButton extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final color = isSelected
|
||||
? Theme.of(context).accentTextTheme.subtitle.decorationColor
|
||||
? Colors.green
|
||||
: Theme.of(context).accentTextTheme.caption.color;
|
||||
final textColor = isSelected
|
||||
? Theme.of(context).accentTextTheme.headline.decorationColor
|
||||
|
|
|
@ -65,98 +65,90 @@ class NodeListPage extends BasePage {
|
|||
padding: EdgeInsets.only(top: 10),
|
||||
child: Observer(
|
||||
builder: (BuildContext context) {
|
||||
return nodeListViewModel.nodes.isNotEmpty
|
||||
? SectionStandardList(
|
||||
sectionCount: 2,
|
||||
context: context,
|
||||
itemCounter: (int sectionIndex) {
|
||||
if (sectionIndex == 0) {
|
||||
return 1;
|
||||
}
|
||||
return SectionStandardList(
|
||||
sectionCount: 2,
|
||||
context: context,
|
||||
itemCounter: (int sectionIndex) {
|
||||
if (sectionIndex == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return nodeListViewModel.nodes.length;
|
||||
},
|
||||
itemBuilder: (_, sectionIndex, index) {
|
||||
if (sectionIndex == 0) {
|
||||
return NodeHeaderListRow(
|
||||
title: S.of(context).add_new_node,
|
||||
onTap: (_) async => await Navigator.of(context)
|
||||
.pushNamed(Routes.newNode));
|
||||
}
|
||||
return nodeListViewModel.nodes.length;
|
||||
},
|
||||
itemBuilder: (_, sectionIndex, index) {
|
||||
if (sectionIndex == 0) {
|
||||
return NodeHeaderListRow(
|
||||
title: S.of(context).add_new_node,
|
||||
onTap: (_) async => await Navigator.of(context)
|
||||
.pushNamed(Routes.newNode));
|
||||
}
|
||||
|
||||
final node = nodeListViewModel.nodes[index];
|
||||
final isSelected = node.keyIndex ==
|
||||
nodeListViewModel.settingsStore.currentNode.keyIndex;
|
||||
final nodeListRow = NodeListRow(
|
||||
title: node.uri,
|
||||
isSelected: isSelected,
|
||||
isAlive: node.requestNode(),
|
||||
onTap: (_) async {
|
||||
if (isSelected) {
|
||||
return;
|
||||
final node = nodeListViewModel.nodes[index];
|
||||
final isSelected =
|
||||
node.keyIndex == nodeListViewModel.currentNode?.keyIndex;
|
||||
final nodeListRow = NodeListRow(
|
||||
title: node.uri,
|
||||
isSelected: isSelected,
|
||||
isAlive: node.requestNode(),
|
||||
onTap: (_) async {
|
||||
if (isSelected) {
|
||||
return;
|
||||
}
|
||||
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithTwoActions(
|
||||
alertTitle:
|
||||
S.of(context).change_current_node_title,
|
||||
alertContent:
|
||||
S.of(context).change_current_node(node.uri),
|
||||
leftButtonText: S.of(context).cancel,
|
||||
rightButtonText: S.of(context).change,
|
||||
actionLeftButton: () =>
|
||||
Navigator.of(context).pop(),
|
||||
actionRightButton: () async {
|
||||
await nodeListViewModel.setAsCurrent(node);
|
||||
Navigator.of(context).pop();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
final dismissibleRow = Slidable(
|
||||
key: Key('${node.keyIndex}'),
|
||||
actionPane: SlidableDrawerActionPane(),
|
||||
child: nodeListRow,
|
||||
secondaryActions: <Widget>[
|
||||
IconSlideAction(
|
||||
caption: S.of(context).delete,
|
||||
color: Colors.red,
|
||||
icon: CupertinoIcons.delete,
|
||||
onTap: () async {
|
||||
final confirmed = await showPopUp<bool>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithTwoActions(
|
||||
alertTitle: S.of(context).remove_node,
|
||||
alertContent:
|
||||
S.of(context).remove_node_message,
|
||||
rightButtonText: S.of(context).remove,
|
||||
leftButtonText: S.of(context).cancel,
|
||||
actionRightButton: () =>
|
||||
Navigator.pop(context, true),
|
||||
actionLeftButton: () =>
|
||||
Navigator.pop(context, false));
|
||||
}) ??
|
||||
false;
|
||||
|
||||
if (confirmed) {
|
||||
await nodeListViewModel.delete(node);
|
||||
}
|
||||
},
|
||||
),
|
||||
]);
|
||||
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithTwoActions(
|
||||
alertTitle: S.of(context)
|
||||
.change_current_node_title,
|
||||
alertContent: S
|
||||
.of(context)
|
||||
.change_current_node(node.uri),
|
||||
leftButtonText: S.of(context).cancel,
|
||||
rightButtonText: S.of(context).change,
|
||||
actionLeftButton: () =>
|
||||
Navigator.of(context).pop(),
|
||||
actionRightButton: () async {
|
||||
await nodeListViewModel
|
||||
.setAsCurrent(node);
|
||||
Navigator.of(context).pop();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
final dismissibleRow = Slidable(
|
||||
key: Key('${node.keyIndex}'),
|
||||
actionPane: SlidableDrawerActionPane(),
|
||||
child: nodeListRow,
|
||||
secondaryActions: <Widget>[
|
||||
IconSlideAction(
|
||||
caption: S.of(context).delete,
|
||||
color: Colors.red,
|
||||
icon: CupertinoIcons.delete,
|
||||
onTap: () async {
|
||||
final confirmed = await showPopUp<bool>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithTwoActions(
|
||||
alertTitle:
|
||||
S.of(context).remove_node,
|
||||
alertContent: S
|
||||
.of(context)
|
||||
.remove_node_message,
|
||||
rightButtonText:
|
||||
S.of(context).remove,
|
||||
leftButtonText:
|
||||
S.of(context).cancel,
|
||||
actionRightButton: () =>
|
||||
Navigator.pop(context, true),
|
||||
actionLeftButton: () =>
|
||||
Navigator.pop(context, false));
|
||||
}) ??
|
||||
false;
|
||||
|
||||
if (confirmed) {
|
||||
await nodeListViewModel.delete(node);
|
||||
}
|
||||
},
|
||||
),
|
||||
]);
|
||||
|
||||
return isSelected ? nodeListRow : dismissibleRow;
|
||||
})
|
||||
: Container();
|
||||
return isSelected ? nodeListRow : dismissibleRow;
|
||||
});
|
||||
},
|
||||
),
|
||||
);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
@ -27,16 +28,47 @@ class ReceivePage extends BasePage {
|
|||
String get title => S.current.receive;
|
||||
|
||||
@override
|
||||
Color get backgroundLightColor => Colors.transparent;
|
||||
Color get backgroundLightColor => currentTheme.type == ThemeType.bright
|
||||
? Colors.transparent : Colors.white;
|
||||
|
||||
@override
|
||||
Color get backgroundDarkColor => Colors.transparent;
|
||||
|
||||
@override
|
||||
Color get titleColor => Colors.white;
|
||||
|
||||
final FocusNode _cryptoAmountFocus;
|
||||
|
||||
@override
|
||||
Widget leading(BuildContext context) {
|
||||
final _backButton = Icon(Icons.arrow_back_ios,
|
||||
color: Theme.of(context).accentTextTheme.display3.backgroundColor,
|
||||
size: 16,);
|
||||
|
||||
return SizedBox(
|
||||
height: 37,
|
||||
width: 37,
|
||||
child: ButtonTheme(
|
||||
minWidth: double.minPositive,
|
||||
child: FlatButton(
|
||||
highlightColor: Colors.transparent,
|
||||
splashColor: Colors.transparent,
|
||||
padding: EdgeInsets.all(0),
|
||||
onPressed: () => onClose(context),
|
||||
child: _backButton),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget middle(BuildContext context) {
|
||||
return Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: 18.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: 'Lato',
|
||||
color: Theme.of(context).accentTextTheme.display3.backgroundColor),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget Function(BuildContext, Widget) get rootWrapper =>
|
||||
(BuildContext context, Widget scaffold) => Container(
|
||||
|
@ -51,7 +83,8 @@ class ReceivePage extends BasePage {
|
|||
@override
|
||||
Widget trailing(BuildContext context) {
|
||||
final shareImage =
|
||||
Image.asset('assets/images/share.png', color: Colors.white);
|
||||
Image.asset('assets/images/share.png',
|
||||
color: Theme.of(context).accentTextTheme.display3.backgroundColor);
|
||||
|
||||
return SizedBox(
|
||||
height: 20.0,
|
||||
|
@ -74,9 +107,8 @@ class ReceivePage extends BasePage {
|
|||
return KeyboardActions(
|
||||
config: KeyboardActionsConfig(
|
||||
keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
|
||||
keyboardBarColor: isDarkTheme
|
||||
? Color.fromRGBO(48, 51, 60, 1.0)
|
||||
: Color.fromRGBO(98, 98, 98, 1.0),
|
||||
keyboardBarColor: Theme.of(context).accentTextTheme.body2
|
||||
.backgroundColor,
|
||||
nextFocus: false,
|
||||
actions: [
|
||||
KeyboardActionsItem(
|
||||
|
|
|
@ -47,8 +47,8 @@ class QRWidget extends StatelessWidget {
|
|||
child: QrImage(
|
||||
data: addressListViewModel.uri.toString(),
|
||||
backgroundColor: Colors.transparent,
|
||||
foregroundColor: Colors.white,
|
||||
//Theme.of(context).textTheme.headline.color,
|
||||
foregroundColor: Theme.of(context).accentTextTheme.
|
||||
display3.backgroundColor,
|
||||
))))),
|
||||
Spacer(flex: 3)
|
||||
]),
|
||||
|
@ -67,11 +67,12 @@ class QRWidget extends StatelessWidget {
|
|||
decimal: true),
|
||||
inputFormatters: [
|
||||
BlacklistingTextInputFormatter(
|
||||
RegExp('[\\-|\\ |\\,]'))
|
||||
RegExp('[\\-|\\ ]'))
|
||||
],
|
||||
textAlign: TextAlign.center,
|
||||
hintText: S.of(context).receive_amount,
|
||||
textColor: Colors.white,
|
||||
textColor: Theme.of(context).accentTextTheme.
|
||||
display3.backgroundColor,
|
||||
borderColor: Theme.of(context)
|
||||
.textTheme
|
||||
.headline
|
||||
|
@ -110,7 +111,8 @@ class QRWidget extends StatelessWidget {
|
|||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.white),
|
||||
color: Theme.of(context).accentTextTheme.
|
||||
display3.backgroundColor),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'package:cake_wallet/entities/wallet_type.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_restore_view_model.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
|
@ -7,12 +9,20 @@ import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
|||
import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart';
|
||||
|
||||
class WalletRestoreFromSeedForm extends StatefulWidget {
|
||||
WalletRestoreFromSeedForm({Key key, this.blockHeightFocusNode,
|
||||
this.onHeightOrDateEntered})
|
||||
WalletRestoreFromSeedForm(
|
||||
{Key key,
|
||||
@required this.displayLanguageSelector,
|
||||
@required this.displayBlockHeightSelector,
|
||||
@required this.type,
|
||||
this.blockHeightFocusNode,
|
||||
this.onHeightOrDateEntered})
|
||||
: super(key: key);
|
||||
|
||||
final WalletType type;
|
||||
final bool displayLanguageSelector;
|
||||
final bool displayBlockHeightSelector;
|
||||
final FocusNode blockHeightFocusNode;
|
||||
final Function (bool) onHeightOrDateEntered;
|
||||
final Function(bool) onHeightOrDateEntered;
|
||||
|
||||
@override
|
||||
WalletRestoreFromSeedFormState createState() =>
|
||||
|
@ -41,32 +51,35 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
|||
return Container(
|
||||
padding: EdgeInsets.only(left: 25, right: 25),
|
||||
child: Column(children: [
|
||||
SeedWidget(key: seedWidgetStateKey, language: language),
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
final selected = await showPopUp<String>(
|
||||
context: context,
|
||||
builder: (BuildContext context) =>
|
||||
SeedLanguagePicker(selected: language));
|
||||
SeedWidget(
|
||||
key: seedWidgetStateKey, language: language, type: widget.type),
|
||||
if (widget.displayLanguageSelector)
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
final selected = await showPopUp<String>(
|
||||
context: context,
|
||||
builder: (BuildContext context) =>
|
||||
SeedLanguagePicker(selected: language));
|
||||
|
||||
if (selected == null || selected.isEmpty) {
|
||||
return;
|
||||
}
|
||||
if (selected == null || selected.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
_changeLanguage(selected);
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
padding: EdgeInsets.only(top: 20.0),
|
||||
child: IgnorePointer(
|
||||
child: BaseTextFormField(
|
||||
controller: languageController,
|
||||
enableInteractiveSelection: false,
|
||||
readOnly: true)))),
|
||||
BlockchainHeightWidget(
|
||||
focusNode: widget.blockHeightFocusNode,
|
||||
key: blockchainHeightKey,
|
||||
onHeightOrDateEntered: widget.onHeightOrDateEntered)
|
||||
_changeLanguage(selected);
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
padding: EdgeInsets.only(top: 20.0),
|
||||
child: IgnorePointer(
|
||||
child: BaseTextFormField(
|
||||
controller: languageController,
|
||||
enableInteractiveSelection: false,
|
||||
readOnly: true)))),
|
||||
if (widget.displayBlockHeightSelector)
|
||||
BlockchainHeightWidget(
|
||||
focusNode: widget.blockHeightFocusNode,
|
||||
key: blockchainHeightKey,
|
||||
onHeightOrDateEntered: widget.onHeightOrDateEntered)
|
||||
]));
|
||||
}
|
||||
|
||||
|
|
|
@ -25,16 +25,30 @@ class WalletRestorePage extends BasePage {
|
|||
_pages = [],
|
||||
_blockHeightFocusNode = FocusNode(),
|
||||
_controller = PageController(initialPage: 0) {
|
||||
_pages.addAll([
|
||||
WalletRestoreFromSeedForm(
|
||||
key: walletRestoreFromSeedFormKey,
|
||||
blockHeightFocusNode: _blockHeightFocusNode,
|
||||
onHeightOrDateEntered: (value)
|
||||
=> walletRestoreViewModel.isButtonEnabled = value),
|
||||
WalletRestoreFromKeysFrom(key: walletRestoreFromKeysFormKey,
|
||||
onHeightOrDateEntered: (value)
|
||||
=> walletRestoreViewModel.isButtonEnabled = value)
|
||||
]);
|
||||
walletRestoreViewModel.availableModes.forEach((mode) {
|
||||
switch (mode) {
|
||||
case WalletRestoreMode.seed:
|
||||
_pages.add(WalletRestoreFromSeedForm(
|
||||
displayBlockHeightSelector:
|
||||
walletRestoreViewModel.hasBlockchainHeightLanguageSelector,
|
||||
displayLanguageSelector:
|
||||
walletRestoreViewModel.hasSeedLanguageSelector,
|
||||
type: walletRestoreViewModel.type,
|
||||
key: walletRestoreFromSeedFormKey,
|
||||
blockHeightFocusNode: _blockHeightFocusNode,
|
||||
onHeightOrDateEntered: (value) =>
|
||||
walletRestoreViewModel.isButtonEnabled = value));
|
||||
break;
|
||||
case WalletRestoreMode.keys:
|
||||
_pages.add(WalletRestoreFromKeysFrom(
|
||||
key: walletRestoreFromKeysFormKey,
|
||||
onHeightOrDateEntered: (value) =>
|
||||
walletRestoreViewModel.isButtonEnabled = value));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -76,20 +90,19 @@ class WalletRestorePage extends BasePage {
|
|||
}
|
||||
});
|
||||
|
||||
reaction((_) => walletRestoreViewModel.mode, (WalletRestoreMode mode)
|
||||
{
|
||||
walletRestoreViewModel.isButtonEnabled = false;
|
||||
reaction((_) => walletRestoreViewModel.mode, (WalletRestoreMode mode) {
|
||||
walletRestoreViewModel.isButtonEnabled = false;
|
||||
|
||||
walletRestoreFromSeedFormKey.currentState.blockchainHeightKey
|
||||
.currentState.restoreHeightController.text = '';
|
||||
walletRestoreFromSeedFormKey.currentState.blockchainHeightKey
|
||||
.currentState.dateController.text = '';
|
||||
walletRestoreFromSeedFormKey.currentState.blockchainHeightKey.currentState
|
||||
.restoreHeightController.text = '';
|
||||
walletRestoreFromSeedFormKey.currentState.blockchainHeightKey.currentState
|
||||
.dateController.text = '';
|
||||
|
||||
walletRestoreFromKeysFormKey.currentState.blockchainHeightKey
|
||||
.currentState.restoreHeightController.text = '';
|
||||
walletRestoreFromKeysFormKey.currentState.blockchainHeightKey
|
||||
.currentState.dateController.text = '';
|
||||
});
|
||||
walletRestoreFromKeysFormKey.currentState.blockchainHeightKey.currentState
|
||||
.restoreHeightController.text = '';
|
||||
walletRestoreFromKeysFormKey.currentState.blockchainHeightKey.currentState
|
||||
.dateController.text = '';
|
||||
});
|
||||
|
||||
return Column(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||
Expanded(
|
||||
|
@ -100,40 +113,37 @@ class WalletRestorePage extends BasePage {
|
|||
},
|
||||
controller: _controller,
|
||||
itemCount: _pages.length,
|
||||
itemBuilder: (_, index) => SingleChildScrollView(child: _pages[index]))),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: SmoothPageIndicator(
|
||||
controller: _controller,
|
||||
count: _pages.length,
|
||||
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),
|
||||
)),
|
||||
itemBuilder: (_, index) =>
|
||||
SingleChildScrollView(child: _pages[index]))),
|
||||
if (_pages.length > 1)
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: SmoothPageIndicator(
|
||||
controller: _controller,
|
||||
count: _pages.length,
|
||||
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: Observer(
|
||||
builder: (context) {
|
||||
return LoadingPrimaryButton(
|
||||
onPressed: () =>
|
||||
walletRestoreViewModel.create(options: _credentials()),
|
||||
text: S.of(context).restore_recover,
|
||||
color: Theme
|
||||
.of(context)
|
||||
.accentTextTheme
|
||||
.subtitle
|
||||
.decorationColor,
|
||||
textColor: Theme
|
||||
.of(context)
|
||||
.accentTextTheme
|
||||
.headline
|
||||
.decorationColor,
|
||||
isLoading: walletRestoreViewModel.state is IsExecutingState,
|
||||
isDisabled: !walletRestoreViewModel.isButtonEnabled,);
|
||||
onPressed: () =>
|
||||
walletRestoreViewModel.create(options: _credentials()),
|
||||
text: S.of(context).restore_recover,
|
||||
color:
|
||||
Theme.of(context).accentTextTheme.subtitle.decorationColor,
|
||||
textColor:
|
||||
Theme.of(context).accentTextTheme.headline.decorationColor,
|
||||
isLoading: walletRestoreViewModel.state is IsExecutingState,
|
||||
isDisabled: !walletRestoreViewModel.isButtonEnabled,
|
||||
);
|
||||
},
|
||||
))
|
||||
]);
|
||||
|
@ -145,8 +155,11 @@ class WalletRestorePage extends BasePage {
|
|||
if (walletRestoreViewModel.mode == WalletRestoreMode.seed) {
|
||||
credentials['seed'] = walletRestoreFromSeedFormKey
|
||||
.currentState.seedWidgetStateKey.currentState.text;
|
||||
credentials['height'] = walletRestoreFromSeedFormKey
|
||||
.currentState.blockchainHeightKey.currentState.height;
|
||||
|
||||
if (walletRestoreViewModel.hasBlockchainHeightLanguageSelector) {
|
||||
credentials['height'] = walletRestoreFromSeedFormKey
|
||||
.currentState.blockchainHeightKey.currentState.height;
|
||||
}
|
||||
} else {
|
||||
credentials['address'] =
|
||||
walletRestoreFromKeysFormKey.currentState.addressController.text;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
|
@ -8,8 +7,8 @@ import 'package:cake_wallet/src/widgets/primary_button.dart';
|
|||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
|
||||
class PreSeedPage extends BasePage {
|
||||
static final imageLight = Image.asset('assets/images/pre_seed_light.png');
|
||||
static final imageDark = Image.asset('assets/images/pre_seed_dark.png');
|
||||
final imageLight = Image.asset('assets/images/pre_seed_light.png');
|
||||
final imageDark = Image.asset('assets/images/pre_seed_dark.png');
|
||||
|
||||
@override
|
||||
Widget leading(BuildContext context) => null;
|
||||
|
@ -19,8 +18,7 @@ class PreSeedPage extends BasePage {
|
|||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
final image =
|
||||
getIt.get<SettingsStore>().isDarkTheme ? imageDark : imageLight;
|
||||
final image = currentTheme.type == ThemeType.dark ? imageDark : imageLight;
|
||||
|
||||
return WillPopScope(
|
||||
onWillPop: () async => false,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/utils/show_bar.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
@ -17,8 +16,8 @@ import 'package:cake_wallet/view_model/wallet_seed_view_model.dart';
|
|||
class WalletSeedPage extends BasePage {
|
||||
WalletSeedPage(this.walletSeedViewModel, {@required this.isNewWalletCreated});
|
||||
|
||||
static final imageLight = Image.asset('assets/images/crypto_lock_light.png');
|
||||
static final imageDark = Image.asset('assets/images/crypto_lock.png');
|
||||
final imageLight = Image.asset('assets/images/crypto_lock_light.png');
|
||||
final imageDark = Image.asset('assets/images/crypto_lock.png');
|
||||
|
||||
@override
|
||||
String get title => S.current.seed_title;
|
||||
|
@ -83,8 +82,7 @@ class WalletSeedPage extends BasePage {
|
|||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
final image =
|
||||
getIt.get<SettingsStore>().isDarkTheme ? imageDark : imageLight;
|
||||
final image = currentTheme.type == ThemeType.dark ? imageDark : imageLight;
|
||||
|
||||
return WillPopScope(onWillPop: () async => false, child: Container(
|
||||
padding: EdgeInsets.all(24),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:cake_wallet/src/widgets/seed_language_selector.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
@ -15,17 +14,26 @@ class SeedLanguage extends BasePage {
|
|||
|
||||
final Function(BuildContext, String) onConfirm;
|
||||
|
||||
final walletNameImage = Image.asset('assets/images/wallet_name.png');
|
||||
final walletNameLightImage =
|
||||
Image.asset('assets/images/wallet_name_light.png');
|
||||
|
||||
@override
|
||||
String get title => S.current.wallet_list_restore_wallet;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) => SeedLanguageForm(onConfirm: onConfirm);
|
||||
Widget body(BuildContext context) =>
|
||||
SeedLanguageForm(
|
||||
onConfirm: onConfirm,
|
||||
walletImage: currentTheme.type == ThemeType.dark
|
||||
? walletNameImage : walletNameLightImage);
|
||||
}
|
||||
|
||||
class SeedLanguageForm extends StatefulWidget {
|
||||
SeedLanguageForm({this.onConfirm});
|
||||
SeedLanguageForm({this.onConfirm, this.walletImage});
|
||||
|
||||
final Function(BuildContext, String) onConfirm;
|
||||
final Image walletImage;
|
||||
|
||||
@override
|
||||
SeedLanguageFormState createState() => SeedLanguageFormState();
|
||||
|
@ -33,18 +41,10 @@ class SeedLanguageForm extends StatefulWidget {
|
|||
|
||||
class SeedLanguageFormState extends State<SeedLanguageForm> {
|
||||
static const aspectRatioImage = 1.22;
|
||||
|
||||
final walletNameImage = Image.asset('assets/images/wallet_name.png');
|
||||
final walletNameLightImage =
|
||||
Image.asset('assets/images/wallet_name_light.png');
|
||||
final _languageSelectorKey = GlobalKey<SeedLanguageSelectorState>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final walletImage = getIt.get<SettingsStore>().isDarkTheme
|
||||
? walletNameImage
|
||||
: walletNameLightImage;
|
||||
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: ScrollableWithBottomSection(
|
||||
|
@ -55,7 +55,8 @@ class SeedLanguageFormState extends State<SeedLanguageForm> {
|
|||
padding: EdgeInsets.only(left: 12, right: 12),
|
||||
child: AspectRatio(
|
||||
aspectRatio: aspectRatioImage,
|
||||
child: FittedBox(child: walletImage, fit: BoxFit.fill)),
|
||||
child: FittedBox(child: widget.walletImage,
|
||||
fit: BoxFit.fill)),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 40),
|
||||
|
|
|
@ -83,9 +83,8 @@ class SendPage extends BasePage {
|
|||
return KeyboardActions(
|
||||
config: KeyboardActionsConfig(
|
||||
keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
|
||||
keyboardBarColor: isDarkTheme
|
||||
? Color.fromRGBO(48, 51, 60, 1.0)
|
||||
: Color.fromRGBO(98, 98, 98, 1.0),
|
||||
keyboardBarColor: Theme.of(context).accentTextTheme.body2
|
||||
.backgroundColor,
|
||||
nextFocus: false,
|
||||
actions: [
|
||||
KeyboardActionsItem(
|
||||
|
@ -133,7 +132,8 @@ class SendPage extends BasePage {
|
|||
|
||||
if (uri != null) {
|
||||
address = uri.path;
|
||||
amount = uri.queryParameters['tx_amount'];
|
||||
amount = uri.queryParameters['tx_amount'] ??
|
||||
uri.queryParameters['amount'];
|
||||
} else {
|
||||
address = uri.toString();
|
||||
}
|
||||
|
@ -497,14 +497,8 @@ class SendPage extends BasePage {
|
|||
}
|
||||
},
|
||||
text: S.of(context).send,
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.subtitle
|
||||
.decorationColor,
|
||||
textColor: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.headline
|
||||
.decorationColor,
|
||||
color: Theme.of(context).accentTextTheme.body2.color,
|
||||
textColor: Colors.white,
|
||||
isLoading: sendViewModel.state is IsExecutingState ||
|
||||
sendViewModel.state is TransactionCommitting,
|
||||
isDisabled:
|
||||
|
@ -634,7 +628,9 @@ class SendPage extends BasePage {
|
|||
padding: EdgeInsets.only(
|
||||
top: 220, left: 24, right: 24),
|
||||
child: Text(
|
||||
S.of(context).send_success,
|
||||
S.of(context).send_success(
|
||||
sendViewModel.currency
|
||||
.toString()),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 22,
|
||||
|
@ -748,7 +744,7 @@ class SendPage extends BasePage {
|
|||
}
|
||||
|
||||
Future<void> _setTransactionPriority(BuildContext context) async {
|
||||
final items = TransactionPriority.all;
|
||||
final items = TransactionPriority.forWalletType(sendViewModel.walletType);
|
||||
final selectedItem = items.indexOf(sendViewModel.transactionPriority);
|
||||
|
||||
await showPopUp<void>(
|
||||
|
|
|
@ -49,9 +49,8 @@ class SendTemplatePage extends BasePage {
|
|||
return KeyboardActions(
|
||||
config: KeyboardActionsConfig(
|
||||
keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
|
||||
keyboardBarColor: isDarkTheme
|
||||
? Color.fromRGBO(48, 51, 60, 1.0)
|
||||
: Color.fromRGBO(98, 98, 98, 1.0),
|
||||
keyboardBarColor: Theme.of(context).accentTextTheme.body2
|
||||
.backgroundColor,
|
||||
nextFocus: false,
|
||||
actions: [
|
||||
KeyboardActionsItem(
|
||||
|
@ -113,7 +112,8 @@ class SendTemplatePage extends BasePage {
|
|||
|
||||
if (uri != null) {
|
||||
address = uri.path;
|
||||
amount = uri.queryParameters['tx_amount'];
|
||||
amount = uri.queryParameters['tx_amount'] ??
|
||||
uri.queryParameters['amount'];
|
||||
} else {
|
||||
address = uri.toString();
|
||||
}
|
||||
|
@ -246,9 +246,8 @@ class SendTemplatePage extends BasePage {
|
|||
}
|
||||
},
|
||||
text: S.of(context).save,
|
||||
color: Theme.of(context).accentTextTheme.subtitle.decorationColor,
|
||||
textColor:
|
||||
Theme.of(context).accentTextTheme.headline.decorationColor,
|
||||
color: Colors.green,
|
||||
textColor: Colors.white,
|
||||
),
|
||||
),
|
||||
));
|
||||
|
|
|
@ -13,7 +13,8 @@ import 'package:cake_wallet/utils/date_formatter.dart';
|
|||
import 'package:hive/hive.dart';
|
||||
|
||||
class TransactionDetailsPage extends BasePage {
|
||||
TransactionDetailsPage(this.transactionInfo, bool showRecipientAddress, Box<TransactionDescription> transactionDescriptionBox)
|
||||
TransactionDetailsPage(this.transactionInfo, bool showRecipientAddress,
|
||||
Box<TransactionDescription> transactionDescriptionBox)
|
||||
: _items = [] {
|
||||
final dateFormat = DateFormatter.withCurrentLocal();
|
||||
final tx = transactionInfo;
|
||||
|
@ -30,21 +31,9 @@ class TransactionDetailsPage extends BasePage {
|
|||
StandartListItem(
|
||||
title: S.current.transaction_details_amount,
|
||||
value: tx.amountFormatted()),
|
||||
StandartListItem(
|
||||
title: S.current.send_fee,
|
||||
value: tx.feeFormatted())
|
||||
StandartListItem(title: S.current.send_fee, value: tx.feeFormatted())
|
||||
];
|
||||
|
||||
if (showRecipientAddress) {
|
||||
final recipientAddress = transactionDescriptionBox.values.firstWhere((val) => val.id == transactionInfo.id, orElse: () => null)?.recipientAddress;
|
||||
|
||||
if (recipientAddress?.isNotEmpty ?? false) {
|
||||
items.add(StandartListItem(
|
||||
title: S.current.transaction_details_recipient_address,
|
||||
value: recipientAddress));
|
||||
}
|
||||
}
|
||||
|
||||
if (tx.key?.isNotEmpty ?? null) {
|
||||
// FIXME: add translation
|
||||
items.add(StandartListItem(title: 'Transaction Key', value: tx.key));
|
||||
|
@ -66,11 +55,25 @@ class TransactionDetailsPage extends BasePage {
|
|||
title: S.current.transaction_details_height, value: '${tx.height}'),
|
||||
StandartListItem(
|
||||
title: S.current.transaction_details_amount,
|
||||
value: tx.amountFormatted())
|
||||
value: tx.amountFormatted()),
|
||||
if (tx.feeFormatted()?.isNotEmpty)
|
||||
StandartListItem(title: S.current.send_fee, value: tx.feeFormatted())
|
||||
];
|
||||
|
||||
_items.addAll(items);
|
||||
}
|
||||
|
||||
if (showRecipientAddress) {
|
||||
final recipientAddress = transactionDescriptionBox.values
|
||||
.firstWhere((val) => val.id == transactionInfo.id, orElse: () => null)
|
||||
?.recipientAddress;
|
||||
|
||||
if (recipientAddress?.isNotEmpty ?? false) {
|
||||
_items.add(StandartListItem(
|
||||
title: S.current.transaction_details_recipient_address,
|
||||
value: recipientAddress));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import 'package:cake_wallet/src/screens/auth/auth_page.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_list/widgets/wallet_menu_alert.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/utils/show_bar.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
|
@ -15,7 +14,6 @@ import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart';
|
|||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_list/wallet_menu.dart';
|
||||
import 'package:flutter_slidable/flutter_slidable.dart';
|
||||
|
||||
class WalletListPage extends BasePage {
|
||||
|
@ -51,7 +49,7 @@ class WalletListBodyState extends State<WalletListBody> {
|
|||
final newWalletImage = Image.asset('assets/images/new_wallet.png',
|
||||
height: 12,
|
||||
width: 12,
|
||||
color: Theme.of(context).accentTextTheme.headline.decorationColor);
|
||||
color: Colors.white);
|
||||
final restoreWalletImage = Image.asset('assets/images/restore_wallet.png',
|
||||
height: 12,
|
||||
width: 12,
|
||||
|
@ -165,17 +163,16 @@ class WalletListBodyState extends State<WalletListBody> {
|
|||
),
|
||||
bottomSection: Column(children: <Widget>[
|
||||
PrimaryImageButton(
|
||||
onPressed: () => _generateNewWallet(),
|
||||
onPressed: () => Navigator.of(context).pushNamed(Routes.newWalletType),
|
||||
image: newWalletImage,
|
||||
text: S.of(context).wallet_list_create_new_wallet,
|
||||
color: Theme.of(context).accentTextTheme.subtitle.decorationColor,
|
||||
textColor:
|
||||
Theme.of(context).accentTextTheme.headline.decorationColor,
|
||||
color: Theme.of(context).accentTextTheme.body2.color,
|
||||
textColor: Colors.white,
|
||||
),
|
||||
SizedBox(height: 10.0),
|
||||
PrimaryImageButton(
|
||||
onPressed: () =>
|
||||
Navigator.of(context).pushNamed(Routes.restoreWallet),
|
||||
Navigator.of(context).pushNamed(Routes.restoreWalletType),
|
||||
image: restoreWalletImage,
|
||||
text: S.of(context).wallet_list_restore_wallet,
|
||||
color: Theme.of(context).accentTextTheme.caption.color,
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
|
@ -23,9 +22,7 @@ class WelcomePage extends BasePage {
|
|||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
final welcomeImage = getIt
|
||||
.get<SettingsStore>()
|
||||
.isDarkTheme
|
||||
final welcomeImage = currentTheme.type == ThemeType.dark
|
||||
? welcomeImageDark : welcomeImageLight;
|
||||
|
||||
final newWalletImage = Image.asset('assets/images/new_wallet.png',
|
||||
|
|
|
@ -204,7 +204,7 @@ class AddressTextField extends StatelessWidget {
|
|||
onURIScanned(uri);
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error $e');
|
||||
print(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ class AlertWithOneAction extends BaseAlertDialog {
|
|||
width: 300,
|
||||
height: 52,
|
||||
padding: EdgeInsets.only(left: 12, right: 12),
|
||||
color: Theme.of(context).accentTextTheme.body2.color,
|
||||
color: Theme.of(context).accentTextTheme.body1.backgroundColor,
|
||||
child: ButtonTheme(
|
||||
minWidth: double.infinity,
|
||||
child: FlatButton(
|
||||
|
@ -44,7 +44,8 @@ class AlertWithOneAction extends BaseAlertDialog {
|
|||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white,
|
||||
color: Theme.of(context).primaryTextTheme.body1
|
||||
.backgroundColor,
|
||||
decoration: TextDecoration.none,
|
||||
),
|
||||
)),
|
||||
|
|
|
@ -61,18 +61,24 @@ class BaseAlertDialog extends StatelessWidget {
|
|||
fontSize: 15,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white,
|
||||
color: Theme.of(context).primaryTextTheme.body2
|
||||
.backgroundColor,
|
||||
decoration: TextDecoration.none,
|
||||
),
|
||||
)),
|
||||
),
|
||||
)
|
||||
),
|
||||
Container(
|
||||
width: 1,
|
||||
height: 52,
|
||||
color: Theme.of(context).dividerColor,
|
||||
),
|
||||
Flexible(
|
||||
child: Container(
|
||||
height: 52,
|
||||
padding: EdgeInsets.only(left: 6, right: 6),
|
||||
color: Theme.of(context).accentTextTheme.body2.color,
|
||||
color: Theme.of(context).accentTextTheme.body1.backgroundColor,
|
||||
child: ButtonTheme(
|
||||
minWidth: double.infinity,
|
||||
child: FlatButton(
|
||||
|
@ -86,7 +92,8 @@ class BaseAlertDialog extends StatelessWidget {
|
|||
fontSize: 15,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white,
|
||||
color: Theme.of(context).primaryTextTheme.body1
|
||||
.backgroundColor,
|
||||
decoration: TextDecoration.none,
|
||||
),
|
||||
)),
|
||||
|
@ -133,6 +140,10 @@ class BaseAlertDialog extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: 1,
|
||||
color: Theme.of(context).dividerColor,
|
||||
),
|
||||
actionButtons(context)
|
||||
],
|
||||
),
|
||||
|
|
|
@ -12,20 +12,21 @@ import 'package:cake_wallet/generated/i18n.dart';
|
|||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class SeedWidget extends StatefulWidget {
|
||||
SeedWidget({Key key, this.language}) : super(key: key);
|
||||
SeedWidget({Key key, this.language, this.type}) : super(key: key);
|
||||
|
||||
final String language;
|
||||
final WalletType type;
|
||||
|
||||
@override
|
||||
SeedWidgetState createState() => SeedWidgetState(language);
|
||||
SeedWidgetState createState() => SeedWidgetState(language, type);
|
||||
}
|
||||
|
||||
class SeedWidgetState extends State<SeedWidget> {
|
||||
SeedWidgetState(String language)
|
||||
SeedWidgetState(String language, this.type)
|
||||
: controller = TextEditingController(),
|
||||
focusNode = FocusNode(),
|
||||
words = SeedValidator.getWordList(
|
||||
type: WalletType.monero, language: language) {
|
||||
type:type, language: language) {
|
||||
focusNode.addListener(() {
|
||||
setState(() {
|
||||
if (!focusNode.hasFocus && controller.text.isEmpty) {
|
||||
|
@ -41,6 +42,7 @@ class SeedWidgetState extends State<SeedWidget> {
|
|||
|
||||
final TextEditingController controller;
|
||||
final FocusNode focusNode;
|
||||
final WalletType type;
|
||||
List<String> words;
|
||||
bool _showPlaceholder;
|
||||
|
||||
|
@ -55,7 +57,7 @@ class SeedWidgetState extends State<SeedWidget> {
|
|||
void changeSeedLanguage(String language) {
|
||||
setState(() {
|
||||
words = SeedValidator.getWordList(
|
||||
type: WalletType.monero, language: language);
|
||||
type: type, language: language);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,10 @@ class TrailButton extends StatelessWidget {
|
|||
child: Text(
|
||||
caption,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).textTheme.subhead.decorationColor,
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.display4
|
||||
.decorationColor,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 14),
|
||||
),
|
||||
|
|
|
@ -26,4 +26,10 @@ abstract class AppStoreBase with Store {
|
|||
SettingsStore settingsStore;
|
||||
|
||||
NodeListStore nodeListStore;
|
||||
|
||||
@action
|
||||
void changeCurrentWallet(WalletBase wallet) {
|
||||
this.wallet?.close();
|
||||
this.wallet = wallet;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import 'package:cake_wallet/entities/crypto_currency.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
part 'fiat_conversion_store.g.dart';
|
||||
|
||||
class FiatConversionStore = FiatConversionStoreBase
|
||||
with _$FiatConversionStore;
|
||||
class FiatConversionStore = FiatConversionStoreBase with _$FiatConversionStore;
|
||||
|
||||
abstract class FiatConversionStoreBase with Store {
|
||||
FiatConversionStoreBase() : price = 0.0;
|
||||
FiatConversionStoreBase() : prices = ObservableMap<CryptoCurrency, double>();
|
||||
|
||||
@observable
|
||||
double price;
|
||||
ObservableMap<CryptoCurrency, double> prices;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/themes.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:cake_wallet/themes/theme_list.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
|
@ -28,7 +29,7 @@ abstract class SettingsStoreBase with Store {
|
|||
@required BalanceDisplayMode initialBalanceDisplayMode,
|
||||
@required bool initialSaveRecipientAddress,
|
||||
@required bool initialAllowBiometricalAuthentication,
|
||||
@required bool initialDarkTheme,
|
||||
@required ThemeBase initialTheme,
|
||||
@required int initialPinLength,
|
||||
@required String initialLanguageCode,
|
||||
// @required String initialCurrentLocale,
|
||||
|
@ -40,10 +41,9 @@ abstract class SettingsStoreBase with Store {
|
|||
balanceDisplayMode = initialBalanceDisplayMode;
|
||||
shouldSaveRecipientAddress = initialSaveRecipientAddress;
|
||||
allowBiometricalAuthentication = initialAllowBiometricalAuthentication;
|
||||
isDarkTheme = initialDarkTheme;
|
||||
currentTheme = initialTheme;
|
||||
pinCodeLength = initialPinLength;
|
||||
languageCode = initialLanguageCode;
|
||||
currentNode = nodes[WalletType.monero];
|
||||
this.nodes = ObservableMap<WalletType, Node>.of(nodes);
|
||||
_sharedPreferences = sharedPreferences;
|
||||
|
||||
|
@ -65,9 +65,9 @@ abstract class SettingsStoreBase with Store {
|
|||
shouldSaveRecipientAddress));
|
||||
|
||||
reaction(
|
||||
(_) => isDarkTheme,
|
||||
(bool isDarkTheme) => sharedPreferences.setBool(
|
||||
PreferencesKey.currentDarkTheme, isDarkTheme));
|
||||
(_) => currentTheme,
|
||||
(ThemeBase theme) => sharedPreferences.setInt(
|
||||
PreferencesKey.currentTheme, theme.raw));
|
||||
|
||||
reaction(
|
||||
(_) => allowBiometricalAuthentication,
|
||||
|
@ -80,13 +80,14 @@ abstract class SettingsStoreBase with Store {
|
|||
(int pinLength) => sharedPreferences.setInt(
|
||||
PreferencesKey.currentPinLength, pinLength));
|
||||
|
||||
reaction((_) => currentNode,
|
||||
(Node node) => _saveCurrentNode(node, WalletType.monero));
|
||||
|
||||
reaction(
|
||||
(_) => languageCode,
|
||||
(String languageCode) => sharedPreferences.setString(
|
||||
PreferencesKey.currentLanguageCode, languageCode));
|
||||
|
||||
this
|
||||
.nodes
|
||||
.observe((change) => _saveCurrentNode(change.newValue, change.key));
|
||||
}
|
||||
|
||||
static const defaultPinLength = 4;
|
||||
|
@ -111,16 +112,13 @@ abstract class SettingsStoreBase with Store {
|
|||
bool allowBiometricalAuthentication;
|
||||
|
||||
@observable
|
||||
bool isDarkTheme;
|
||||
ThemeBase currentTheme;
|
||||
|
||||
@observable
|
||||
int pinCodeLength;
|
||||
|
||||
@observable
|
||||
Node currentNode;
|
||||
|
||||
@computed
|
||||
ThemeData get theme => isDarkTheme ? Themes.darkTheme : Themes.lightTheme;
|
||||
ThemeData get theme => currentTheme.themeData;
|
||||
|
||||
@observable
|
||||
String languageCode;
|
||||
|
@ -154,8 +152,8 @@ abstract class SettingsStoreBase with Store {
|
|||
final allowBiometricalAuthentication = sharedPreferences
|
||||
.getBool(PreferencesKey.allowBiometricalAuthenticationKey) ??
|
||||
false;
|
||||
final savedDarkTheme =
|
||||
sharedPreferences.getBool(PreferencesKey.currentDarkTheme) ?? false;
|
||||
final savedTheme = ThemeList.deserialize(
|
||||
raw: sharedPreferences.getInt(PreferencesKey.currentTheme) ?? 0);
|
||||
final actionListDisplayMode = ObservableList<ActionListDisplayMode>();
|
||||
actionListDisplayMode.addAll(deserializeActionlistDisplayModes(
|
||||
sharedPreferences.getInt(PreferencesKey.displayActionListModeKey) ??
|
||||
|
@ -188,7 +186,7 @@ abstract class SettingsStoreBase with Store {
|
|||
initialBalanceDisplayMode: currentBalanceDisplayMode,
|
||||
initialSaveRecipientAddress: shouldSaveRecipientAddress,
|
||||
initialAllowBiometricalAuthentication: allowBiometricalAuthentication,
|
||||
initialDarkTheme: savedDarkTheme,
|
||||
initialTheme: savedTheme,
|
||||
actionlistDisplayMode: actionListDisplayMode,
|
||||
initialPinLength: pinLength,
|
||||
initialLanguageCode: savedLanguageCode);
|
||||
|
|
353
lib/themes.dart
|
@ -1,353 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'palette.dart';
|
||||
|
||||
class Themes {
|
||||
|
||||
static final ThemeData lightTheme = ThemeData(
|
||||
fontFamily: 'Lato',
|
||||
brightness: Brightness.light,
|
||||
backgroundColor: Colors.white,
|
||||
accentColor: Palette.blueCraiola, // first gradient color
|
||||
scaffoldBackgroundColor: Palette.pinkFlamingo, // second gradient color
|
||||
primaryColor: Palette.redHat, // third gradient color
|
||||
buttonColor: Colors.white.withOpacity(0.2), // action buttons on dashboard page
|
||||
indicatorColor: Colors.white.withOpacity(0.5), // page indicator
|
||||
hoverColor: Colors.white, // amount hint text (receive page)
|
||||
dividerColor: Palette.paleBlue,
|
||||
hintColor: Palette.gray,
|
||||
textTheme: TextTheme(
|
||||
title: TextStyle(
|
||||
color: Colors.white, // sync_indicator text
|
||||
backgroundColor: Colors.white.withOpacity(0.2), // synced sync_indicator
|
||||
decorationColor: Colors.white.withOpacity(0.15), // not synced sync_indicator
|
||||
),
|
||||
caption: TextStyle(
|
||||
color: Palette.shineOrange, // not synced light
|
||||
decorationColor: Colors.white, // filter icon
|
||||
),
|
||||
overline: TextStyle(
|
||||
color: Colors.white.withOpacity(0.2), // filter button
|
||||
backgroundColor: Colors.white.withOpacity(0.5), // date section row
|
||||
decorationColor: Colors.white.withOpacity(0.2) // icons (transaction and trade rows)
|
||||
),
|
||||
subhead: TextStyle(
|
||||
color: Colors.white.withOpacity(0.2), // address button border
|
||||
decorationColor: Colors.white.withOpacity(0.4), // copy button (qr widget)
|
||||
),
|
||||
headline: TextStyle(
|
||||
color: Colors.white, // qr code
|
||||
decorationColor: Colors.white.withOpacity(0.5), // bottom border of amount (receive page)
|
||||
),
|
||||
display1: TextStyle(
|
||||
color: PaletteDark.lightBlueGrey, // icons color (receive page)
|
||||
decorationColor: Palette.lavender, // icons background (receive page)
|
||||
),
|
||||
display2: TextStyle(
|
||||
color: Palette.darkBlueCraiola, // text color of tiles (receive page)
|
||||
decorationColor: Colors.white // background of tiles (receive page)
|
||||
),
|
||||
display3: TextStyle(
|
||||
color: Colors.white, // text color of current tile (receive page),
|
||||
//decorationColor: Palette.blueCraiola // background of current tile (receive page)
|
||||
decorationColor: Palette.moderateSlateBlue // background of current tile (receive page)
|
||||
),
|
||||
display4: TextStyle(
|
||||
color: Palette.violetBlue, // text color of tiles (account list)
|
||||
decorationColor: Colors.white // background of tiles (account list)
|
||||
),
|
||||
subtitle: TextStyle(
|
||||
color: Palette.moderateSlateBlue, // text color of current tile (account list)
|
||||
decorationColor: Colors.white // background of current tile (account list)
|
||||
),
|
||||
body1: TextStyle(
|
||||
color: Palette.moderatePurpleBlue, // scrollbar thumb
|
||||
decorationColor: Palette.periwinkleCraiola // scrollbar background
|
||||
),
|
||||
body2: TextStyle(
|
||||
color: Palette.moderateLavender, // menu header
|
||||
decorationColor: Colors.white, // menu background
|
||||
)
|
||||
),
|
||||
primaryTextTheme: TextTheme(
|
||||
title: TextStyle(
|
||||
color: Palette.darkBlueCraiola, // title color
|
||||
backgroundColor: Palette.wildPeriwinkle // textfield underline
|
||||
),
|
||||
caption: TextStyle(
|
||||
color: PaletteDark.pigeonBlue, // secondary text
|
||||
decorationColor: Palette.wildLavender // menu divider
|
||||
),
|
||||
overline: TextStyle(
|
||||
color: Palette.darkGray, // transaction/trade details titles
|
||||
decorationColor: Colors.white.withOpacity(0.5), // placeholder
|
||||
),
|
||||
subhead: TextStyle(
|
||||
color: Palette.blueCraiola, // first gradient color (send page)
|
||||
decorationColor: Palette.pinkFlamingo // second gradient color (send page)
|
||||
),
|
||||
headline: TextStyle(
|
||||
color: Colors.white.withOpacity(0.5), // text field border color (send page)
|
||||
decorationColor: Colors.white.withOpacity(0.5), // text field hint color (send page)
|
||||
),
|
||||
display1: TextStyle(
|
||||
color: Colors.white.withOpacity(0.2), // text field button color (send page)
|
||||
decorationColor: Colors.white // text field button icon color (send page)
|
||||
),
|
||||
display2: TextStyle(
|
||||
color: Colors.white.withOpacity(0.5), // estimated fee (send page)
|
||||
decorationColor: Palette.shadowWhite // template dotted border (send page)
|
||||
),
|
||||
display3: TextStyle(
|
||||
color: Palette.darkBlueCraiola, // template new text (send page)
|
||||
decorationColor: Palette.shadowWhite // template background color (send page)
|
||||
),
|
||||
display4: TextStyle(
|
||||
color: Palette.darkBlueCraiola, // template title (send page)
|
||||
decorationColor: Palette.niagara // receive amount text (exchange page)
|
||||
),
|
||||
subtitle: TextStyle(
|
||||
color: Palette.blueCraiola, // first gradient color top panel (exchange page)
|
||||
decorationColor: Palette.pinkFlamingo // second gradient color top panel (exchange page)
|
||||
),
|
||||
body1: TextStyle(
|
||||
color: Palette.blueCraiola.withOpacity(0.7), // first gradient color bottom panel (exchange page)
|
||||
decorationColor: Palette.pinkFlamingo.withOpacity(0.7) // second gradient color bottom panel (exchange page)
|
||||
),
|
||||
body2: TextStyle(
|
||||
color: Colors.white.withOpacity(0.5), // text field border on top panel (exchange page)
|
||||
decorationColor: Colors.white.withOpacity(0.5), // text field border on bottom panel (exchange page)
|
||||
)
|
||||
),
|
||||
focusColor: Colors.white.withOpacity(0.2), // text field button (exchange page)
|
||||
accentTextTheme: TextTheme(
|
||||
title: TextStyle(
|
||||
color: Colors.white, // picker background
|
||||
backgroundColor: Palette.periwinkleCraiola, // picker divider
|
||||
decorationColor: Colors.white // dialog background
|
||||
),
|
||||
caption: TextStyle(
|
||||
color: Palette.moderateLavender, // container (confirm exchange)
|
||||
backgroundColor: Palette.moderateLavender, // button background (confirm exchange)
|
||||
decorationColor: Palette.darkBlueCraiola, // text color (information page)
|
||||
),
|
||||
subtitle: TextStyle(
|
||||
color: Palette.darkBlueCraiola, // QR code (exchange trade page)
|
||||
backgroundColor: Palette.wildPeriwinkle, // divider (exchange trade page)
|
||||
//decorationColor: Palette.blueCraiola // crete new wallet button background (wallet list page)
|
||||
decorationColor: Palette.moderateSlateBlue // crete new wallet button background (wallet list page)
|
||||
),
|
||||
headline: TextStyle(
|
||||
color: Palette.moderateLavender, // first gradient color of wallet action buttons (wallet list page)
|
||||
backgroundColor: Palette.moderateLavender, // second gradient color of wallet action buttons (wallet list page)
|
||||
decorationColor: Colors.white // restore wallet button text color (wallet list page)
|
||||
),
|
||||
subhead: TextStyle(
|
||||
color: Palette.darkGray, // titles color (filter widget)
|
||||
backgroundColor: Palette.periwinkle, // divider color (filter widget)
|
||||
decorationColor: Colors.white // checkbox background (filter widget)
|
||||
),
|
||||
overline: TextStyle(
|
||||
color: Palette.wildPeriwinkle, // checkbox bounds (filter widget)
|
||||
decorationColor: Colors.white, // menu subname
|
||||
),
|
||||
display1: TextStyle(
|
||||
color: Palette.blueCraiola, // first gradient color (menu header)
|
||||
decorationColor: Palette.pinkFlamingo // second gradient color(menu header)
|
||||
),
|
||||
display2: TextStyle(
|
||||
color: Palette.shadowWhite, // action button color (address text field)
|
||||
decorationColor: Palette.darkGray // hint text (seed widget)
|
||||
),
|
||||
display3: TextStyle(
|
||||
color: Palette.darkGray, // hint text (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)
|
||||
),
|
||||
body2: TextStyle(
|
||||
color: Palette.moderateSlateBlue, // primary buttons, alert right buttons
|
||||
decorationColor: Palette.brightOrange // alert left button
|
||||
),
|
||||
),
|
||||
cardColor: Palette.moderateSlateBlue // bottom button (action list)
|
||||
);
|
||||
|
||||
|
||||
static final ThemeData darkTheme = ThemeData(
|
||||
fontFamily: 'Lato',
|
||||
brightness: Brightness.dark,
|
||||
backgroundColor: PaletteDark.backgroundColor,
|
||||
accentColor: PaletteDark.backgroundColor, // first gradient color
|
||||
scaffoldBackgroundColor: PaletteDark.backgroundColor, // second gradient color
|
||||
primaryColor: PaletteDark.backgroundColor, // third gradient color
|
||||
buttonColor: PaletteDark.nightBlue, // action buttons on dashboard page
|
||||
indicatorColor: PaletteDark.cyanBlue, // page indicator
|
||||
hoverColor: PaletteDark.cyanBlue, // amount hint text (receive page)
|
||||
dividerColor: PaletteDark.dividerColor,
|
||||
hintColor: PaletteDark.pigeonBlue, // menu
|
||||
textTheme: TextTheme(
|
||||
title: TextStyle(
|
||||
color: PaletteDark.wildBlue, // sync_indicator text
|
||||
backgroundColor: PaletteDark.lightNightBlue, // synced sync_indicator
|
||||
decorationColor: PaletteDark.oceanBlue // not synced sync_indicator
|
||||
),
|
||||
caption: TextStyle(
|
||||
color: PaletteDark.orangeYellow, // not synced light
|
||||
decorationColor: PaletteDark.wildBlue, // filter icon
|
||||
),
|
||||
overline: TextStyle(
|
||||
color: PaletteDark.oceanBlue, // filter button
|
||||
backgroundColor: PaletteDark.darkCyanBlue, // date section row
|
||||
decorationColor: PaletteDark.wildNightBlue // icons (transaction and trade rows)
|
||||
),
|
||||
subhead: TextStyle(
|
||||
color: PaletteDark.nightBlue, // address button border
|
||||
decorationColor: PaletteDark.lightBlueGrey, // copy button (qr widget)
|
||||
),
|
||||
headline: TextStyle(
|
||||
color: PaletteDark.lightBlueGrey, // qr code
|
||||
decorationColor: PaletteDark.darkGrey, // bottom border of amount (receive page)
|
||||
),
|
||||
display1: TextStyle(
|
||||
color: Colors.white, // icons color (receive page)
|
||||
decorationColor: PaletteDark.distantNightBlue, // icons background (receive page)
|
||||
),
|
||||
display2: TextStyle(
|
||||
color: Colors.white, // text color of tiles (receive page)
|
||||
decorationColor: PaletteDark.nightBlue // background of tiles (receive page)
|
||||
),
|
||||
display3: TextStyle(
|
||||
color: Palette.blueCraiola, // text color of current tile (receive page)
|
||||
decorationColor: PaletteDark.lightOceanBlue // background of current tile (receive page)
|
||||
),
|
||||
display4: TextStyle(
|
||||
color: Colors.white, // text color of tiles (account list)
|
||||
decorationColor: PaletteDark.darkOceanBlue // background of tiles (account list)
|
||||
),
|
||||
subtitle: TextStyle(
|
||||
color: Palette.blueCraiola, // text color of current tile (account list)
|
||||
decorationColor: PaletteDark.darkNightBlue // background of current tile (account list)
|
||||
),
|
||||
body1: TextStyle(
|
||||
color: PaletteDark.wildBlueGrey, // scrollbar thumb
|
||||
decorationColor: PaletteDark.violetBlue // scrollbar background
|
||||
),
|
||||
body2: TextStyle(
|
||||
color: PaletteDark.deepPurpleBlue, // menu header
|
||||
decorationColor: PaletteDark.deepPurpleBlue, // menu background
|
||||
)
|
||||
),
|
||||
primaryTextTheme: TextTheme(
|
||||
title: TextStyle(
|
||||
color: Colors.white, // title color
|
||||
backgroundColor: PaletteDark.darkOceanBlue // textfield underline
|
||||
),
|
||||
caption: TextStyle(
|
||||
color: PaletteDark.darkCyanBlue, // secondary text
|
||||
decorationColor: PaletteDark.darkOceanBlue // menu divider
|
||||
),
|
||||
overline: TextStyle(
|
||||
color: PaletteDark.lightBlueGrey, // transaction/trade details titles
|
||||
decorationColor: Colors.grey, // placeholder
|
||||
),
|
||||
subhead: TextStyle(
|
||||
color: PaletteDark.darkNightBlue, // first gradient color (send page)
|
||||
decorationColor: PaletteDark.darkNightBlue // second gradient color (send page)
|
||||
),
|
||||
headline: TextStyle(
|
||||
color: PaletteDark.lightVioletBlue, // text field border color (send page)
|
||||
decorationColor: PaletteDark.darkCyanBlue, // text field hint color (send page)
|
||||
),
|
||||
display1: TextStyle(
|
||||
color: PaletteDark.buttonNightBlue, // text field button color (send page)
|
||||
decorationColor: PaletteDark.gray // text field button icon color (send page)
|
||||
),
|
||||
display2: TextStyle(
|
||||
color: Colors.white, // estimated fee (send page)
|
||||
decorationColor: PaletteDark.darkCyanBlue // template dotted border (send page)
|
||||
),
|
||||
display3: TextStyle(
|
||||
color: PaletteDark.darkCyanBlue, // template new text (send page)
|
||||
decorationColor: PaletteDark.darkVioletBlue // template background color (send page)
|
||||
),
|
||||
display4: TextStyle(
|
||||
color: PaletteDark.cyanBlue, // template title (send page)
|
||||
decorationColor: PaletteDark.darkCyanBlue // receive amount text (exchange page)
|
||||
),
|
||||
subtitle: TextStyle(
|
||||
color: PaletteDark.wildVioletBlue, // first gradient color top panel (exchange page)
|
||||
decorationColor: PaletteDark.wildVioletBlue // second gradient color top panel (exchange page)
|
||||
),
|
||||
body1: TextStyle(
|
||||
color: PaletteDark.darkNightBlue, // first gradient color bottom panel (exchange page)
|
||||
decorationColor: PaletteDark.darkNightBlue // second gradient color bottom panel (exchange page)
|
||||
),
|
||||
body2: TextStyle(
|
||||
color: PaletteDark.blueGrey, // text field border on top panel (exchange page)
|
||||
decorationColor: PaletteDark.moderateVioletBlue, // text field border on bottom panel (exchange page)
|
||||
)
|
||||
),
|
||||
focusColor: PaletteDark.moderateBlue, // text field button (exchange page)
|
||||
accentTextTheme: TextTheme(
|
||||
title: TextStyle(
|
||||
color: PaletteDark.nightBlue, // picker background
|
||||
backgroundColor: PaletteDark.dividerColor, // picker divider
|
||||
decorationColor: PaletteDark.darkNightBlue // dialog background
|
||||
),
|
||||
caption: TextStyle(
|
||||
color: PaletteDark.nightBlue, // container (confirm exchange)
|
||||
backgroundColor: PaletteDark.deepVioletBlue, // button background (confirm exchange)
|
||||
decorationColor: Palette.darkLavender, // text color (information page)
|
||||
),
|
||||
subtitle: TextStyle(
|
||||
//color: PaletteDark.lightBlueGrey, // QR code (exchange trade page)
|
||||
color: Colors.white, // QR code (exchange trade page)
|
||||
backgroundColor: PaletteDark.deepVioletBlue, // divider (exchange trade page)
|
||||
decorationColor: Colors.white // crete new wallet button background (wallet list page)
|
||||
),
|
||||
headline: TextStyle(
|
||||
color: PaletteDark.distantBlue, // first gradient color of wallet action buttons (wallet list page)
|
||||
backgroundColor: PaletteDark.distantNightBlue, // second gradient color of wallet action buttons (wallet list page)
|
||||
decorationColor: Palette.darkBlueCraiola // restore wallet button text color (wallet list page)
|
||||
),
|
||||
subhead: TextStyle(
|
||||
color: Colors.white, // titles color (filter widget)
|
||||
backgroundColor: PaletteDark.darkOceanBlue, // divider color (filter widget)
|
||||
decorationColor: PaletteDark.wildVioletBlue.withOpacity(0.3) // checkbox background (filter widget)
|
||||
),
|
||||
overline: TextStyle(
|
||||
color: PaletteDark.wildVioletBlue, // checkbox bounds (filter widget)
|
||||
decorationColor: PaletteDark.darkCyanBlue, // menu subname
|
||||
),
|
||||
display1: TextStyle(
|
||||
color: PaletteDark.deepPurpleBlue, // first gradient color (menu header)
|
||||
decorationColor: PaletteDark.deepPurpleBlue // second gradient color(menu header)
|
||||
),
|
||||
display2: TextStyle(
|
||||
color: PaletteDark.nightBlue, // action button color (address text field)
|
||||
decorationColor: PaletteDark.darkCyanBlue // hint text (seed widget)
|
||||
),
|
||||
display3: TextStyle(
|
||||
color: PaletteDark.cyanBlue, // hint text (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)
|
||||
),
|
||||
body2: TextStyle(
|
||||
color: Palette.blueCraiola, // primary buttons, alert right buttons
|
||||
decorationColor: Palette.alizarinRed // alert left button
|
||||
),
|
||||
),
|
||||
cardColor: PaletteDark.darkNightBlue // bottom button (action list)
|
||||
);
|
||||
}
|
197
lib/themes/bright_theme.dart
Normal file
|
@ -0,0 +1,197 @@
|
|||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class BrightTheme extends ThemeBase {
|
||||
BrightTheme({@required int raw}) : super(raw: raw);
|
||||
|
||||
@override
|
||||
String get title => S.current.bright_theme;
|
||||
|
||||
@override
|
||||
ThemeType get type => ThemeType.bright;
|
||||
|
||||
@override
|
||||
ThemeData get themeData => ThemeData(
|
||||
fontFamily: 'Lato',
|
||||
brightness: Brightness.light,
|
||||
backgroundColor: Colors.white,
|
||||
accentColor: Palette.blueCraiola, // first gradient color
|
||||
scaffoldBackgroundColor: Palette.pinkFlamingo, // second gradient color
|
||||
primaryColor: Palette.redHat, // third gradient color
|
||||
buttonColor: Colors.white.withOpacity(0.2), // action buttons on dashboard page
|
||||
indicatorColor: Colors.white.withOpacity(0.5), // page indicator
|
||||
hoverColor: Colors.white, // amount hint text (receive page)
|
||||
dividerColor: Palette.paleBlue,
|
||||
hintColor: Palette.gray,
|
||||
textTheme: TextTheme(
|
||||
title: TextStyle(
|
||||
color: Colors.white, // sync_indicator text
|
||||
backgroundColor: Colors.white.withOpacity(0.2), // synced sync_indicator
|
||||
decorationColor: Colors.white.withOpacity(0.15), // not synced sync_indicator
|
||||
),
|
||||
caption: TextStyle(
|
||||
color: Palette.shineOrange, // not synced light
|
||||
decorationColor: Colors.white, // filter icon
|
||||
),
|
||||
overline: TextStyle(
|
||||
color: Colors.white.withOpacity(0.2), // filter button
|
||||
backgroundColor: Colors.white.withOpacity(0.5), // date section row
|
||||
decorationColor: Colors.white.withOpacity(0.2) // icons (transaction and trade rows)
|
||||
),
|
||||
subhead: TextStyle(
|
||||
color: Colors.white.withOpacity(0.2), // address button border
|
||||
decorationColor: Colors.white.withOpacity(0.4), // copy button (qr widget)
|
||||
),
|
||||
headline: TextStyle(
|
||||
color: Colors.white, // qr code
|
||||
decorationColor: Colors.white.withOpacity(0.5), // bottom border of amount (receive page)
|
||||
),
|
||||
display1: TextStyle(
|
||||
color: PaletteDark.lightBlueGrey, // icons color (receive page)
|
||||
decorationColor: Palette.lavender, // icons background (receive page)
|
||||
),
|
||||
display2: TextStyle(
|
||||
color: Palette.darkBlueCraiola, // text color of tiles (receive page)
|
||||
decorationColor: Colors.white // background of tiles (receive page)
|
||||
),
|
||||
display3: TextStyle(
|
||||
color: Colors.white, // text color of current tile (receive page),
|
||||
//decorationColor: Palette.blueCraiola // background of current tile (receive page)
|
||||
decorationColor: Palette.moderateSlateBlue // background of current tile (receive page)
|
||||
),
|
||||
display4: TextStyle(
|
||||
color: Palette.violetBlue, // text color of tiles (account list)
|
||||
decorationColor: Colors.white // background of tiles (account list)
|
||||
),
|
||||
subtitle: TextStyle(
|
||||
color: Palette.moderateSlateBlue, // text color of current tile (account list)
|
||||
decorationColor: Colors.white // background of current tile (account list)
|
||||
),
|
||||
body1: TextStyle(
|
||||
color: Palette.moderatePurpleBlue, // scrollbar thumb
|
||||
decorationColor: Palette.periwinkleCraiola // scrollbar background
|
||||
),
|
||||
body2: TextStyle(
|
||||
color: Palette.moderateLavender, // menu header
|
||||
decorationColor: Colors.white, // menu background
|
||||
)
|
||||
),
|
||||
primaryTextTheme: TextTheme(
|
||||
title: TextStyle(
|
||||
color: Palette.darkBlueCraiola, // title color
|
||||
backgroundColor: Palette.wildPeriwinkle // textfield underline
|
||||
),
|
||||
caption: TextStyle(
|
||||
color: PaletteDark.pigeonBlue, // secondary text
|
||||
decorationColor: Palette.wildLavender // menu divider
|
||||
),
|
||||
overline: TextStyle(
|
||||
color: Palette.darkGray, // transaction/trade details titles
|
||||
decorationColor: Colors.white.withOpacity(0.5), // placeholder
|
||||
),
|
||||
subhead: TextStyle(
|
||||
color: Palette.blueCraiola, // first gradient color (send page)
|
||||
decorationColor: Palette.pinkFlamingo // second gradient color (send page)
|
||||
),
|
||||
headline: TextStyle(
|
||||
color: Colors.white.withOpacity(0.5), // text field border color (send page)
|
||||
decorationColor: Colors.white.withOpacity(0.5), // text field hint color (send page)
|
||||
),
|
||||
display1: TextStyle(
|
||||
color: Colors.white.withOpacity(0.2), // text field button color (send page)
|
||||
decorationColor: Colors.white // text field button icon color (send page)
|
||||
),
|
||||
display2: TextStyle(
|
||||
color: Colors.white.withOpacity(0.5), // estimated fee (send page)
|
||||
decorationColor: Palette.shadowWhite // template dotted border (send page)
|
||||
),
|
||||
display3: TextStyle(
|
||||
color: Palette.darkBlueCraiola, // template new text (send page)
|
||||
decorationColor: Palette.shadowWhite // template background color (send page)
|
||||
),
|
||||
display4: TextStyle(
|
||||
color: Palette.darkBlueCraiola, // template title (send page)
|
||||
decorationColor: Palette.niagara // receive amount text (exchange page)
|
||||
),
|
||||
subtitle: TextStyle(
|
||||
color: Palette.blueCraiola, // first gradient color top panel (exchange page)
|
||||
decorationColor: Palette.pinkFlamingo // second gradient color top panel (exchange page)
|
||||
),
|
||||
body1: TextStyle(
|
||||
color: Palette.blueCraiola.withOpacity(0.7), // first gradient color bottom panel (exchange page)
|
||||
decorationColor: Palette.pinkFlamingo.withOpacity(0.7), // second gradient color bottom panel (exchange page)
|
||||
backgroundColor: Palette.moderateSlateBlue // alert right button text
|
||||
),
|
||||
body2: TextStyle(
|
||||
color: Colors.white.withOpacity(0.5), // text field border on top panel (exchange page)
|
||||
decorationColor: Colors.white.withOpacity(0.5), // text field border on bottom panel (exchange page)
|
||||
backgroundColor: Palette.brightOrange // alert left button text
|
||||
)
|
||||
),
|
||||
focusColor: Colors.white.withOpacity(0.2), // text field button (exchange page)
|
||||
accentTextTheme: TextTheme(
|
||||
title: TextStyle(
|
||||
color: Colors.white, // picker background
|
||||
backgroundColor: Palette.periwinkleCraiola, // picker divider
|
||||
decorationColor: Colors.white // dialog background
|
||||
),
|
||||
caption: TextStyle(
|
||||
color: Palette.moderateLavender, // container (confirm exchange)
|
||||
backgroundColor: Palette.moderateLavender, // button background (confirm exchange)
|
||||
decorationColor: Palette.darkBlueCraiola, // text color (information page)
|
||||
),
|
||||
subtitle: TextStyle(
|
||||
color: Palette.darkBlueCraiola, // QR code (exchange trade page)
|
||||
backgroundColor: Palette.wildPeriwinkle, // divider (exchange trade page)
|
||||
//decorationColor: Palette.blueCraiola // crete new wallet button background (wallet list page)
|
||||
decorationColor: Palette.moderateSlateBlue // crete new wallet button background (wallet list page)
|
||||
),
|
||||
headline: TextStyle(
|
||||
color: Palette.moderateLavender, // first gradient color of wallet action buttons (wallet list page)
|
||||
backgroundColor: Palette.moderateLavender, // second gradient color of wallet action buttons (wallet list page)
|
||||
decorationColor: Colors.white // restore wallet button text color (wallet list page)
|
||||
),
|
||||
subhead: TextStyle(
|
||||
color: Palette.darkGray, // titles color (filter widget)
|
||||
backgroundColor: Palette.periwinkle, // divider color (filter widget)
|
||||
decorationColor: Colors.white // checkbox background (filter widget)
|
||||
),
|
||||
overline: TextStyle(
|
||||
color: Palette.wildPeriwinkle, // checkbox bounds (filter widget)
|
||||
decorationColor: Colors.white, // menu subname
|
||||
),
|
||||
display1: TextStyle(
|
||||
color: Palette.blueCraiola, // first gradient color (menu header)
|
||||
decorationColor: Palette.pinkFlamingo, // second gradient color(menu header)
|
||||
backgroundColor: Colors.white // active dot color
|
||||
),
|
||||
display2: TextStyle(
|
||||
color: Palette.shadowWhite, // action button color (address text field)
|
||||
decorationColor: Palette.darkGray, // hint text (seed widget)
|
||||
backgroundColor: Colors.white.withOpacity(0.5) // text on balance page
|
||||
),
|
||||
display3: TextStyle(
|
||||
color: Palette.darkGray, // hint text (new wallet page)
|
||||
decorationColor: Palette.periwinkleCraiola, // underline (new wallet page)
|
||||
backgroundColor: Colors.white // menu, icons, balance (dashboard page)
|
||||
),
|
||||
display4: TextStyle(
|
||||
color: Palette.darkGray, // switch background (settings page)
|
||||
decorationColor: Colors.white.withOpacity(0.4) // hint text (exchange page)
|
||||
),
|
||||
body1: TextStyle(
|
||||
color: Palette.darkGray, // indicators (PIN code)
|
||||
decorationColor: Palette.darkGray, // switch (PIN code)
|
||||
backgroundColor: Colors.white // alert right button
|
||||
),
|
||||
body2: TextStyle(
|
||||
color: Palette.moderateSlateBlue, // primary buttons
|
||||
decorationColor: Colors.white, // alert left button,
|
||||
backgroundColor: Palette.dullGray // keyboard bar color
|
||||
),
|
||||
),
|
||||
cardColor: Palette.moderateSlateBlue // bottom button (action list)
|
||||
);
|
||||
}
|
196
lib/themes/dark_theme.dart
Normal file
|
@ -0,0 +1,196 @@
|
|||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DarkTheme extends ThemeBase {
|
||||
DarkTheme({@required int raw}) : super(raw: raw);
|
||||
|
||||
@override
|
||||
String get title => S.current.dark_theme;
|
||||
|
||||
@override
|
||||
ThemeType get type => ThemeType.dark;
|
||||
|
||||
@override
|
||||
ThemeData get themeData => ThemeData(
|
||||
fontFamily: 'Lato',
|
||||
brightness: Brightness.dark,
|
||||
backgroundColor: PaletteDark.backgroundColor,
|
||||
accentColor: PaletteDark.backgroundColor, // first gradient color
|
||||
scaffoldBackgroundColor: PaletteDark.backgroundColor, // second gradient color
|
||||
primaryColor: PaletteDark.backgroundColor, // third gradient color
|
||||
buttonColor: PaletteDark.nightBlue, // action buttons on dashboard page
|
||||
indicatorColor: PaletteDark.cyanBlue, // page indicator
|
||||
hoverColor: PaletteDark.cyanBlue, // amount hint text (receive page)
|
||||
dividerColor: PaletteDark.dividerColor,
|
||||
hintColor: PaletteDark.pigeonBlue, // menu
|
||||
textTheme: TextTheme(
|
||||
title: TextStyle(
|
||||
color: PaletteDark.wildBlue, // sync_indicator text
|
||||
backgroundColor: PaletteDark.lightNightBlue, // synced sync_indicator
|
||||
decorationColor: PaletteDark.oceanBlue // not synced sync_indicator
|
||||
),
|
||||
caption: TextStyle(
|
||||
color: PaletteDark.orangeYellow, // not synced light
|
||||
decorationColor: PaletteDark.wildBlue, // filter icon
|
||||
),
|
||||
overline: TextStyle(
|
||||
color: PaletteDark.oceanBlue, // filter button
|
||||
backgroundColor: PaletteDark.darkCyanBlue, // date section row
|
||||
decorationColor: PaletteDark.wildNightBlue // icons (transaction and trade rows)
|
||||
),
|
||||
subhead: TextStyle(
|
||||
color: PaletteDark.nightBlue, // address button border
|
||||
decorationColor: PaletteDark.lightBlueGrey, // copy button (qr widget)
|
||||
),
|
||||
headline: TextStyle(
|
||||
color: PaletteDark.lightBlueGrey, // qr code
|
||||
decorationColor: PaletteDark.darkGrey, // bottom border of amount (receive page)
|
||||
),
|
||||
display1: TextStyle(
|
||||
color: Colors.white, // icons color (receive page)
|
||||
decorationColor: PaletteDark.distantNightBlue, // icons background (receive page)
|
||||
),
|
||||
display2: TextStyle(
|
||||
color: Colors.white, // text color of tiles (receive page)
|
||||
decorationColor: PaletteDark.nightBlue // background of tiles (receive page)
|
||||
),
|
||||
display3: TextStyle(
|
||||
color: Palette.blueCraiola, // text color of current tile (receive page)
|
||||
decorationColor: PaletteDark.lightOceanBlue // background of current tile (receive page)
|
||||
),
|
||||
display4: TextStyle(
|
||||
color: Colors.white, // text color of tiles (account list)
|
||||
decorationColor: PaletteDark.darkOceanBlue // background of tiles (account list)
|
||||
),
|
||||
subtitle: TextStyle(
|
||||
color: Palette.blueCraiola, // text color of current tile (account list)
|
||||
decorationColor: PaletteDark.darkNightBlue // background of current tile (account list)
|
||||
),
|
||||
body1: TextStyle(
|
||||
color: PaletteDark.wildBlueGrey, // scrollbar thumb
|
||||
decorationColor: PaletteDark.violetBlue // scrollbar background
|
||||
),
|
||||
body2: TextStyle(
|
||||
color: PaletteDark.deepPurpleBlue, // menu header
|
||||
decorationColor: PaletteDark.deepPurpleBlue, // menu background
|
||||
)
|
||||
),
|
||||
primaryTextTheme: TextTheme(
|
||||
title: TextStyle(
|
||||
color: Colors.white, // title color
|
||||
backgroundColor: PaletteDark.darkOceanBlue // textfield underline
|
||||
),
|
||||
caption: TextStyle(
|
||||
color: PaletteDark.darkCyanBlue, // secondary text
|
||||
decorationColor: PaletteDark.darkOceanBlue // menu divider
|
||||
),
|
||||
overline: TextStyle(
|
||||
color: PaletteDark.lightBlueGrey, // transaction/trade details titles
|
||||
decorationColor: Colors.grey, // placeholder
|
||||
),
|
||||
subhead: TextStyle(
|
||||
color: PaletteDark.darkNightBlue, // first gradient color (send page)
|
||||
decorationColor: PaletteDark.darkNightBlue // second gradient color (send page)
|
||||
),
|
||||
headline: TextStyle(
|
||||
color: PaletteDark.lightVioletBlue, // text field border color (send page)
|
||||
decorationColor: PaletteDark.darkCyanBlue, // text field hint color (send page)
|
||||
),
|
||||
display1: TextStyle(
|
||||
color: PaletteDark.buttonNightBlue, // text field button color (send page)
|
||||
decorationColor: PaletteDark.gray // text field button icon color (send page)
|
||||
),
|
||||
display2: TextStyle(
|
||||
color: Colors.white, // estimated fee (send page)
|
||||
decorationColor: PaletteDark.darkCyanBlue // template dotted border (send page)
|
||||
),
|
||||
display3: TextStyle(
|
||||
color: PaletteDark.darkCyanBlue, // template new text (send page)
|
||||
decorationColor: PaletteDark.darkVioletBlue // template background color (send page)
|
||||
),
|
||||
display4: TextStyle(
|
||||
color: PaletteDark.cyanBlue, // template title (send page)
|
||||
decorationColor: PaletteDark.darkCyanBlue // receive amount text (exchange page)
|
||||
),
|
||||
subtitle: TextStyle(
|
||||
color: PaletteDark.wildVioletBlue, // first gradient color top panel (exchange page)
|
||||
decorationColor: PaletteDark.wildVioletBlue // second gradient color top panel (exchange page)
|
||||
),
|
||||
body1: TextStyle(
|
||||
color: PaletteDark.darkNightBlue, // first gradient color bottom panel (exchange page)
|
||||
decorationColor: PaletteDark.darkNightBlue, // second gradient color bottom panel (exchange page)
|
||||
backgroundColor: Palette.blueCraiola // alert right button text
|
||||
),
|
||||
body2: TextStyle(
|
||||
color: PaletteDark.blueGrey, // text field border on top panel (exchange page)
|
||||
decorationColor: PaletteDark.moderateVioletBlue, // text field border on bottom panel (exchange page)
|
||||
backgroundColor: Palette.alizarinRed // alert left button text
|
||||
)
|
||||
),
|
||||
focusColor: PaletteDark.moderateBlue, // text field button (exchange page)
|
||||
accentTextTheme: TextTheme(
|
||||
title: TextStyle(
|
||||
color: PaletteDark.nightBlue, // picker background
|
||||
backgroundColor: PaletteDark.dividerColor, // picker divider
|
||||
decorationColor: PaletteDark.darkNightBlue // dialog background
|
||||
),
|
||||
caption: TextStyle(
|
||||
color: PaletteDark.nightBlue, // container (confirm exchange)
|
||||
backgroundColor: PaletteDark.deepVioletBlue, // button background (confirm exchange)
|
||||
decorationColor: Palette.darkLavender, // text color (information page)
|
||||
),
|
||||
subtitle: TextStyle(
|
||||
//color: PaletteDark.lightBlueGrey, // QR code (exchange trade page)
|
||||
color: Colors.white, // QR code (exchange trade page)
|
||||
backgroundColor: PaletteDark.deepVioletBlue, // divider (exchange trade page)
|
||||
decorationColor: Colors.white // crete new wallet button background (wallet list page)
|
||||
),
|
||||
headline: TextStyle(
|
||||
color: PaletteDark.distantBlue, // first gradient color of wallet action buttons (wallet list page)
|
||||
backgroundColor: PaletteDark.distantNightBlue, // second gradient color of wallet action buttons (wallet list page)
|
||||
decorationColor: Palette.darkBlueCraiola // restore wallet button text color (wallet list page)
|
||||
),
|
||||
subhead: TextStyle(
|
||||
color: Colors.white, // titles color (filter widget)
|
||||
backgroundColor: PaletteDark.darkOceanBlue, // divider color (filter widget)
|
||||
decorationColor: PaletteDark.wildVioletBlue.withOpacity(0.3) // checkbox background (filter widget)
|
||||
),
|
||||
overline: TextStyle(
|
||||
color: PaletteDark.wildVioletBlue, // checkbox bounds (filter widget)
|
||||
decorationColor: PaletteDark.darkCyanBlue, // menu subname
|
||||
),
|
||||
display1: TextStyle(
|
||||
color: PaletteDark.deepPurpleBlue, // first gradient color (menu header)
|
||||
decorationColor: PaletteDark.deepPurpleBlue, // second gradient color(menu header)
|
||||
backgroundColor: Colors.white // active dot color
|
||||
),
|
||||
display2: TextStyle(
|
||||
color: PaletteDark.nightBlue, // action button color (address text field)
|
||||
decorationColor: PaletteDark.darkCyanBlue, // hint text (seed widget)
|
||||
backgroundColor: PaletteDark.cyanBlue // text on balance page
|
||||
),
|
||||
display3: TextStyle(
|
||||
color: PaletteDark.cyanBlue, // hint text (new wallet page)
|
||||
decorationColor: PaletteDark.darkGrey, // underline (new wallet page)
|
||||
backgroundColor: Colors.white // menu, icons, balance (dashboard page)
|
||||
),
|
||||
display4: TextStyle(
|
||||
color: PaletteDark.deepVioletBlue, // switch background (settings page)
|
||||
decorationColor: PaletteDark.lightBlueGrey // hint text (exchange page)
|
||||
),
|
||||
body1: TextStyle(
|
||||
color: PaletteDark.indicatorVioletBlue, // indicators (PIN code)
|
||||
decorationColor: PaletteDark.lightPurpleBlue, // switch (PIN code)
|
||||
backgroundColor: PaletteDark.darkNightBlue // alert right button
|
||||
),
|
||||
body2: TextStyle(
|
||||
color: Palette.blueCraiola, // primary buttons
|
||||
decorationColor: PaletteDark.darkNightBlue, // alert left button
|
||||
backgroundColor: PaletteDark.granite // keyboard bar color
|
||||
),
|
||||
),
|
||||
cardColor: PaletteDark.darkNightBlue // bottom button (action list)
|
||||
);
|
||||
}
|
196
lib/themes/light_theme.dart
Normal file
|
@ -0,0 +1,196 @@
|
|||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class LightTheme extends ThemeBase {
|
||||
LightTheme({@required int raw}) : super(raw: raw);
|
||||
|
||||
@override
|
||||
String get title => S.current.light_theme;
|
||||
|
||||
@override
|
||||
ThemeType get type => ThemeType.light;
|
||||
|
||||
@override
|
||||
ThemeData get themeData => ThemeData(
|
||||
fontFamily: 'Lato',
|
||||
brightness: Brightness.light,
|
||||
backgroundColor: Colors.white,
|
||||
accentColor: Colors.white, // first gradient color
|
||||
scaffoldBackgroundColor: Colors.white, // second gradient color
|
||||
primaryColor: Colors.white, // third gradient color
|
||||
buttonColor: Palette.blueAlice, // action buttons on dashboard page
|
||||
indicatorColor: PaletteDark.darkCyanBlue.withOpacity(0.67), // page indicator
|
||||
hoverColor: Palette.darkBlueCraiola, // amount hint text (receive page)
|
||||
dividerColor: Palette.paleBlue,
|
||||
hintColor: Palette.gray,
|
||||
textTheme: TextTheme(
|
||||
title: TextStyle(
|
||||
color: Palette.darkBlueCraiola, // sync_indicator text
|
||||
backgroundColor: Palette.blueAlice, // synced sync_indicator
|
||||
decorationColor: Palette.blueAlice.withOpacity(0.75), // not synced sync_indicator
|
||||
),
|
||||
caption: TextStyle(
|
||||
color: Palette.shineOrange, // not synced light
|
||||
decorationColor: PaletteDark.wildBlue, // filter icon
|
||||
),
|
||||
overline: TextStyle(
|
||||
color: Palette.blueAlice, // filter button
|
||||
backgroundColor: PaletteDark.darkCyanBlue, // date section row
|
||||
decorationColor: Palette.blueAlice // icons (transaction and trade rows)
|
||||
),
|
||||
subhead: TextStyle(
|
||||
color: Palette.blueAlice, // address button border
|
||||
decorationColor: PaletteDark.lightBlueGrey, // copy button (qr widget)
|
||||
),
|
||||
headline: TextStyle(
|
||||
color: Colors.white, // qr code
|
||||
decorationColor: Palette.darkBlueCraiola, // bottom border of amount (receive page)
|
||||
),
|
||||
display1: TextStyle(
|
||||
color: PaletteDark.lightBlueGrey, // icons color (receive page)
|
||||
decorationColor: Palette.moderateLavender, // icons background (receive page)
|
||||
),
|
||||
display2: TextStyle(
|
||||
color: Palette.darkBlueCraiola, // text color of tiles (receive page)
|
||||
decorationColor: Palette.blueAlice // background of tiles (receive page)
|
||||
),
|
||||
display3: TextStyle(
|
||||
color: Colors.white, // text color of current tile (receive page),
|
||||
//decorationColor: Palette.blueCraiola // background of current tile (receive page)
|
||||
decorationColor: Palette.blueCraiola // background of current tile (receive page)
|
||||
),
|
||||
display4: TextStyle(
|
||||
color: Palette.violetBlue, // text color of tiles (account list)
|
||||
decorationColor: Colors.white // background of tiles (account list)
|
||||
),
|
||||
subtitle: TextStyle(
|
||||
color: Palette.protectiveBlue, // text color of current tile (account list)
|
||||
decorationColor: Colors.white // background of current tile (account list)
|
||||
),
|
||||
body1: TextStyle(
|
||||
color: Palette.moderatePurpleBlue, // scrollbar thumb
|
||||
decorationColor: Palette.periwinkleCraiola // scrollbar background
|
||||
),
|
||||
body2: TextStyle(
|
||||
color: Palette.moderateLavender, // menu header
|
||||
decorationColor: Colors.white, // menu background
|
||||
)
|
||||
),
|
||||
primaryTextTheme: TextTheme(
|
||||
title: TextStyle(
|
||||
color: Palette.darkBlueCraiola, // title color
|
||||
backgroundColor: Palette.wildPeriwinkle // textfield underline
|
||||
),
|
||||
caption: TextStyle(
|
||||
color: PaletteDark.pigeonBlue, // secondary text
|
||||
decorationColor: Palette.wildLavender // menu divider
|
||||
),
|
||||
overline: TextStyle(
|
||||
color: Palette.darkGray, // transaction/trade details titles
|
||||
decorationColor: PaletteDark.darkCyanBlue, // placeholder
|
||||
),
|
||||
subhead: TextStyle(
|
||||
color: Palette.blueCraiola, // first gradient color (send page)
|
||||
decorationColor: Palette.blueGreyCraiola // second gradient color (send page)
|
||||
),
|
||||
headline: TextStyle(
|
||||
color: Colors.white.withOpacity(0.5), // text field border color (send page)
|
||||
decorationColor: Colors.white.withOpacity(0.5), // text field hint color (send page)
|
||||
),
|
||||
display1: TextStyle(
|
||||
color: Colors.white.withOpacity(0.2), // text field button color (send page)
|
||||
decorationColor: Colors.white // text field button icon color (send page)
|
||||
),
|
||||
display2: TextStyle(
|
||||
color: Colors.white.withOpacity(0.5), // estimated fee (send page)
|
||||
decorationColor: Palette.moderateLavender // template dotted border (send page)
|
||||
),
|
||||
display3: TextStyle(
|
||||
color: Palette.darkBlueCraiola, // template new text (send page)
|
||||
decorationColor: Palette.blueAlice // template background color (send page)
|
||||
),
|
||||
display4: TextStyle(
|
||||
color: Palette.darkBlueCraiola, // template title (send page)
|
||||
decorationColor: Palette.niagara // receive amount text (exchange page)
|
||||
),
|
||||
subtitle: TextStyle(
|
||||
color: Palette.blueCraiola, // first gradient color top panel (exchange page)
|
||||
decorationColor: Palette.blueGreyCraiola // second gradient color top panel (exchange page)
|
||||
),
|
||||
body1: TextStyle(
|
||||
color: Palette.blueCraiola.withOpacity(0.7), // first gradient color bottom panel (exchange page)
|
||||
decorationColor: Palette.blueGreyCraiola.withOpacity(0.7), // second gradient color bottom panel (exchange page)
|
||||
backgroundColor: Palette.protectiveBlue // alert right button text
|
||||
),
|
||||
body2: TextStyle(
|
||||
color: Colors.white.withOpacity(0.5), // text field border on top panel (exchange page)
|
||||
decorationColor: Colors.white.withOpacity(0.5), // text field border on bottom panel (exchange page)
|
||||
backgroundColor: Palette.brightOrange // alert left button text
|
||||
)
|
||||
),
|
||||
focusColor: Colors.white.withOpacity(0.2), // text field button (exchange page)
|
||||
accentTextTheme: TextTheme(
|
||||
title: TextStyle(
|
||||
color: Colors.white, // picker background
|
||||
backgroundColor: Palette.periwinkleCraiola, // picker divider
|
||||
decorationColor: Colors.white // dialog background
|
||||
),
|
||||
caption: TextStyle(
|
||||
color: Palette.blueAlice, // container (confirm exchange)
|
||||
backgroundColor: Palette.blueAlice, // button background (confirm exchange)
|
||||
decorationColor: Palette.darkBlueCraiola, // text color (information page)
|
||||
),
|
||||
subtitle: TextStyle(
|
||||
color: Palette.darkBlueCraiola, // QR code (exchange trade page)
|
||||
backgroundColor: Palette.wildPeriwinkle, // divider (exchange trade page)
|
||||
decorationColor: Palette.protectiveBlue // crete new wallet button background (wallet list page)
|
||||
),
|
||||
headline: TextStyle(
|
||||
color: Palette.moderateLavender, // first gradient color of wallet action buttons (wallet list page)
|
||||
backgroundColor: Palette.moderateLavender, // second gradient color of wallet action buttons (wallet list page)
|
||||
decorationColor: Colors.white // restore wallet button text color (wallet list page)
|
||||
),
|
||||
subhead: TextStyle(
|
||||
color: Palette.darkGray, // titles color (filter widget)
|
||||
backgroundColor: Palette.periwinkle, // divider color (filter widget)
|
||||
decorationColor: Colors.white // checkbox background (filter widget)
|
||||
),
|
||||
overline: TextStyle(
|
||||
color: Palette.wildPeriwinkle, // checkbox bounds (filter widget)
|
||||
decorationColor: Colors.white, // menu subname
|
||||
),
|
||||
display1: TextStyle(
|
||||
color: Palette.blueCraiola, // first gradient color (menu header)
|
||||
decorationColor: Palette.blueGreyCraiola, // second gradient color(menu header)
|
||||
backgroundColor: PaletteDark.darkNightBlue // active dot color
|
||||
),
|
||||
display2: TextStyle(
|
||||
color: Palette.shadowWhite, // action button color (address text field)
|
||||
decorationColor: Palette.darkGray, // hint text (seed widget)
|
||||
backgroundColor: Palette.darkBlueCraiola.withOpacity(0.67) // text on balance page
|
||||
),
|
||||
display3: TextStyle(
|
||||
color: Palette.darkGray, // hint text (new wallet page)
|
||||
decorationColor: Palette.periwinkleCraiola, // underline (new wallet page)
|
||||
backgroundColor: Palette.darkBlueCraiola // menu, icons, balance (dashboard page)
|
||||
),
|
||||
display4: TextStyle(
|
||||
color: Palette.darkGray, // switch background (settings page)
|
||||
decorationColor: Colors.white.withOpacity(0.4) // hint text (exchange page)
|
||||
),
|
||||
body1: TextStyle(
|
||||
color: Palette.darkGray, // indicators (PIN code)
|
||||
decorationColor: Palette.darkGray, // switch (PIN code)
|
||||
backgroundColor: Colors.white // alert right button
|
||||
),
|
||||
body2: TextStyle(
|
||||
color: Palette.protectiveBlue, // primary buttons
|
||||
decorationColor: Colors.white, // alert left button,
|
||||
backgroundColor: Palette.dullGray // keyboard bar color
|
||||
),
|
||||
),
|
||||
cardColor: Palette.protectiveBlue // bottom button (action list)
|
||||
);
|
||||
}
|
17
lib/themes/theme_base.dart
Normal file
|
@ -0,0 +1,17 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
enum ThemeType {light, bright, dark}
|
||||
|
||||
abstract class ThemeBase {
|
||||
ThemeBase({@required this.raw});
|
||||
|
||||
final int raw;
|
||||
String get title;
|
||||
ThemeData get themeData;
|
||||
ThemeType get type;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return title;
|
||||
}
|
||||
}
|
25
lib/themes/theme_list.dart
Normal file
|
@ -0,0 +1,25 @@
|
|||
import 'package:cake_wallet/themes/bright_theme.dart';
|
||||
import 'package:cake_wallet/themes/dark_theme.dart';
|
||||
import 'package:cake_wallet/themes/light_theme.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
|
||||
class ThemeList {
|
||||
static final all = [lightTheme, brightTheme, darkTheme];
|
||||
|
||||
static final lightTheme = LightTheme(raw: 0);
|
||||
static final brightTheme = BrightTheme(raw: 1);
|
||||
static final darkTheme = DarkTheme(raw: 2);
|
||||
|
||||
static ThemeBase deserialize({int raw}) {
|
||||
switch (raw) {
|
||||
case 0:
|
||||
return lightTheme;
|
||||
case 1:
|
||||
return brightTheme;
|
||||
case 2:
|
||||
return darkTheme;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -57,7 +57,8 @@ extension MobxBindable<T extends Keyable> on Box<T> {
|
|||
Filter<T> filter,
|
||||
}) {
|
||||
if (initialFire) {
|
||||
dest.addAll(values);
|
||||
final res = filter != null ? values.where(filter) : values;
|
||||
dest.addAll(res);
|
||||
}
|
||||
|
||||
return watch().listen((event) {
|
||||
|
|
|
@ -15,31 +15,34 @@ part 'balance_view_model.g.dart';
|
|||
class BalanceViewModel = BalanceViewModelBase with _$BalanceViewModel;
|
||||
|
||||
abstract class BalanceViewModelBase with Store {
|
||||
BalanceViewModelBase({
|
||||
@required this.appStore,
|
||||
@required this.settingsStore,
|
||||
@required this.fiatConvertationStore
|
||||
}) : isReversing = false;
|
||||
BalanceViewModelBase(
|
||||
{@required this.appStore,
|
||||
@required this.settingsStore,
|
||||
@required this.fiatConvertationStore})
|
||||
: isReversing = false;
|
||||
|
||||
final AppStore appStore;
|
||||
final SettingsStore settingsStore;
|
||||
final FiatConversionStore fiatConvertationStore;
|
||||
|
||||
bool get canReverse =>
|
||||
(appStore.wallet.balance.availableModes as List).length > 1;
|
||||
|
||||
@observable
|
||||
bool isReversing;
|
||||
|
||||
@computed
|
||||
double get price => fiatConvertationStore.prices[appStore.wallet.currency];
|
||||
|
||||
@computed
|
||||
BalanceDisplayMode get savedDisplayMode => settingsStore.balanceDisplayMode;
|
||||
|
||||
@computed
|
||||
BalanceDisplayMode get displayMode => isReversing
|
||||
? (savedDisplayMode == BalanceDisplayMode.availableBalance
|
||||
? BalanceDisplayMode.fullBalance
|
||||
: BalanceDisplayMode.availableBalance)
|
||||
: savedDisplayMode;
|
||||
|
||||
@computed
|
||||
double get price => fiatConvertationStore.price;
|
||||
? (savedDisplayMode == BalanceDisplayMode.availableBalance
|
||||
? BalanceDisplayMode.fullBalance
|
||||
: BalanceDisplayMode.availableBalance)
|
||||
: savedDisplayMode;
|
||||
|
||||
@computed
|
||||
String get cryptoBalance {
|
||||
|
@ -63,15 +66,11 @@ abstract class BalanceViewModelBase with Store {
|
|||
final fiatCurrency = settingsStore.fiatCurrency;
|
||||
var balance = '---';
|
||||
|
||||
final totalBalance = _getFiatBalance(
|
||||
price: price,
|
||||
cryptoAmount: walletBalance.totalBalance
|
||||
);
|
||||
final totalBalance =
|
||||
_getFiatBalance(price: price, cryptoAmount: walletBalance.totalBalance);
|
||||
|
||||
final unlockedBalance = _getFiatBalance(
|
||||
price: price,
|
||||
cryptoAmount: walletBalance.unlockedBalance
|
||||
);
|
||||
price: price, cryptoAmount: walletBalance.unlockedBalance);
|
||||
|
||||
if (displayMode == BalanceDisplayMode.availableBalance) {
|
||||
balance = fiatCurrency.toString() + ' ' + unlockedBalance ?? '0.00';
|
||||
|
@ -89,14 +88,14 @@ abstract class BalanceViewModelBase with Store {
|
|||
final _wallet = appStore.wallet;
|
||||
|
||||
if (_wallet is MoneroWallet) {
|
||||
return WalletBalance(
|
||||
return WalletBalance(
|
||||
unlockedBalance: _wallet.balance.formattedUnlockedBalance,
|
||||
totalBalance: _wallet.balance.formattedFullBalance);
|
||||
}
|
||||
|
||||
if (_wallet is BitcoinWallet) {
|
||||
return WalletBalance(
|
||||
unlockedBalance: _wallet.balance.totalFormatted,
|
||||
unlockedBalance: _wallet.balance.availableBalanceFormatted,
|
||||
totalBalance: _wallet.balance.totalFormatted);
|
||||
}
|
||||
|
||||
|
@ -113,4 +112,4 @@ abstract class BalanceViewModelBase with Store {
|
|||
|
||||
return calculateFiatAmount(price: price, cryptoAmount: cryptoAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -186,6 +186,8 @@ abstract class DashboardViewModelBase with Store {
|
|||
@observable
|
||||
WalletBase wallet;
|
||||
|
||||
bool get hasRescan => wallet.type == WalletType.monero;
|
||||
|
||||
BalanceViewModel balanceViewModel;
|
||||
|
||||
AppStore appStore;
|
||||
|
@ -212,6 +214,7 @@ abstract class DashboardViewModelBase with Store {
|
|||
@action
|
||||
void _onWalletChange(WalletBase wallet) {
|
||||
this.wallet = wallet;
|
||||
type = wallet.type;
|
||||
name = wallet.name;
|
||||
|
||||
if (wallet is MoneroWallet) {
|
||||
|
@ -236,6 +239,21 @@ abstract class DashboardViewModelBase with Store {
|
|||
balanceViewModel: balanceViewModel,
|
||||
settingsStore: appStore.settingsStore)));
|
||||
}
|
||||
|
||||
connectMapToListWithTransform(
|
||||
appStore.wallet.transactionHistory.transactions,
|
||||
transactions,
|
||||
(TransactionInfo val) => TransactionListItem(
|
||||
transaction: val,
|
||||
balanceViewModel: balanceViewModel,
|
||||
settingsStore: appStore.settingsStore),
|
||||
filter: (TransactionInfo tx) {
|
||||
if (tx is MoneroTransactionInfo && wallet is MoneroWallet) {
|
||||
return tx.accountIndex == wallet.account.id;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@action
|
||||
|
|
|
@ -13,16 +13,18 @@ part 'node_list_view_model.g.dart';
|
|||
class NodeListViewModel = NodeListViewModelBase with _$NodeListViewModel;
|
||||
|
||||
abstract class NodeListViewModelBase with Store {
|
||||
NodeListViewModelBase(this._nodeSource, this._wallet, this.settingsStore)
|
||||
NodeListViewModelBase(this._nodeSource, this.wallet, this.settingsStore)
|
||||
: nodes = ObservableList<Node>() {
|
||||
_nodeSource.bindToList(nodes,
|
||||
filter: (Node val) => val?.type == _wallet.type, initialFire: true);
|
||||
filter: (Node val) => val?.type == wallet.type, initialFire: true);
|
||||
}
|
||||
|
||||
@computed
|
||||
Node get currentNode => settingsStore.nodes[wallet.type];
|
||||
|
||||
final ObservableList<Node> nodes;
|
||||
final SettingsStore settingsStore;
|
||||
|
||||
final WalletBase _wallet;
|
||||
final WalletBase wallet;
|
||||
final Box<Node> _nodeSource;
|
||||
|
||||
Future<void> reset() async {
|
||||
|
@ -30,14 +32,12 @@ abstract class NodeListViewModelBase with Store {
|
|||
|
||||
Node node;
|
||||
|
||||
switch (_wallet.type) {
|
||||
switch (wallet.type) {
|
||||
case WalletType.bitcoin:
|
||||
node = getBitcoinDefaultElectrumServer(nodes: _nodeSource);
|
||||
break;
|
||||
case WalletType.monero:
|
||||
node = getMoneroDefaultNode(
|
||||
nodes: _nodeSource,
|
||||
);
|
||||
node = getMoneroDefaultNode(nodes: _nodeSource);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -50,5 +50,5 @@ abstract class NodeListViewModelBase with Store {
|
|||
Future<void> delete(Node node) async => node.delete();
|
||||
|
||||
Future<void> setAsCurrent(Node node) async =>
|
||||
settingsStore.currentNode = node;
|
||||
settingsStore.nodes[wallet.type] = node;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cake_wallet/entities/balance_display_mode.dart';
|
||||
import 'package:cake_wallet/entities/transaction_description.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
@ -77,19 +78,9 @@ abstract class SendViewModelBase with Store {
|
|||
PendingTransaction pendingTransaction;
|
||||
|
||||
@computed
|
||||
String get balance {
|
||||
String balance = '0.0';
|
||||
|
||||
if (_wallet is MoneroWallet) {
|
||||
balance = _wallet.balance.formattedUnlockedBalance as String ?? '';
|
||||
}
|
||||
|
||||
if (_wallet is BitcoinWallet) {
|
||||
balance = _wallet.balance.confirmedFormatted as String ?? '';
|
||||
}
|
||||
|
||||
return balance;
|
||||
}
|
||||
String get balance =>
|
||||
_wallet.balance.formattedBalance(BalanceDisplayMode.availableBalance)
|
||||
as String ?? '0.0';
|
||||
|
||||
@computed
|
||||
bool get isReadyForSend => _wallet.syncStatus is SyncedSyncStatus;
|
||||
|
@ -97,6 +88,7 @@ abstract class SendViewModelBase with Store {
|
|||
@computed
|
||||
ObservableList<Template> get templates => _sendTemplateStore.templates;
|
||||
|
||||
WalletType get walletType => _wallet.type;
|
||||
final WalletBase _wallet;
|
||||
final SettingsStore _settingsStore;
|
||||
final SendTemplateStore _sendTemplateStore;
|
||||
|
@ -175,7 +167,7 @@ abstract class SendViewModelBase with Store {
|
|||
void _updateFiatAmount() {
|
||||
try {
|
||||
final fiat = calculateFiatAmount(
|
||||
price: _fiatConversationStore.price,
|
||||
price: _fiatConversationStore.prices[_wallet.currency],
|
||||
cryptoAmount: cryptoAmount.replaceAll(',', '.'));
|
||||
if (fiatAmount != fiat) {
|
||||
fiatAmount = fiat;
|
||||
|
@ -189,7 +181,7 @@ abstract class SendViewModelBase with Store {
|
|||
void _updateCryptoAmount() {
|
||||
try {
|
||||
final crypto = double.parse(fiatAmount.replaceAll(',', '.')) /
|
||||
_fiatConversationStore.price;
|
||||
_fiatConversationStore.prices[_wallet.currency];
|
||||
final cryptoAmountTmp = _cryptoNumberFormat.format(crypto);
|
||||
|
||||
if (cryptoAmount != cryptoAmountTmp) {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:cake_wallet/themes/theme_list.dart';
|
||||
import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
@ -35,12 +37,13 @@ abstract class SettingsViewModelBase with Store {
|
|||
(PackageInfo packageInfo) => currentVersion = packageInfo.version);
|
||||
sections = [
|
||||
[
|
||||
PickerListItem(
|
||||
title: S.current.settings_display_balance_as,
|
||||
items: BalanceDisplayMode.all,
|
||||
selectedItem: () => balanceDisplayMode,
|
||||
onItemSelected: (BalanceDisplayMode mode) =>
|
||||
_settingsStore.balanceDisplayMode = mode),
|
||||
if ((wallet.balance.availableModes as List).length > 1)
|
||||
PickerListItem(
|
||||
title: S.current.settings_display_balance_as,
|
||||
items: BalanceDisplayMode.all,
|
||||
selectedItem: () => balanceDisplayMode,
|
||||
onItemSelected: (BalanceDisplayMode mode) =>
|
||||
_settingsStore.balanceDisplayMode = mode),
|
||||
PickerListItem(
|
||||
title: S.current.settings_currency,
|
||||
items: FiatCurrency.all,
|
||||
|
@ -50,7 +53,7 @@ abstract class SettingsViewModelBase with Store {
|
|||
setFiatCurrency(currency)),
|
||||
PickerListItem(
|
||||
title: S.current.settings_fee_priority,
|
||||
items: _transactionPriorities(wallet.type),
|
||||
items: TransactionPriority.forWalletType(wallet.type),
|
||||
selectedItem: () => transactionPriority,
|
||||
isAlwaysShowScrollThumb: true,
|
||||
onItemSelected: (TransactionPriority priority) =>
|
||||
|
@ -106,11 +109,12 @@ abstract class SettingsViewModelBase with Store {
|
|||
setAllowBiometricalAuthentication(value);
|
||||
}
|
||||
}),
|
||||
SwitcherListItem(
|
||||
title: S.current.settings_dark_mode,
|
||||
value: () => _settingsStore.isDarkTheme,
|
||||
onValueChange: (_, bool value) =>
|
||||
_settingsStore.isDarkTheme = value)
|
||||
PickerListItem(
|
||||
title: S.current.color_theme,
|
||||
items: ThemeList.all,
|
||||
selectedItem: () => theme,
|
||||
onItemSelected: (ThemeBase theme) =>
|
||||
_settingsStore.currentTheme = theme)
|
||||
],
|
||||
[
|
||||
LinkListItem(
|
||||
|
@ -186,6 +190,9 @@ abstract class SettingsViewModelBase with Store {
|
|||
bool get allowBiometricalAuthentication =>
|
||||
_settingsStore.allowBiometricalAuthentication;
|
||||
|
||||
@computed
|
||||
ThemeBase get theme => _settingsStore.currentTheme;
|
||||
|
||||
final Map<String, String> itemHeaders;
|
||||
List<List<SettingsListItem>> sections;
|
||||
final SettingsStore _settingsStore;
|
||||
|
@ -234,19 +241,4 @@ abstract class SettingsViewModelBase with Store {
|
|||
|
||||
@action
|
||||
void _showTrades() => actionlistDisplayMode.add(ActionListDisplayMode.trades);
|
||||
|
||||
static List<TransactionPriority> _transactionPriorities(WalletType type) {
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
return TransactionPriority.all;
|
||||
case WalletType.bitcoin:
|
||||
return [
|
||||
TransactionPriority.slow,
|
||||
TransactionPriority.regular,
|
||||
TransactionPriority.fast
|
||||
];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ class MoneroURI extends PaymentURI {
|
|||
var base = 'monero:' + address;
|
||||
|
||||
if (amount?.isNotEmpty ?? false) {
|
||||
base += '?tx_amount=$amount';
|
||||
base += '?tx_amount=${amount.replaceAll(',', '.')}';
|
||||
}
|
||||
|
||||
return base;
|
||||
|
@ -47,7 +47,7 @@ class BitcoinURI extends PaymentURI {
|
|||
var base = 'bitcoin:' + address;
|
||||
|
||||
if (amount?.isNotEmpty ?? false) {
|
||||
base += '?amount=$amount';
|
||||
base += '?amount=${amount.replaceAll(',', '.')}';
|
||||
}
|
||||
|
||||
return base;
|
||||
|
@ -57,10 +57,13 @@ class BitcoinURI extends PaymentURI {
|
|||
abstract class WalletAddressListViewModelBase with Store {
|
||||
WalletAddressListViewModelBase(
|
||||
{@required AppStore appStore}) {
|
||||
hasAccounts = _wallet is MoneroWallet;
|
||||
_appStore = appStore;
|
||||
_wallet = _appStore.wallet;
|
||||
_onWalletChangeReaction = reaction((_) => _appStore.wallet, (WalletBase wallet) => _wallet = wallet);
|
||||
hasAccounts = _wallet?.type == WalletType.monero;
|
||||
_onWalletChangeReaction = reaction((_) => _appStore.wallet, (WalletBase wallet) {
|
||||
_wallet = wallet;
|
||||
hasAccounts = _wallet.type == WalletType.monero;
|
||||
});
|
||||
_init();
|
||||
}
|
||||
|
||||
|
@ -125,6 +128,7 @@ abstract class WalletAddressListViewModelBase with Store {
|
|||
return addressList;
|
||||
}
|
||||
|
||||
@observable
|
||||
bool hasAccounts;
|
||||
|
||||
@observable
|
||||
|
|
|
@ -27,7 +27,7 @@ abstract class WalletCreationVMBase with Store {
|
|||
@observable
|
||||
ExecutionState state;
|
||||
|
||||
final WalletType type;
|
||||
WalletType type;
|
||||
final bool isRecovery;
|
||||
final Box<WalletInfo> _walletInfoSource;
|
||||
final AppStore _appStore;
|
||||
|
@ -51,7 +51,7 @@ abstract class WalletCreationVMBase with Store {
|
|||
credentials.walletInfo = walletInfo;
|
||||
final wallet = await process(credentials);
|
||||
await _walletInfoSource.add(walletInfo);
|
||||
_appStore.wallet = wallet;
|
||||
_appStore.changeCurrentWallet(wallet);
|
||||
_appStore.authenticationStore.allowed();
|
||||
state = ExecutedSuccessfullyState();
|
||||
} catch (e) {
|
||||
|
|
|
@ -32,7 +32,8 @@ abstract class WalletListViewModelBase with Store {
|
|||
final password =
|
||||
await _keyService.getWalletPassword(walletName: wallet.name);
|
||||
final walletService = getIt.get<WalletService>(param1: wallet.type);
|
||||
_appStore.wallet = await walletService.openWallet(wallet.name, password);
|
||||
final loadedWallet = await walletService.openWallet(wallet.name, password);
|
||||
_appStore.changeCurrentWallet(loadedWallet);
|
||||
_updateList();
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,8 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<WalletBase> process(WalletCredentials credentials) async =>
|
||||
_walletCreationService.create(credentials);
|
||||
Future<WalletBase> process(WalletCredentials credentials) async {
|
||||
_walletCreationService.changeWalletType(type: type);
|
||||
return _walletCreationService.create(credentials);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cake_wallet/bitcoin/bitcoin_wallet_creation_credentials.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
@ -22,10 +23,16 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
|||
WalletRestoreViewModelBase(AppStore appStore, this._walletCreationService,
|
||||
Box<WalletInfo> walletInfoSource,
|
||||
{@required WalletType type})
|
||||
: super(appStore, walletInfoSource, type: type, isRecovery: true) {
|
||||
isButtonEnabled = false;
|
||||
: availableModes = type == WalletType.monero
|
||||
? WalletRestoreMode.values
|
||||
: [WalletRestoreMode.seed],
|
||||
hasSeedLanguageSelector = type == WalletType.monero,
|
||||
hasBlockchainHeightLanguageSelector = type == WalletType.monero,
|
||||
super(appStore, walletInfoSource, type: type, isRecovery: true) {
|
||||
isButtonEnabled =
|
||||
!hasSeedLanguageSelector && !hasBlockchainHeightLanguageSelector;
|
||||
mode = WalletRestoreMode.seed;
|
||||
_walletCreationService.changeWalletType(type: WalletType.monero);
|
||||
_walletCreationService.changeWalletType(type: type);
|
||||
}
|
||||
|
||||
@observable
|
||||
|
@ -34,6 +41,10 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
|||
@observable
|
||||
bool isButtonEnabled;
|
||||
|
||||
final List<WalletRestoreMode> availableModes;
|
||||
final bool hasSeedLanguageSelector;
|
||||
final bool hasBlockchainHeightLanguageSelector;
|
||||
|
||||
final WalletCreationService _walletCreationService;
|
||||
|
||||
@override
|
||||
|
@ -44,8 +55,16 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
|||
if (mode == WalletRestoreMode.seed) {
|
||||
final seed = options['seed'] as String;
|
||||
|
||||
return MoneroRestoreWalletFromSeedCredentials(
|
||||
name: name, height: height, mnemonic: seed, password: password);
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
return MoneroRestoreWalletFromSeedCredentials(
|
||||
name: name, height: height, mnemonic: seed, password: password);
|
||||
case WalletType.bitcoin:
|
||||
return BitcoinRestoreWalletFromSeedCredentials(
|
||||
name: name, mnemonic: seed, password: password);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == WalletRestoreMode.keys) {
|
||||
|
|
16
pubspec.lock
|
@ -247,12 +247,19 @@ packages:
|
|||
source: hosted
|
||||
version: "2.1.1"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: crypto
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.5"
|
||||
cryptography:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cryptography
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -924,6 +931,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0-nullsafety.3"
|
||||
unorm_dart:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: unorm_dart
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.2"
|
||||
url_launcher:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -11,7 +11,7 @@ description: Cake Wallet.
|
|||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
version: 4.0.9+21
|
||||
version: 4.0.91+22
|
||||
|
||||
environment:
|
||||
sdk: ">=2.7.0 <3.0.0"
|
||||
|
@ -60,6 +60,7 @@ dependencies:
|
|||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^0.1.2
|
||||
encrypt: ^4.0.0
|
||||
crypto: ^2.1.5
|
||||
password: ^1.0.0
|
||||
basic_utils: ^1.0.8
|
||||
bitcoin_flutter: ^2.0.0
|
||||
|
@ -67,6 +68,8 @@ dependencies:
|
|||
connectivity: ^0.4.9+2
|
||||
keyboard_actions: ^3.3.0
|
||||
flushbar: ^1.10.4
|
||||
unorm_dart: ^0.1.2
|
||||
cryptography: ^1.4.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
@ -423,5 +423,10 @@
|
|||
|
||||
"provider_error" : "${provider} Error",
|
||||
|
||||
"use_ssl" : "Verwenden Sie SSL"
|
||||
"use_ssl" : "Verwenden Sie SSL",
|
||||
|
||||
"color_theme" : "Farbthema",
|
||||
"light_theme" : "Licht",
|
||||
"bright_theme" : "Hell",
|
||||
"dark_theme" : "Dunkel"
|
||||
}
|
|
@ -423,5 +423,10 @@
|
|||
|
||||
"provider_error" : "${provider} error",
|
||||
|
||||
"use_ssl" : "Use SSL"
|
||||
"use_ssl" : "Use SSL",
|
||||
|
||||
"color_theme" : "Color theme",
|
||||
"light_theme" : "Light",
|
||||
"bright_theme" : "Bright",
|
||||
"dark_theme" : "Dark"
|
||||
}
|