Merge pull request #88 from cake-tech/CAKE-15-new-dashboard-screen
Cake 15 new dashboard screen
BIN
assets/fonts/Poppins-Bold.ttf
Normal file
BIN
assets/fonts/Poppins-Medium.ttf
Normal file
BIN
assets/fonts/Poppins-Regular.ttf
Normal file
BIN
assets/images/changenow.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
assets/images/download.png
Normal file
After Width: | Height: | Size: 352 B |
BIN
assets/images/filter_icon.png
Normal file
After Width: | Height: | Size: 190 B |
BIN
assets/images/menu.png
Normal file
After Width: | Height: | Size: 148 B |
BIN
assets/images/morph.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/images/transfer.png
Normal file
After Width: | Height: | Size: 408 B |
Before Width: | Height: | Size: 193 B After Width: | Height: | Size: 212 B |
BIN
assets/images/upload.png
Normal file
After Width: | Height: | Size: 341 B |
BIN
assets/images/xmrto.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
|
@ -4,6 +4,7 @@ import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||||
import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData;
|
import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData;
|
||||||
import 'package:cake_wallet/src/domain/common/transaction_direction.dart';
|
import 'package:cake_wallet/src/domain/common/transaction_direction.dart';
|
||||||
import 'package:cake_wallet/src/domain/common/transaction_info.dart';
|
import 'package:cake_wallet/src/domain/common/transaction_info.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/common/format_amount.dart';
|
||||||
|
|
||||||
class BitcoinTransactionInfo extends TransactionInfo {
|
class BitcoinTransactionInfo extends TransactionInfo {
|
||||||
BitcoinTransactionInfo(
|
BitcoinTransactionInfo(
|
||||||
|
@ -62,11 +63,16 @@ class BitcoinTransactionInfo extends TransactionInfo {
|
||||||
|
|
||||||
final String id;
|
final String id;
|
||||||
|
|
||||||
@override
|
String _fiatAmount;
|
||||||
String amountFormatted() => bitcoinAmountToString(amount: amount);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String fiatAmount() => '\$ 24.5';
|
String amountFormatted() => '${formatAmount(bitcoinAmountToString(amount: amount))} BTC';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String fiatAmount() => _fiatAmount ?? '';
|
||||||
|
|
||||||
|
@override
|
||||||
|
void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount);
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final m = Map<String, dynamic>();
|
final m = Map<String, dynamic>();
|
||||||
|
|
34
lib/di.dart
|
@ -1,6 +1,7 @@
|
||||||
import 'package:cake_wallet/core/contact_service.dart';
|
import 'package:cake_wallet/core/contact_service.dart';
|
||||||
import 'package:cake_wallet/src/domain/common/contact.dart';
|
import 'package:cake_wallet/src/domain/common/contact.dart';
|
||||||
import 'package:cake_wallet/src/domain/common/node.dart';
|
import 'package:cake_wallet/src/domain/common/node.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/exchange/trade.dart';
|
||||||
import 'package:cake_wallet/src/screens/contact/contact_list_page.dart';
|
import 'package:cake_wallet/src/screens/contact/contact_list_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/contact/contact_page.dart';
|
import 'package:cake_wallet/src/screens/contact/contact_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/nodes/node_create_or_edit_page.dart';
|
import 'package:cake_wallet/src/screens/nodes/node_create_or_edit_page.dart';
|
||||||
|
@ -11,7 +12,7 @@ import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart';
|
||||||
import 'package:cake_wallet/store/contact_list_store.dart';
|
import 'package:cake_wallet/store/contact_list_store.dart';
|
||||||
import 'package:cake_wallet/store/node_list_store.dart';
|
import 'package:cake_wallet/store/node_list_store.dart';
|
||||||
import 'package:cake_wallet/store/settings_store.dart';
|
import 'package:cake_wallet/store/settings_store.dart';
|
||||||
import 'package:cake_wallet/store/settings_store.dart';
|
import 'package:cake_wallet/src/stores/price/price_store.dart';
|
||||||
import 'package:cake_wallet/core/auth_service.dart';
|
import 'package:cake_wallet/core/auth_service.dart';
|
||||||
import 'package:cake_wallet/core/key_service.dart';
|
import 'package:cake_wallet/core/key_service.dart';
|
||||||
import 'package:cake_wallet/monero/monero_wallet.dart';
|
import 'package:cake_wallet/monero/monero_wallet.dart';
|
||||||
|
@ -31,7 +32,8 @@ import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart';
|
import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart';
|
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/auth_view_model.dart';
|
import 'package:cake_wallet/view_model/auth_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/dashboard_view_model.dart';
|
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart';
|
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart';
|
import 'package:cake_wallet/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/monero_account_list/monero_account_list_view_model.dart';
|
import 'package:cake_wallet/view_model/monero_account_list/monero_account_list_view_model.dart';
|
||||||
|
@ -52,6 +54,9 @@ import 'package:cake_wallet/store/app_store.dart';
|
||||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||||
import 'package:cake_wallet/view_model/wallet_new_vm.dart';
|
import 'package:cake_wallet/view_model/wallet_new_vm.dart';
|
||||||
import 'package:cake_wallet/store/authentication_store.dart';
|
import 'package:cake_wallet/store/authentication_store.dart';
|
||||||
|
import 'package:cake_wallet/store/dashboard/trades_store.dart';
|
||||||
|
import 'package:cake_wallet/store/dashboard/trade_filter_store.dart';
|
||||||
|
import 'package:cake_wallet/store/dashboard/transaction_filter_store.dart';
|
||||||
|
|
||||||
final getIt = GetIt.instance;
|
final getIt = GetIt.instance;
|
||||||
|
|
||||||
|
@ -77,7 +82,9 @@ NodeListStore setupNodeListStore(Box<Node> nodeSource) {
|
||||||
Future setup(
|
Future setup(
|
||||||
{Box<WalletInfo> walletInfoSource,
|
{Box<WalletInfo> walletInfoSource,
|
||||||
Box<Node> nodeSource,
|
Box<Node> nodeSource,
|
||||||
Box<Contact> contactSource}) async {
|
Box<Contact> contactSource,
|
||||||
|
Box<Trade> tradesSource,
|
||||||
|
PriceStore priceStore}) async {
|
||||||
getIt.registerSingletonAsync<SharedPreferences>(
|
getIt.registerSingletonAsync<SharedPreferences>(
|
||||||
() => SharedPreferences.getInstance());
|
() => SharedPreferences.getInstance());
|
||||||
|
|
||||||
|
@ -97,6 +104,13 @@ Future setup(
|
||||||
nodeListStore: getIt.get<NodeListStore>()));
|
nodeListStore: getIt.get<NodeListStore>()));
|
||||||
getIt.registerSingleton<ContactService>(
|
getIt.registerSingleton<ContactService>(
|
||||||
ContactService(contactSource, getIt.get<AppStore>().contactListStore));
|
ContactService(contactSource, getIt.get<AppStore>().contactListStore));
|
||||||
|
getIt.registerSingleton<TradesStore>(TradesStore(
|
||||||
|
tradesSource: tradesSource,
|
||||||
|
settingsStore: getIt.get<SettingsStore>()));
|
||||||
|
getIt.registerSingleton<TradeFilterStore>(
|
||||||
|
TradeFilterStore(wallet: getIt.get<AppStore>().wallet));
|
||||||
|
getIt.registerSingleton<TransactionFilterStore>(TransactionFilterStore());
|
||||||
|
|
||||||
getIt.registerFactory<KeyService>(
|
getIt.registerFactory<KeyService>(
|
||||||
() => KeyService(getIt.get<FlutterSecureStorage>()));
|
() => KeyService(getIt.get<FlutterSecureStorage>()));
|
||||||
|
|
||||||
|
@ -128,7 +142,19 @@ Future setup(
|
||||||
() => WalletAddressListViewModel(wallet: getIt.get<AppStore>().wallet));
|
() => WalletAddressListViewModel(wallet: getIt.get<AppStore>().wallet));
|
||||||
|
|
||||||
getIt.registerFactory(
|
getIt.registerFactory(
|
||||||
() => DashboardViewModel(appStore: getIt.get<AppStore>()));
|
() => BalanceViewModel(
|
||||||
|
wallet: getIt.get<AppStore>().wallet,
|
||||||
|
settingsStore: getIt.get<SettingsStore>(),
|
||||||
|
priceStore: priceStore));
|
||||||
|
|
||||||
|
getIt.registerFactory(
|
||||||
|
() => DashboardViewModel(
|
||||||
|
balanceViewModel: getIt.get<BalanceViewModel>(),
|
||||||
|
appStore: getIt.get<AppStore>(),
|
||||||
|
tradesStore: getIt.get<TradesStore>(),
|
||||||
|
tradeFilterStore: getIt.get<TradeFilterStore>(),
|
||||||
|
transactionFilterStore: getIt.get<TransactionFilterStore>()
|
||||||
|
));
|
||||||
|
|
||||||
getIt.registerFactory<AuthService>(() => AuthService(
|
getIt.registerFactory<AuthService>(() => AuthService(
|
||||||
secureStorage: getIt.get<FlutterSecureStorage>(),
|
secureStorage: getIt.get<FlutterSecureStorage>(),
|
||||||
|
|
|
@ -24,7 +24,6 @@ class S implements WidgetsLocalizations {
|
||||||
String get account => "Account";
|
String get account => "Account";
|
||||||
String get accounts => "Accounts";
|
String get accounts => "Accounts";
|
||||||
String get accounts_subaddresses => "Accounts and subaddresses";
|
String get accounts_subaddresses => "Accounts and subaddresses";
|
||||||
String get addresses => "Addresses";
|
|
||||||
String get add => "Add";
|
String get add => "Add";
|
||||||
String get add_new_node => "Add new node";
|
String get add_new_node => "Add new node";
|
||||||
String get add_new_word => "Add new word";
|
String get add_new_word => "Add new word";
|
||||||
|
@ -32,6 +31,7 @@ class S implements WidgetsLocalizations {
|
||||||
String get address_book_menu => "Address book";
|
String get address_book_menu => "Address book";
|
||||||
String get address_remove_contact => "Remove contact";
|
String get address_remove_contact => "Remove contact";
|
||||||
String get address_remove_content => "Are you sure that you want to remove selected contact?";
|
String get address_remove_content => "Are you sure that you want to remove selected contact?";
|
||||||
|
String get addresses => "Addresses";
|
||||||
String get all => "ALL";
|
String get all => "ALL";
|
||||||
String get amount => "Amount: ";
|
String get amount => "Amount: ";
|
||||||
String get amount_is_estimate => "The receive amount is an estimate";
|
String get amount_is_estimate => "The receive amount is an estimate";
|
||||||
|
@ -643,8 +643,6 @@ class $de extends S {
|
||||||
@override
|
@override
|
||||||
String get accounts_subaddresses => "Konten und Unteradressen";
|
String get accounts_subaddresses => "Konten und Unteradressen";
|
||||||
@override
|
@override
|
||||||
String get addresses => "Addressen";
|
|
||||||
@override
|
|
||||||
String get wallet_name => "Walletname";
|
String get wallet_name => "Walletname";
|
||||||
@override
|
@override
|
||||||
String get error_text_payment_id => "Die Zahlungs-ID kann nur 16 bis 64 hexadezimale Zeichen enthalten";
|
String get error_text_payment_id => "Die Zahlungs-ID kann nur 16 bis 64 hexadezimale Zeichen enthalten";
|
||||||
|
@ -1265,8 +1263,6 @@ class $hi extends S {
|
||||||
@override
|
@override
|
||||||
String get accounts_subaddresses => "लेखा और उपदेस";
|
String get accounts_subaddresses => "लेखा और उपदेस";
|
||||||
@override
|
@override
|
||||||
String get addresses => "पतों";
|
|
||||||
@override
|
|
||||||
String get wallet_name => "बटुए का नाम";
|
String get wallet_name => "बटुए का नाम";
|
||||||
@override
|
@override
|
||||||
String get error_text_payment_id => "पेमेंट आईडी केवल हेक्स में 16 से 64 चार्ट तक हो सकती है";
|
String get error_text_payment_id => "पेमेंट आईडी केवल हेक्स में 16 से 64 चार्ट तक हो सकती है";
|
||||||
|
@ -1887,8 +1883,6 @@ class $ru extends S {
|
||||||
@override
|
@override
|
||||||
String get accounts_subaddresses => "Аккаунты и субадреса";
|
String get accounts_subaddresses => "Аккаунты и субадреса";
|
||||||
@override
|
@override
|
||||||
String get addresses => "Адреса";
|
|
||||||
@override
|
|
||||||
String get wallet_name => "Имя кошелька";
|
String get wallet_name => "Имя кошелька";
|
||||||
@override
|
@override
|
||||||
String get error_text_payment_id => "Идентификатор платежа может содержать от 16 до 64 символов в hex";
|
String get error_text_payment_id => "Идентификатор платежа может содержать от 16 до 64 символов в hex";
|
||||||
|
@ -2509,8 +2503,6 @@ class $ko extends S {
|
||||||
@override
|
@override
|
||||||
String get accounts_subaddresses => "계정 및 하위 주소";
|
String get accounts_subaddresses => "계정 및 하위 주소";
|
||||||
@override
|
@override
|
||||||
String get addresses => "구애";
|
|
||||||
@override
|
|
||||||
String get wallet_name => "지갑 이름";
|
String get wallet_name => "지갑 이름";
|
||||||
@override
|
@override
|
||||||
String get error_text_payment_id => "지불 ID는 16 ~ 64 자의 16 진 문자 만 포함 할 수 있습니다";
|
String get error_text_payment_id => "지불 ID는 16 ~ 64 자의 16 진 문자 만 포함 할 수 있습니다";
|
||||||
|
@ -3131,8 +3123,6 @@ class $pt extends S {
|
||||||
@override
|
@override
|
||||||
String get accounts_subaddresses => "Contas e sub-endereços";
|
String get accounts_subaddresses => "Contas e sub-endereços";
|
||||||
@override
|
@override
|
||||||
String get addresses => "Endereços";
|
|
||||||
@override
|
|
||||||
String get wallet_name => "Nome da carteira";
|
String get wallet_name => "Nome da carteira";
|
||||||
@override
|
@override
|
||||||
String get error_text_payment_id => "O ID de pagamento pode conter apenas de 16 a 64 caracteres em hexadecimal";
|
String get error_text_payment_id => "O ID de pagamento pode conter apenas de 16 a 64 caracteres em hexadecimal";
|
||||||
|
@ -3753,8 +3743,6 @@ class $uk extends S {
|
||||||
@override
|
@override
|
||||||
String get accounts_subaddresses => "Акаунти та субадреси";
|
String get accounts_subaddresses => "Акаунти та субадреси";
|
||||||
@override
|
@override
|
||||||
String get addresses => "Адреси";
|
|
||||||
@override
|
|
||||||
String get wallet_name => "Ім'я гаманця";
|
String get wallet_name => "Ім'я гаманця";
|
||||||
@override
|
@override
|
||||||
String get error_text_payment_id => "Ідентифікатор платежу може містити від 16 до 64 символів в hex";
|
String get error_text_payment_id => "Ідентифікатор платежу може містити від 16 до 64 символів в hex";
|
||||||
|
@ -4375,8 +4363,6 @@ class $ja extends S {
|
||||||
@override
|
@override
|
||||||
String get accounts_subaddresses => "アカウントとサブアドレス";
|
String get accounts_subaddresses => "アカウントとサブアドレス";
|
||||||
@override
|
@override
|
||||||
String get addresses => "アドレス";
|
|
||||||
@override
|
|
||||||
String get wallet_name => "ウォレット名";
|
String get wallet_name => "ウォレット名";
|
||||||
@override
|
@override
|
||||||
String get error_text_payment_id => "支払いIDには、16進数で16〜64文字しか含めることができません";
|
String get error_text_payment_id => "支払いIDには、16進数で16〜64文字しか含めることができません";
|
||||||
|
@ -5001,8 +4987,6 @@ class $pl extends S {
|
||||||
@override
|
@override
|
||||||
String get accounts_subaddresses => "Konta i podadresy";
|
String get accounts_subaddresses => "Konta i podadresy";
|
||||||
@override
|
@override
|
||||||
String get addresses => "Adresy";
|
|
||||||
@override
|
|
||||||
String get wallet_name => "Nazwa portfela";
|
String get wallet_name => "Nazwa portfela";
|
||||||
@override
|
@override
|
||||||
String get error_text_payment_id => "ID może zawierać od 16 do 64 znaków w formacie szesnastkowym";
|
String get error_text_payment_id => "ID może zawierać od 16 do 64 znaków w formacie szesnastkowym";
|
||||||
|
@ -5623,8 +5607,6 @@ class $es extends S {
|
||||||
@override
|
@override
|
||||||
String get accounts_subaddresses => "Cuentas y subdirecciones";
|
String get accounts_subaddresses => "Cuentas y subdirecciones";
|
||||||
@override
|
@override
|
||||||
String get addresses => "Direcciones";
|
|
||||||
@override
|
|
||||||
String get wallet_name => "Nombre de la billetera";
|
String get wallet_name => "Nombre de la billetera";
|
||||||
@override
|
@override
|
||||||
String get error_text_payment_id => "La ID de pago solo puede contener de 16 a 64 caracteres en hexadecimal";
|
String get error_text_payment_id => "La ID de pago solo puede contener de 16 a 64 caracteres en hexadecimal";
|
||||||
|
@ -6245,8 +6227,6 @@ class $nl extends S {
|
||||||
@override
|
@override
|
||||||
String get accounts_subaddresses => "Accounts en subadressen";
|
String get accounts_subaddresses => "Accounts en subadressen";
|
||||||
@override
|
@override
|
||||||
String get addresses => "Adressen";
|
|
||||||
@override
|
|
||||||
String get wallet_name => "Portemonnee naam";
|
String get wallet_name => "Portemonnee naam";
|
||||||
@override
|
@override
|
||||||
String get error_text_payment_id => "Betalings-ID kan alleen 16 tot 64 tekens bevatten in hexadecimale volgorde";
|
String get error_text_payment_id => "Betalings-ID kan alleen 16 tot 64 tekens bevatten in hexadecimale volgorde";
|
||||||
|
@ -6867,8 +6847,6 @@ class $zh extends S {
|
||||||
@override
|
@override
|
||||||
String get accounts_subaddresses => "帳戶和子地址";
|
String get accounts_subaddresses => "帳戶和子地址";
|
||||||
@override
|
@override
|
||||||
String get addresses => "地址";
|
|
||||||
@override
|
|
||||||
String get wallet_name => "钱包名称";
|
String get wallet_name => "钱包名称";
|
||||||
@override
|
@override
|
||||||
String get error_text_payment_id => "付款ID只能包含16到64个字符(十六进制)";
|
String get error_text_payment_id => "付款ID只能包含16到64个字符(十六进制)";
|
||||||
|
|
|
@ -85,13 +85,6 @@ void main() async {
|
||||||
final exchangeTemplates =
|
final exchangeTemplates =
|
||||||
await Hive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName);
|
await Hive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName);
|
||||||
|
|
||||||
await initialSetup(
|
|
||||||
sharedPreferences: await SharedPreferences.getInstance(),
|
|
||||||
nodes: nodes,
|
|
||||||
walletInfoSource: walletInfoSource,
|
|
||||||
contactSource: contacts,
|
|
||||||
initialMigrationVersion: 3);
|
|
||||||
|
|
||||||
final sharedPreferences = await SharedPreferences.getInstance();
|
final sharedPreferences = await SharedPreferences.getInstance();
|
||||||
final walletService = WalletService();
|
final walletService = WalletService();
|
||||||
final walletListService = WalletListService(
|
final walletListService = WalletListService(
|
||||||
|
@ -125,6 +118,15 @@ void main() async {
|
||||||
final walletCreationService = WalletCreationService();
|
final walletCreationService = WalletCreationService();
|
||||||
final authService = AuthService();
|
final authService = AuthService();
|
||||||
|
|
||||||
|
await initialSetup(
|
||||||
|
sharedPreferences: await SharedPreferences.getInstance(),
|
||||||
|
nodes: nodes,
|
||||||
|
walletInfoSource: walletInfoSource,
|
||||||
|
contactSource: contacts,
|
||||||
|
tradesSource: trades,
|
||||||
|
priceStore: priceStore,
|
||||||
|
initialMigrationVersion: 3);
|
||||||
|
|
||||||
setReactions(
|
setReactions(
|
||||||
settingsStore: settingsStore,
|
settingsStore: settingsStore,
|
||||||
priceStore: priceStore,
|
priceStore: priceStore,
|
||||||
|
@ -163,6 +165,8 @@ Future<void> initialSetup(
|
||||||
@required Box<Node> nodes,
|
@required Box<Node> nodes,
|
||||||
@required Box<WalletInfo> walletInfoSource,
|
@required Box<WalletInfo> walletInfoSource,
|
||||||
@required Box<Contact> contactSource,
|
@required Box<Contact> contactSource,
|
||||||
|
@required Box<Trade> tradesSource,
|
||||||
|
@required PriceStore priceStore,
|
||||||
int initialMigrationVersion = 3}) async {
|
int initialMigrationVersion = 3}) async {
|
||||||
await defaultSettingsMigration(
|
await defaultSettingsMigration(
|
||||||
version: initialMigrationVersion,
|
version: initialMigrationVersion,
|
||||||
|
@ -171,7 +175,9 @@ Future<void> initialSetup(
|
||||||
await setup(
|
await setup(
|
||||||
walletInfoSource: walletInfoSource,
|
walletInfoSource: walletInfoSource,
|
||||||
nodeSource: nodes,
|
nodeSource: nodes,
|
||||||
contactSource: contactSource);
|
contactSource: contactSource,
|
||||||
|
tradesSource: tradesSource,
|
||||||
|
priceStore: priceStore);
|
||||||
await bootstrap();
|
await bootstrap();
|
||||||
monero_wallet.onStartup();
|
monero_wallet.onStartup();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ class Palette {
|
||||||
class PaletteDark {
|
class PaletteDark {
|
||||||
static const Color distantBlue = Color.fromRGBO(70, 85, 133, 1.0); // mainBackgroundColor
|
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 lightDistantBlue = Color.fromRGBO(81, 96, 147, 1.0); // borderCardColor
|
||||||
static const Color nightBlue = Color.fromRGBO(45, 56, 95, 1.0); // walletCardBottomEndSync
|
|
||||||
static const Color gray = Color.fromRGBO(140, 153, 201, 1.0); // walletCardText
|
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 violetBlue = Color.fromRGBO(51, 63, 104, 1.0); // walletCardAddressField
|
||||||
static const Color moderateBlue = Color.fromRGBO(63, 77, 122, 1.0); // walletCardSubAddressField
|
static const Color moderateBlue = Color.fromRGBO(63, 77, 122, 1.0); // walletCardSubAddressField
|
||||||
|
@ -28,8 +27,21 @@ class PaletteDark {
|
||||||
static const Color pigeonBlue = Color.fromRGBO(91, 112, 146, 1.0); // historyPanelText
|
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 moderateNightBlue = Color.fromRGBO(39, 53, 96, 1.0); // historyPanelButton
|
||||||
static const Color headerNightBlue = Color.fromRGBO(41, 52, 84, 1.0); // menuHeader
|
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 lightNightBlue = Color.fromRGBO(48, 59, 95, 1.0); // menuList
|
||||||
static const Color moderatePurpleBlue = Color.fromRGBO(57, 74, 95, 1.0); // selectButtonText
|
static const Color moderatePurpleBlue = Color.fromRGBO(57, 74, 95, 1.0); // selectButtonText
|
||||||
|
|
||||||
|
// NEW DESIGN
|
||||||
|
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);
|
||||||
|
static const Color cyanBlue = Color.fromRGBO(99, 113, 150, 1.0);
|
||||||
|
static const Color darkCyanBlue = Color.fromRGBO(91, 112, 146, 1.0);
|
||||||
|
static const Color orangeYellow = Color.fromRGBO(243, 166, 50, 1.0);
|
||||||
|
static const Color brightGreen = Color.fromRGBO(88, 243, 50, 1.0);
|
||||||
|
static const Color oceanBlue = Color.fromRGBO(27, 39, 71, 1.0);
|
||||||
|
static const Color lightNightBlue = Color.fromRGBO(39, 52, 89, 1.0);
|
||||||
|
static const Color wildBlue = Color.fromRGBO(165, 176, 205, 1.0);
|
||||||
|
|
||||||
// FIXME: Rename.
|
// FIXME: Rename.
|
||||||
static const Color eee = Color.fromRGBO(236, 239, 245, 1.0);
|
static const Color eee = Color.fromRGBO(236, 239, 245, 1.0);
|
||||||
static const Color xxx = Color.fromRGBO(72, 89, 109, 1);
|
static const Color xxx = Color.fromRGBO(72, 89, 109, 1);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:cake_wallet/src/screens/dashboard/dashboard_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/seed/wallet_seed_page.dart';
|
import 'package:cake_wallet/src/screens/seed/wallet_seed_page.dart';
|
||||||
import 'package:cake_wallet/view_model/wallet_new_vm.dart';
|
import 'package:cake_wallet/view_model/wallet_new_vm.dart';
|
||||||
import 'package:cake_wallet/view_model/wallet_restoration_from_seed_vm.dart';
|
import 'package:cake_wallet/view_model/wallet_restoration_from_seed_vm.dart';
|
||||||
|
@ -249,13 +250,7 @@ class Router {
|
||||||
|
|
||||||
case Routes.dashboard:
|
case Routes.dashboard:
|
||||||
return CupertinoPageRoute<void>(
|
return CupertinoPageRoute<void>(
|
||||||
builder: (_) => createDashboardPage(
|
builder: (_) => getIt.get<DashboardPage>());
|
||||||
walletService: walletService,
|
|
||||||
priceStore: priceStore,
|
|
||||||
settingsStore: settingsStore,
|
|
||||||
trades: trades,
|
|
||||||
transactionDescriptions: transactionDescriptions,
|
|
||||||
walletStore: walletStore));
|
|
||||||
|
|
||||||
case Routes.send:
|
case Routes.send:
|
||||||
return CupertinoPageRoute<void>(
|
return CupertinoPageRoute<void>(
|
||||||
|
|
|
@ -8,4 +8,5 @@ abstract class TransactionInfo extends Object {
|
||||||
int height;
|
int height;
|
||||||
String amountFormatted();
|
String amountFormatted();
|
||||||
String fiatAmount();
|
String fiatAmount();
|
||||||
|
void changeFiatAmount(String amount);
|
||||||
}
|
}
|
|
@ -2,149 +2,164 @@ import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:cake_wallet/view_model/dashboard_view_model.dart';
|
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/dashboard/widgets/wallet_card.dart';
|
|
||||||
import 'package:cake_wallet/src/screens/dashboard/widgets/trade_history_panel.dart';
|
|
||||||
import 'package:cake_wallet/src/screens/dashboard/widgets/menu_widget.dart';
|
import 'package:cake_wallet/src/screens/dashboard/widgets/menu_widget.dart';
|
||||||
|
import 'package:cake_wallet/palette.dart';
|
||||||
|
import 'package:dots_indicator/dots_indicator.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/dashboard/widgets/action_button.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/dashboard/widgets/balance_page.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_page.dart';
|
||||||
|
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator.dart';
|
||||||
|
|
||||||
class DashboardPage extends BasePage {
|
class DashboardPage extends BasePage {
|
||||||
DashboardPage({@required this.walletViewModel});
|
DashboardPage({@required this.walletViewModel});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color get backgroundLightColor => Colors.transparent;
|
Color get backgroundLightColor => PaletteDark.backgroundColor;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color get backgroundDarkColor => Colors.transparent;
|
Color get backgroundDarkColor => PaletteDark.backgroundColor;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget Function(BuildContext, Widget) get rootWrapper =>
|
Widget middle(BuildContext context) {
|
||||||
(BuildContext context, Widget scaffold) => Container(
|
return SyncIndicator(dashboardViewModel: walletViewModel);
|
||||||
decoration: BoxDecoration(
|
}
|
||||||
gradient: LinearGradient(colors: [
|
|
||||||
Theme.of(context).scaffoldBackgroundColor,
|
|
||||||
Theme.of(context).primaryColor
|
|
||||||
], begin: Alignment.topLeft, end: Alignment.bottomRight)),
|
|
||||||
child: scaffold);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget trailing(BuildContext context) {
|
Widget trailing(BuildContext context) {
|
||||||
final menuButton = Image.asset('assets/images/header.png',
|
final menuButton = Image.asset('assets/images/menu.png',
|
||||||
color: Theme.of(context).primaryTextTheme.title.color);
|
color: Colors.white);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: SizedBox(
|
width: 40,
|
||||||
width: 24,
|
child: FlatButton(
|
||||||
child: FlatButton(
|
highlightColor: Colors.transparent,
|
||||||
highlightColor: Colors.transparent,
|
splashColor: Colors.transparent,
|
||||||
splashColor: Colors.transparent,
|
padding: EdgeInsets.all(0),
|
||||||
padding: EdgeInsets.all(0),
|
onPressed: () async {
|
||||||
onPressed: () async {
|
await showDialog<void>(
|
||||||
await showDialog<void>(
|
builder: (_) => MenuWidget(
|
||||||
builder: (_) => MenuWidget(
|
name: walletViewModel.name,
|
||||||
name: walletViewModel.name,
|
subname: walletViewModel.subname,
|
||||||
subname: walletViewModel.subname,
|
type: walletViewModel.type),
|
||||||
type: walletViewModel.type),
|
context: context);
|
||||||
context: context);
|
},
|
||||||
},
|
child: menuButton
|
||||||
child: menuButton),
|
)
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final DashboardViewModel walletViewModel;
|
final DashboardViewModel walletViewModel;
|
||||||
final sendImage = Image.asset('assets/images/send.png');
|
final sendImage = Image.asset('assets/images/upload.png',
|
||||||
final exchangeImage = Image.asset('assets/images/exchange.png');
|
height: 22.24, width: 24, color: Colors.white);
|
||||||
final buyImage = Image.asset('assets/images/coins.png');
|
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: 0);
|
||||||
|
|
||||||
|
var pages = <Widget>[];
|
||||||
|
bool _isEffectsInstalled = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget body(BuildContext context) {
|
Widget body(BuildContext context) {
|
||||||
return LayoutBuilder(builder: (context, constraints) {
|
|
||||||
final transactionListMinHeight =
|
|
||||||
constraints.heightConstraints().maxHeight - 345 - 32;
|
|
||||||
|
|
||||||
return SingleChildScrollView(
|
_setEffects();
|
||||||
child: Column(children: [
|
|
||||||
Container(
|
return SafeArea(
|
||||||
height: 345,
|
child: Column(
|
||||||
child: Column(children: [
|
mainAxisSize: MainAxisSize.max,
|
||||||
Padding(
|
children: <Widget>[
|
||||||
padding: EdgeInsets.only(left: 24, top: 10),
|
Expanded(
|
||||||
child: WalletCard(walletVM: walletViewModel)),
|
child: PageView.builder(
|
||||||
Container(
|
controller: controller,
|
||||||
padding: EdgeInsets.only(left: 44, right: 44, top: 32),
|
itemCount: pages.length,
|
||||||
child: Row(
|
itemBuilder: (context, index) {
|
||||||
children: <Widget>[
|
return pages[index];
|
||||||
Flexible(
|
}
|
||||||
child: actionButton(
|
)
|
||||||
context: context,
|
),
|
||||||
image: sendImage,
|
Padding(
|
||||||
title: S.of(context).send,
|
padding: EdgeInsets.only(
|
||||||
route: Routes.send)),
|
bottom: 24
|
||||||
Flexible(
|
),
|
||||||
child: actionButton(
|
child: Observer(
|
||||||
context: context,
|
builder: (_) {
|
||||||
image: exchangeImage,
|
return DotsIndicator(
|
||||||
title: S.of(context).exchange,
|
dotsCount: pages.length,
|
||||||
route: Routes.exchange)),
|
position: walletViewModel.currentPage,
|
||||||
],
|
decorator: DotsDecorator(
|
||||||
|
color: PaletteDark.cyanBlue,
|
||||||
|
activeColor: Colors.white,
|
||||||
|
size: Size(6, 6),
|
||||||
|
activeSize: Size(6, 6),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
width: double.infinity,
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: 45,
|
||||||
|
right: 45,
|
||||||
|
bottom: 24
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Flexible(
|
||||||
|
child: ActionButton(
|
||||||
|
image: sendImage,
|
||||||
|
title: S.of(context).send,
|
||||||
|
route: Routes.send,
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
Flexible(
|
||||||
])),
|
child: ActionButton(
|
||||||
SizedBox(height: 32),
|
image: exchangeImage,
|
||||||
ConstrainedBox(
|
title: S.of(context).exchange,
|
||||||
constraints: BoxConstraints(minHeight: transactionListMinHeight),
|
route: Routes.exchange
|
||||||
child: TradeHistoryPanel(dashboardViewModel: walletViewModel)),
|
),
|
||||||
// Column(children: [
|
),
|
||||||
// Text('1'),
|
Flexible(
|
||||||
// Text('2')
|
child: ActionButton(
|
||||||
// ])
|
image: receiveImage,
|
||||||
]));
|
title: S.of(context).receive,
|
||||||
|
route: Routes.receive,
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _setEffects() {
|
||||||
|
if (_isEffectsInstalled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pages.add(BalancePage(dashboardViewModel: walletViewModel));
|
||||||
|
pages.add(TransactionsPage(dashboardViewModel: walletViewModel));
|
||||||
|
|
||||||
|
controller.addListener(() {
|
||||||
|
walletViewModel.currentPage = controller.page;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
reaction((_) => walletViewModel.currentPage, (double currentPage) {
|
||||||
|
if (controller.page != currentPage) {
|
||||||
|
controller.jumpTo(currentPage);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_isEffectsInstalled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget actionButton(
|
|
||||||
{BuildContext context,
|
|
||||||
@required Image image,
|
|
||||||
@required String title,
|
|
||||||
@required String route}) {
|
|
||||||
return Container(
|
|
||||||
width: MediaQuery.of(context).size.width,
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
|
||||||
GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
if (route.isNotEmpty) {
|
|
||||||
Navigator.of(context, rootNavigator: true).pushNamed(route);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
height: 48,
|
|
||||||
width: 48,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context).primaryTextTheme.subhead.color,
|
|
||||||
shape: BoxShape.circle),
|
|
||||||
child: image,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.only(top: 12),
|
|
||||||
child: Text(
|
|
||||||
title,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Color.fromRGBO(140, 153, 201,
|
|
||||||
0.8) // Theme.of(context).primaryTextTheme.caption.color
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
55
lib/src/screens/dashboard/widgets/action_button.dart
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:cake_wallet/palette.dart';
|
||||||
|
|
||||||
|
class ActionButton extends StatelessWidget{
|
||||||
|
ActionButton({
|
||||||
|
@required this.image,
|
||||||
|
@required this.title,
|
||||||
|
@required this.route,
|
||||||
|
this.alignment = Alignment.center
|
||||||
|
});
|
||||||
|
|
||||||
|
final Image image;
|
||||||
|
final String title;
|
||||||
|
final String route;
|
||||||
|
final Alignment alignment;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
width: double.infinity,
|
||||||
|
height: 93,
|
||||||
|
alignment: alignment,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
if (route.isNotEmpty) {
|
||||||
|
Navigator.of(context, rootNavigator: true).pushNamed(route);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
height: 60,
|
||||||
|
width: 60,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: PaletteDark.nightBlue,
|
||||||
|
shape: BoxShape.circle),
|
||||||
|
child: image,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.white
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
68
lib/src/screens/dashboard/widgets/balance_page.dart
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||||
|
import 'package:cake_wallet/palette.dart';
|
||||||
|
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||||
|
|
||||||
|
class BalancePage extends StatelessWidget {
|
||||||
|
BalancePage({@required this.dashboardViewModel});
|
||||||
|
|
||||||
|
final DashboardViewModel dashboardViewModel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.all(24),
|
||||||
|
child: Center(
|
||||||
|
child: Container(
|
||||||
|
height: 160,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Observer(
|
||||||
|
builder: (_) {
|
||||||
|
return Text(
|
||||||
|
dashboardViewModel.wallet.currency.toString(),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 40,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: PaletteDark.cyanBlue,
|
||||||
|
height: 1
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
Observer(
|
||||||
|
builder: (_) {
|
||||||
|
return Text(
|
||||||
|
dashboardViewModel.balanceViewModel.cryptoBalance,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 54,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.white,
|
||||||
|
height: 1
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
Observer(
|
||||||
|
builder: (_) {
|
||||||
|
return Text(
|
||||||
|
dashboardViewModel.balanceViewModel.fiatBalance,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: PaletteDark.cyanBlue,
|
||||||
|
height: 1
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,255 +0,0 @@
|
||||||
import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
|
|
||||||
import 'package:cake_wallet/src/stores/action_list/action_list_store.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
|
||||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:cake_wallet/routes.dart';
|
|
||||||
import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker;
|
|
||||||
import 'package:cake_wallet/themes.dart';
|
|
||||||
import 'package:cake_wallet/theme_changer.dart';
|
|
||||||
|
|
||||||
class ButtonHeader extends SliverPersistentHeaderDelegate {
|
|
||||||
final sendImage = Image.asset('assets/images/send.png');
|
|
||||||
final exchangeImage = Image.asset('assets/images/exchange.png');
|
|
||||||
final buyImage = Image.asset('assets/images/coins.png');
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(
|
|
||||||
BuildContext context, double shrinkOffset, bool overlapsContent) {
|
|
||||||
final _themeChanger = Provider.of<ThemeChanger>(context);
|
|
||||||
Image filterButton;
|
|
||||||
|
|
||||||
if (_themeChanger.getTheme() == Themes.darkTheme) {
|
|
||||||
filterButton = Image.asset('assets/images/filter_button.png');
|
|
||||||
} else {
|
|
||||||
filterButton = Image.asset('assets/images/filter_light_button.png');
|
|
||||||
}
|
|
||||||
|
|
||||||
return ClipRRect(
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(24), topRight: Radius.circular(24)),
|
|
||||||
child: Container(
|
|
||||||
color: Colors.red,
|
|
||||||
// height: 75,
|
|
||||||
padding: EdgeInsets.only(top: 26, left: 20, right: 20, bottom: 10),
|
|
||||||
// color: Theme.of(context).backgroundColor,
|
|
||||||
child: Stack(
|
|
||||||
children: <Widget>[
|
|
||||||
Center(
|
|
||||||
child: Text(
|
|
||||||
S.of(context).transactions,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Theme.of(context).primaryTextTheme.title.color),
|
|
||||||
)),
|
|
||||||
Positioned(
|
|
||||||
right: 0,
|
|
||||||
height: 36,
|
|
||||||
child: PopupMenuButton<int>(
|
|
||||||
itemBuilder: (context) => [
|
|
||||||
PopupMenuItem(
|
|
||||||
enabled: false,
|
|
||||||
value: -1,
|
|
||||||
child: Text(S.of(context).transactions,
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.primaryTextTheme
|
|
||||||
.caption
|
|
||||||
.color))),
|
|
||||||
// PopupMenuItem(
|
|
||||||
// value: 0,
|
|
||||||
// child: Observer(
|
|
||||||
// builder: (_) => Row(
|
|
||||||
// mainAxisAlignment:
|
|
||||||
// MainAxisAlignment
|
|
||||||
// .spaceBetween,
|
|
||||||
// children: [
|
|
||||||
// Text(S.of(context).incoming),
|
|
||||||
// Checkbox(
|
|
||||||
// value: actionListStore
|
|
||||||
// .transactionFilterStore
|
|
||||||
// .displayIncoming,
|
|
||||||
// onChanged: (value) =>
|
|
||||||
// actionListStore
|
|
||||||
// .transactionFilterStore
|
|
||||||
// .toggleIncoming(),
|
|
||||||
// )
|
|
||||||
// ]))),
|
|
||||||
// PopupMenuItem(
|
|
||||||
// value: 1,
|
|
||||||
// child: Observer(
|
|
||||||
// builder: (_) => Row(
|
|
||||||
// mainAxisAlignment:
|
|
||||||
// MainAxisAlignment
|
|
||||||
// .spaceBetween,
|
|
||||||
// children: [
|
|
||||||
// Text(S.of(context).outgoing),
|
|
||||||
// Checkbox(
|
|
||||||
// value: actionListStore
|
|
||||||
// .transactionFilterStore
|
|
||||||
// .displayOutgoing,
|
|
||||||
// onChanged: (value) =>
|
|
||||||
// actionListStore
|
|
||||||
// .transactionFilterStore
|
|
||||||
// .toggleOutgoing(),
|
|
||||||
// )
|
|
||||||
// ]))),
|
|
||||||
PopupMenuItem(
|
|
||||||
value: 2,
|
|
||||||
child: Text(S.of(context).transactions_by_date)),
|
|
||||||
PopupMenuDivider(),
|
|
||||||
PopupMenuItem(
|
|
||||||
enabled: false,
|
|
||||||
value: -1,
|
|
||||||
child: Text(S.of(context).trades,
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.primaryTextTheme
|
|
||||||
.caption
|
|
||||||
.color))),
|
|
||||||
PopupMenuItem(
|
|
||||||
value: 3,
|
|
||||||
child: Observer(
|
|
||||||
builder: (_) => Row(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text('XMR.TO'),
|
|
||||||
// Checkbox(
|
|
||||||
// value: actionListStore
|
|
||||||
// .tradeFilterStore
|
|
||||||
// .displayXMRTO,
|
|
||||||
// onChanged: (value) =>
|
|
||||||
// actionListStore
|
|
||||||
// .tradeFilterStore
|
|
||||||
// .toggleDisplayExchange(
|
|
||||||
// ExchangeProviderDescription
|
|
||||||
// .xmrto),
|
|
||||||
// )
|
|
||||||
]))),
|
|
||||||
PopupMenuItem(
|
|
||||||
value: 4,
|
|
||||||
child: Observer(
|
|
||||||
builder: (_) => Row(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text('Change.NOW'),
|
|
||||||
// Checkbox(
|
|
||||||
// value: actionListStore
|
|
||||||
// .tradeFilterStore
|
|
||||||
// .displayChangeNow,
|
|
||||||
// onChanged: (value) =>
|
|
||||||
// actionListStore
|
|
||||||
// .tradeFilterStore
|
|
||||||
// .toggleDisplayExchange(
|
|
||||||
// ExchangeProviderDescription
|
|
||||||
// .changeNow),
|
|
||||||
// )
|
|
||||||
]))),
|
|
||||||
PopupMenuItem(
|
|
||||||
value: 5,
|
|
||||||
child: Observer(
|
|
||||||
builder: (_) => Row(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text('MorphToken'),
|
|
||||||
// Checkbox(
|
|
||||||
// value: actionListStore
|
|
||||||
// .tradeFilterStore
|
|
||||||
// .displayMorphToken,
|
|
||||||
// onChanged: (value) =>
|
|
||||||
// actionListStore
|
|
||||||
// .tradeFilterStore
|
|
||||||
// .toggleDisplayExchange(
|
|
||||||
// ExchangeProviderDescription
|
|
||||||
// .morphToken),
|
|
||||||
// )
|
|
||||||
])))
|
|
||||||
],
|
|
||||||
child: filterButton,
|
|
||||||
onSelected: (item) async {
|
|
||||||
if (item == 2) {
|
|
||||||
final List<DateTime> picked =
|
|
||||||
await date_rage_picker.showDatePicker(
|
|
||||||
context: context,
|
|
||||||
initialFirstDate:
|
|
||||||
DateTime.now().subtract(Duration(days: 1)),
|
|
||||||
initialLastDate: (DateTime.now()),
|
|
||||||
firstDate: DateTime(2015),
|
|
||||||
lastDate: DateTime.now().add(Duration(days: 1)));
|
|
||||||
|
|
||||||
if (picked != null && picked.length == 2) {
|
|
||||||
// actionListStore.transactionFilterStore
|
|
||||||
// .changeStartDate(picked.first);
|
|
||||||
// actionListStore.transactionFilterStore
|
|
||||||
// .changeEndDate(picked.last);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
double get maxExtent => 164;
|
|
||||||
|
|
||||||
@override
|
|
||||||
double get minExtent => 66;
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true;
|
|
||||||
|
|
||||||
Widget actionButton(
|
|
||||||
{BuildContext context,
|
|
||||||
@required Image image,
|
|
||||||
@required String title,
|
|
||||||
@required String route}) {
|
|
||||||
return Container(
|
|
||||||
width: MediaQuery.of(context).size.width,
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
|
||||||
GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
if (route.isNotEmpty) {
|
|
||||||
Navigator.of(context, rootNavigator: true).pushNamed(route);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
height: 48,
|
|
||||||
width: 48,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context).primaryTextTheme.subhead.color,
|
|
||||||
shape: BoxShape.circle),
|
|
||||||
child: image,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.only(top: 12),
|
|
||||||
child: Text(
|
|
||||||
title,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Color.fromRGBO(140, 153, 201,
|
|
||||||
0.8) // Theme.of(context).primaryTextTheme.caption.color
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,6 +3,7 @@ import 'package:intl/intl.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:cake_wallet/src/stores/settings/settings_store.dart';
|
import 'package:cake_wallet/src/stores/settings/settings_store.dart';
|
||||||
|
import 'package:cake_wallet/palette.dart';
|
||||||
|
|
||||||
class DateSectionRaw extends StatelessWidget {
|
class DateSectionRaw extends StatelessWidget {
|
||||||
DateSectionRaw({this.date});
|
DateSectionRaw({this.date});
|
||||||
|
@ -35,21 +36,14 @@ class DateSectionRaw extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
height: 36,
|
height: 35,
|
||||||
padding: EdgeInsets.only(top: 10, bottom: 10, left: 20, right: 20),
|
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
decoration: BoxDecoration(
|
color: Colors.transparent,
|
||||||
color: Theme.of(context).backgroundColor,
|
|
||||||
border: Border.all(
|
|
||||||
width: 1,
|
|
||||||
color: Theme.of(context).backgroundColor
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Text(title,
|
child: Text(title,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Theme.of(context).primaryTextTheme.headline.color
|
color: PaletteDark.darkCyanBlue
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
187
lib/src/screens/dashboard/widgets/header_row.dart
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:cake_wallet/palette.dart';
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
|
||||||
|
import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker;
|
||||||
|
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||||
|
|
||||||
|
class HeaderRow extends StatelessWidget {
|
||||||
|
HeaderRow({this.dashboardViewModel});
|
||||||
|
|
||||||
|
final DashboardViewModel dashboardViewModel;
|
||||||
|
|
||||||
|
final filterIcon = Image.asset('assets/images/filter_icon.png',
|
||||||
|
color: PaletteDark.wildBlue);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
height: 52,
|
||||||
|
color: Colors.transparent,
|
||||||
|
padding: EdgeInsets.only(left: 24, right: 24),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Text(
|
||||||
|
S.of(context).transactions,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Colors.white
|
||||||
|
),
|
||||||
|
),
|
||||||
|
PopupMenuButton<int>(
|
||||||
|
itemBuilder: (context) => [
|
||||||
|
PopupMenuItem(
|
||||||
|
enabled: false,
|
||||||
|
value: -1,
|
||||||
|
child: Text(S.of(context).transactions,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Theme.of(context).primaryTextTheme.caption.color))),
|
||||||
|
PopupMenuItem(
|
||||||
|
value: 0,
|
||||||
|
child: Observer(
|
||||||
|
builder: (_) => Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment
|
||||||
|
.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(S.of(context).incoming),
|
||||||
|
Checkbox(
|
||||||
|
value: dashboardViewModel
|
||||||
|
.transactionFilterStore
|
||||||
|
.displayIncoming,
|
||||||
|
onChanged: (value) => dashboardViewModel
|
||||||
|
.transactionFilterStore
|
||||||
|
.toggleIncoming()
|
||||||
|
)
|
||||||
|
]))),
|
||||||
|
PopupMenuItem(
|
||||||
|
value: 1,
|
||||||
|
child: Observer(
|
||||||
|
builder: (_) => Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment
|
||||||
|
.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(S.of(context).outgoing),
|
||||||
|
Checkbox(
|
||||||
|
value: dashboardViewModel
|
||||||
|
.transactionFilterStore
|
||||||
|
.displayOutgoing,
|
||||||
|
onChanged: (value) => dashboardViewModel
|
||||||
|
.transactionFilterStore
|
||||||
|
.toggleOutgoing(),
|
||||||
|
)
|
||||||
|
]))),
|
||||||
|
PopupMenuItem(
|
||||||
|
value: 2,
|
||||||
|
child:
|
||||||
|
Text(S.of(context).transactions_by_date)),
|
||||||
|
PopupMenuDivider(),
|
||||||
|
PopupMenuItem(
|
||||||
|
enabled: false,
|
||||||
|
value: -1,
|
||||||
|
child: Text(S.of(context).trades,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Theme.of(context).primaryTextTheme.caption.color))),
|
||||||
|
PopupMenuItem(
|
||||||
|
value: 3,
|
||||||
|
child: Observer(
|
||||||
|
builder: (_) => Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment
|
||||||
|
.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text('XMR.TO'),
|
||||||
|
Checkbox(
|
||||||
|
value: dashboardViewModel
|
||||||
|
.tradeFilterStore
|
||||||
|
.displayXMRTO,
|
||||||
|
onChanged: (value) => dashboardViewModel
|
||||||
|
.tradeFilterStore
|
||||||
|
.toggleDisplayExchange(
|
||||||
|
ExchangeProviderDescription
|
||||||
|
.xmrto),
|
||||||
|
)
|
||||||
|
]))),
|
||||||
|
PopupMenuItem(
|
||||||
|
value: 4,
|
||||||
|
child: Observer(
|
||||||
|
builder: (_) => Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment
|
||||||
|
.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text('Change.NOW'),
|
||||||
|
Checkbox(
|
||||||
|
value: dashboardViewModel
|
||||||
|
.tradeFilterStore
|
||||||
|
.displayChangeNow,
|
||||||
|
onChanged: (value) => dashboardViewModel
|
||||||
|
.tradeFilterStore
|
||||||
|
.toggleDisplayExchange(
|
||||||
|
ExchangeProviderDescription
|
||||||
|
.changeNow),
|
||||||
|
)
|
||||||
|
]))),
|
||||||
|
PopupMenuItem(
|
||||||
|
value: 5,
|
||||||
|
child: Observer(
|
||||||
|
builder: (_) => Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment
|
||||||
|
.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text('MorphToken'),
|
||||||
|
Checkbox(
|
||||||
|
value: dashboardViewModel
|
||||||
|
.tradeFilterStore
|
||||||
|
.displayMorphToken,
|
||||||
|
onChanged: (value) => dashboardViewModel
|
||||||
|
.tradeFilterStore
|
||||||
|
.toggleDisplayExchange(
|
||||||
|
ExchangeProviderDescription
|
||||||
|
.morphToken),
|
||||||
|
)
|
||||||
|
])))
|
||||||
|
],
|
||||||
|
child: Container(
|
||||||
|
height: 36,
|
||||||
|
width: 36,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
color: PaletteDark.oceanBlue
|
||||||
|
),
|
||||||
|
child: filterIcon,
|
||||||
|
),
|
||||||
|
onSelected: (item) async {
|
||||||
|
if (item == 2) {
|
||||||
|
final picked =
|
||||||
|
await date_rage_picker.showDatePicker(
|
||||||
|
context: context,
|
||||||
|
initialFirstDate: DateTime.now()
|
||||||
|
.subtract(Duration(days: 1)),
|
||||||
|
initialLastDate: (DateTime.now()),
|
||||||
|
firstDate: DateTime(2015),
|
||||||
|
lastDate: DateTime.now()
|
||||||
|
.add(Duration(days: 1)));
|
||||||
|
|
||||||
|
if (picked != null && picked.length == 2) {
|
||||||
|
dashboardViewModel.transactionFilterStore
|
||||||
|
.changeStartDate(picked.first);
|
||||||
|
dashboardViewModel.transactionFilterStore
|
||||||
|
.changeEndDate(picked.last);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
87
lib/src/screens/dashboard/widgets/sync_indicator.dart
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||||
|
import 'package:cake_wallet/palette.dart';
|
||||||
|
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/common/sync_status.dart';
|
||||||
|
|
||||||
|
class SyncIndicator extends StatelessWidget {
|
||||||
|
SyncIndicator({@required this.dashboardViewModel});
|
||||||
|
|
||||||
|
final DashboardViewModel dashboardViewModel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Observer(
|
||||||
|
builder: (_) {
|
||||||
|
final syncIndicatorWidth = 250.0;
|
||||||
|
final status = dashboardViewModel.status;
|
||||||
|
final statusText = status.title();
|
||||||
|
final progress = status.progress();
|
||||||
|
final indicatorOffset = progress * syncIndicatorWidth;
|
||||||
|
final indicatorWidth =
|
||||||
|
progress <= 1 ? syncIndicatorWidth - indicatorOffset : 0.0;
|
||||||
|
final indicatorColor = status is SyncedSyncStatus
|
||||||
|
? PaletteDark.brightGreen
|
||||||
|
: PaletteDark.orangeYellow;
|
||||||
|
|
||||||
|
return ClipRRect(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(15)),
|
||||||
|
child: Container(
|
||||||
|
height: 30,
|
||||||
|
width: syncIndicatorWidth,
|
||||||
|
color: PaletteDark.lightNightBlue,
|
||||||
|
child: Stack(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
progress <= 1
|
||||||
|
? Positioned(
|
||||||
|
left: indicatorOffset,
|
||||||
|
top: 0,
|
||||||
|
bottom: 0,
|
||||||
|
child: Container(
|
||||||
|
width: indicatorWidth,
|
||||||
|
height: 30,
|
||||||
|
color: PaletteDark.oceanBlue,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
: Offstage(),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: 24,
|
||||||
|
right: 24
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Container(
|
||||||
|
height: 4,
|
||||||
|
width: 4,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
color: indicatorColor
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(left: 6),
|
||||||
|
child: Text(
|
||||||
|
statusText,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: PaletteDark.wildBlue
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,322 +0,0 @@
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
|
||||||
import 'package:cake_wallet/theme_changer.dart';
|
|
||||||
import 'package:cake_wallet/themes.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
|
||||||
import 'package:intl/intl.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:cake_wallet/routes.dart';
|
|
||||||
import 'package:cake_wallet/view_model/dashboard_view_model.dart';
|
|
||||||
import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
|
|
||||||
import 'package:cake_wallet/src/stores/action_list/action_list_store.dart';
|
|
||||||
import 'package:cake_wallet/src/stores/action_list/date_section_item.dart';
|
|
||||||
import 'package:cake_wallet/src/stores/action_list/trade_list_item.dart';
|
|
||||||
import 'package:cake_wallet/src/stores/action_list/transaction_list_item.dart';
|
|
||||||
import 'package:cake_wallet/src/stores/settings/settings_store.dart';
|
|
||||||
import 'date_section_raw.dart';
|
|
||||||
import 'trade_row.dart';
|
|
||||||
import 'transaction_raw.dart';
|
|
||||||
import 'button_header.dart';
|
|
||||||
import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker;
|
|
||||||
|
|
||||||
class TradeHistoryPanel extends StatefulWidget {
|
|
||||||
TradeHistoryPanel({this.dashboardViewModel});
|
|
||||||
|
|
||||||
final DashboardViewModel dashboardViewModel;
|
|
||||||
|
|
||||||
@override
|
|
||||||
TradeHistoryPanelState createState() => TradeHistoryPanelState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class TradeHistoryPanelState extends State<TradeHistoryPanel> {
|
|
||||||
final _listObserverKey = GlobalKey();
|
|
||||||
final _listKey = GlobalKey();
|
|
||||||
|
|
||||||
double panelHeight;
|
|
||||||
double screenHeight;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
panelHeight = 0;
|
|
||||||
screenHeight = 0;
|
|
||||||
super.initState();
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback(afterLayout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void afterLayout(dynamic _) {
|
|
||||||
screenHeight = MediaQuery.of(context).size.height;
|
|
||||||
setState(() {
|
|
||||||
panelHeight = screenHeight;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
// AnimatedContainer(
|
|
||||||
// width: MediaQuery.of(context).size.width,
|
|
||||||
// height: panelHeight,
|
|
||||||
// duration: Duration(milliseconds: 1000),
|
|
||||||
// curve: Curves.fastOutSlowIn,
|
|
||||||
// child: )
|
|
||||||
|
|
||||||
final transactionDateFormat = DateFormat('HH:mm');
|
|
||||||
final _themeChanger = Provider.of<ThemeChanger>(context);
|
|
||||||
final filterButton = Image.asset(
|
|
||||||
_themeChanger.getTheme() == Themes.darkTheme
|
|
||||||
? 'assets/images/filter_button.png'
|
|
||||||
: 'assets/images/filter_light_button.png',
|
|
||||||
height: 36);
|
|
||||||
|
|
||||||
return ClipRRect(
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(20), topRight: Radius.circular(20)),
|
|
||||||
child: Container(
|
|
||||||
color: Colors.white,
|
|
||||||
child: Column(children: [
|
|
||||||
Container(
|
|
||||||
padding:
|
|
||||||
EdgeInsets.only(top: 32, left: 20, right: 20, bottom: 20),
|
|
||||||
color: Theme.of(context).backgroundColor,
|
|
||||||
child: Stack(
|
|
||||||
children: <Widget>[
|
|
||||||
SizedBox(height: 37), // Force stack height
|
|
||||||
Center(
|
|
||||||
child: Text(S.of(context).transactions,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.primaryTextTheme
|
|
||||||
.title
|
|
||||||
.color))),
|
|
||||||
Positioned(
|
|
||||||
right: 0,
|
|
||||||
child: PopupMenuButton<int>(
|
|
||||||
itemBuilder: (context) => [
|
|
||||||
PopupMenuItem(
|
|
||||||
enabled: false,
|
|
||||||
value: -1,
|
|
||||||
child: Text(S.of(context).transactions,
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.primaryTextTheme
|
|
||||||
.caption
|
|
||||||
.color))),
|
|
||||||
// PopupMenuItem(
|
|
||||||
// value: 0,
|
|
||||||
// child: Observer(
|
|
||||||
// builder: (_) => Row(
|
|
||||||
// mainAxisAlignment:
|
|
||||||
// MainAxisAlignment
|
|
||||||
// .spaceBetween,
|
|
||||||
// children: [
|
|
||||||
// Text(S.of(context).incoming),
|
|
||||||
// Checkbox(
|
|
||||||
// value: actionListStore
|
|
||||||
// .transactionFilterStore
|
|
||||||
// .displayIncoming,
|
|
||||||
// onChanged: (value) =>
|
|
||||||
// actionListStore
|
|
||||||
// .transactionFilterStore
|
|
||||||
// .toggleIncoming(),
|
|
||||||
// )
|
|
||||||
// ]))),
|
|
||||||
// PopupMenuItem(
|
|
||||||
// value: 1,
|
|
||||||
// child: Observer(
|
|
||||||
// builder: (_) => Row(
|
|
||||||
// mainAxisAlignment:
|
|
||||||
// MainAxisAlignment
|
|
||||||
// .spaceBetween,
|
|
||||||
// children: [
|
|
||||||
// Text(S.of(context).outgoing),
|
|
||||||
// Checkbox(
|
|
||||||
// value: actionListStore
|
|
||||||
// .transactionFilterStore
|
|
||||||
// .displayOutgoing,
|
|
||||||
// onChanged: (value) =>
|
|
||||||
// actionListStore
|
|
||||||
// .transactionFilterStore
|
|
||||||
// .toggleOutgoing(),
|
|
||||||
// )
|
|
||||||
// ]))),
|
|
||||||
PopupMenuItem(
|
|
||||||
value: 2,
|
|
||||||
child:
|
|
||||||
Text(S.of(context).transactions_by_date)),
|
|
||||||
PopupMenuDivider(),
|
|
||||||
PopupMenuItem(
|
|
||||||
enabled: false,
|
|
||||||
value: -1,
|
|
||||||
child: Text(S.of(context).trades,
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.primaryTextTheme
|
|
||||||
.caption
|
|
||||||
.color))),
|
|
||||||
PopupMenuItem(
|
|
||||||
value: 3,
|
|
||||||
child: Observer(
|
|
||||||
builder: (_) => Row(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text('XMR.TO'),
|
|
||||||
// Checkbox(
|
|
||||||
// value: actionListStore
|
|
||||||
// .tradeFilterStore
|
|
||||||
// .displayXMRTO,
|
|
||||||
// onChanged: (value) =>
|
|
||||||
// actionListStore
|
|
||||||
// .tradeFilterStore
|
|
||||||
// .toggleDisplayExchange(
|
|
||||||
// ExchangeProviderDescription
|
|
||||||
// .xmrto),
|
|
||||||
// )
|
|
||||||
]))),
|
|
||||||
PopupMenuItem(
|
|
||||||
value: 4,
|
|
||||||
child: Observer(
|
|
||||||
builder: (_) => Row(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text('Change.NOW'),
|
|
||||||
// Checkbox(
|
|
||||||
// value: actionListStore
|
|
||||||
// .tradeFilterStore
|
|
||||||
// .displayChangeNow,
|
|
||||||
// onChanged: (value) =>
|
|
||||||
// actionListStore
|
|
||||||
// .tradeFilterStore
|
|
||||||
// .toggleDisplayExchange(
|
|
||||||
// ExchangeProviderDescription
|
|
||||||
// .changeNow),
|
|
||||||
// )
|
|
||||||
]))),
|
|
||||||
PopupMenuItem(
|
|
||||||
value: 5,
|
|
||||||
child: Observer(
|
|
||||||
builder: (_) => Row(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text('MorphToken'),
|
|
||||||
// Checkbox(
|
|
||||||
// value: actionListStore
|
|
||||||
// .tradeFilterStore
|
|
||||||
// .displayMorphToken,
|
|
||||||
// onChanged: (value) =>
|
|
||||||
// actionListStore
|
|
||||||
// .tradeFilterStore
|
|
||||||
// .toggleDisplayExchange(
|
|
||||||
// ExchangeProviderDescription
|
|
||||||
// .morphToken),
|
|
||||||
// )
|
|
||||||
])))
|
|
||||||
],
|
|
||||||
child: filterButton,
|
|
||||||
onSelected: (item) async {
|
|
||||||
if (item == 2) {
|
|
||||||
final picked =
|
|
||||||
await date_rage_picker.showDatePicker(
|
|
||||||
context: context,
|
|
||||||
initialFirstDate: DateTime.now()
|
|
||||||
.subtract(Duration(days: 1)),
|
|
||||||
initialLastDate: (DateTime.now()),
|
|
||||||
firstDate: DateTime(2015),
|
|
||||||
lastDate: DateTime.now()
|
|
||||||
.add(Duration(days: 1)));
|
|
||||||
|
|
||||||
if (picked != null && picked.length == 2) {
|
|
||||||
// actionListStore.transactionFilterStore
|
|
||||||
// .changeStartDate(picked.first);
|
|
||||||
// actionListStore.transactionFilterStore
|
|
||||||
// .changeEndDate(picked.last);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
widget.dashboardViewModel.transactions?.isNotEmpty ?? false
|
|
||||||
? ListView.separated(
|
|
||||||
physics: NeverScrollableScrollPhysics(),
|
|
||||||
shrinkWrap: true,
|
|
||||||
itemCount: widget.dashboardViewModel.transactions.length,
|
|
||||||
itemBuilder: (_, index) {
|
|
||||||
final item =
|
|
||||||
widget.dashboardViewModel.transactions[index];
|
|
||||||
|
|
||||||
if (item is DateSectionItem) {
|
|
||||||
return DateSectionRaw(date: item.date);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item is TransactionListItem) {
|
|
||||||
final transaction = item.transaction;
|
|
||||||
final savedDisplayMode = BalanceDisplayMode.all;
|
|
||||||
//settingsStore
|
|
||||||
// .balanceDisplayMode;
|
|
||||||
final formattedAmount = savedDisplayMode ==
|
|
||||||
BalanceDisplayMode.hiddenBalance
|
|
||||||
? '---'
|
|
||||||
: transaction.amountFormatted();
|
|
||||||
final formattedFiatAmount = savedDisplayMode ==
|
|
||||||
BalanceDisplayMode.hiddenBalance
|
|
||||||
? '---'
|
|
||||||
: transaction.fiatAmount(); // symbol ???
|
|
||||||
|
|
||||||
return TransactionRow(
|
|
||||||
onTap: () => Navigator.of(context).pushNamed(
|
|
||||||
Routes.transactionDetails,
|
|
||||||
arguments: transaction),
|
|
||||||
direction: transaction.direction,
|
|
||||||
formattedDate: transactionDateFormat
|
|
||||||
.format(transaction.date),
|
|
||||||
formattedAmount: formattedAmount,
|
|
||||||
formattedFiatAmount: formattedFiatAmount,
|
|
||||||
isPending: transaction.isPending);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item is TradeListItem) {
|
|
||||||
final trade = item.trade;
|
|
||||||
final savedDisplayMode = BalanceDisplayMode.all;
|
|
||||||
//settingsStore
|
|
||||||
// .balanceDisplayMode;
|
|
||||||
final formattedAmount = trade.amount != null
|
|
||||||
? savedDisplayMode ==
|
|
||||||
BalanceDisplayMode.hiddenBalance
|
|
||||||
? '---'
|
|
||||||
: trade.amountFormatted()
|
|
||||||
: trade.amount;
|
|
||||||
|
|
||||||
return TradeRow(
|
|
||||||
onTap: () => Navigator.of(context).pushNamed(
|
|
||||||
Routes.tradeDetails,
|
|
||||||
arguments: trade),
|
|
||||||
provider: trade.provider,
|
|
||||||
from: trade.from,
|
|
||||||
to: trade.to,
|
|
||||||
createdAtFormattedDate:
|
|
||||||
transactionDateFormat.format(trade.createdAt),
|
|
||||||
formattedAmount: formattedAmount);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Container(
|
|
||||||
color: Theme.of(context).backgroundColor,
|
|
||||||
height: 1);
|
|
||||||
},
|
|
||||||
separatorBuilder: (_, __) =>
|
|
||||||
Container(height: 14, color: Colors.white),
|
|
||||||
)
|
|
||||||
: Padding(
|
|
||||||
padding: EdgeInsets.all(20),
|
|
||||||
child: Text('Your transactions will be displayed here!',
|
|
||||||
style: TextStyle(color: Colors.grey)))
|
|
||||||
]))); //,
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +1,16 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
|
import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
|
||||||
import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
|
import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
|
||||||
|
import 'package:cake_wallet/palette.dart';
|
||||||
|
|
||||||
class TradeRow extends StatelessWidget {
|
class TradeRow extends StatelessWidget {
|
||||||
TradeRow(
|
TradeRow({
|
||||||
{this.provider,
|
this.provider,
|
||||||
this.from,
|
this.from,
|
||||||
this.to,
|
this.to,
|
||||||
this.createdAtFormattedDate,
|
this.createdAtFormattedDate,
|
||||||
this.formattedAmount,
|
this.formattedAmount,
|
||||||
@required this.onTap});
|
@required this.onTap});
|
||||||
|
|
||||||
final VoidCallback onTap;
|
final VoidCallback onTap;
|
||||||
final ExchangeProviderDescription provider;
|
final ExchangeProviderDescription provider;
|
||||||
|
@ -25,58 +26,53 @@ class TradeRow extends StatelessWidget {
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 60,
|
height: 52,
|
||||||
decoration: BoxDecoration(
|
color: Colors.transparent,
|
||||||
color: Theme.of(context).backgroundColor,
|
padding: EdgeInsets.only(left: 24, right: 24),
|
||||||
border: Border.all(
|
child: Row(
|
||||||
width: 1,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
color: Theme.of(context).backgroundColor
|
children: <Widget>[
|
||||||
),
|
_getPoweredImage(provider),
|
||||||
),
|
Expanded(
|
||||||
padding: EdgeInsets.only(top: 5, bottom: 5, left: 20, right: 20),
|
child: Padding(
|
||||||
child: Row(children: <Widget>[
|
padding: const EdgeInsets.only(left: 12),
|
||||||
Container(
|
child: Container(
|
||||||
height: 36,
|
height: 46,
|
||||||
width: 36,
|
child: Column(
|
||||||
decoration: BoxDecoration(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
shape: BoxShape.circle,
|
mainAxisSize: MainAxisSize.max,
|
||||||
color: Theme.of(context).backgroundColor
|
children: <Widget>[
|
||||||
),
|
Row(
|
||||||
child: _getPoweredImage(provider),
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
),
|
children: <Widget>[
|
||||||
Expanded(
|
Text('${from.toString()} → ${to.toString()}',
|
||||||
child: Padding(
|
style: TextStyle(
|
||||||
padding: const EdgeInsets.only(left: 10),
|
fontSize: 16,
|
||||||
child: Column(
|
fontWeight: FontWeight.w500,
|
||||||
children: <Widget>[
|
color: Colors.white
|
||||||
Row(
|
)),
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
formattedAmount != null
|
||||||
children: <Widget>[
|
? Text(formattedAmount + ' ' + amountCrypto,
|
||||||
Text('${from.toString()} → ${to.toString()}',
|
style: TextStyle(
|
||||||
style: TextStyle(
|
fontSize: 16,
|
||||||
fontSize: 16,
|
fontWeight: FontWeight.w500,
|
||||||
color: Theme.of(context).primaryTextTheme.title.color
|
color: Colors.white
|
||||||
)),
|
))
|
||||||
formattedAmount != null
|
: Container()
|
||||||
? Text(formattedAmount + ' ' + amountCrypto,
|
]),
|
||||||
style: TextStyle(
|
Row(
|
||||||
fontSize: 16,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
color: Theme.of(context).primaryTextTheme.title.color
|
children: <Widget>[
|
||||||
))
|
Text(createdAtFormattedDate,
|
||||||
: Container()
|
style: TextStyle(
|
||||||
]),
|
fontSize: 14,
|
||||||
SizedBox(height: 5),
|
color: PaletteDark.darkCyanBlue))
|
||||||
Row(
|
]),
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
],
|
||||||
children: <Widget>[
|
),
|
||||||
Text(createdAtFormattedDate,
|
),
|
||||||
style: TextStyle(
|
))
|
||||||
fontSize: 14, color: Theme.of(context).primaryTextTheme.headline.color))
|
]),
|
||||||
]),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
))
|
|
||||||
]),
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,17 +80,17 @@ class TradeRow extends StatelessWidget {
|
||||||
Image image;
|
Image image;
|
||||||
switch (provider) {
|
switch (provider) {
|
||||||
case ExchangeProviderDescription.xmrto:
|
case ExchangeProviderDescription.xmrto:
|
||||||
image = Image.asset('assets/images/xmr_btc.png');
|
image = Image.asset('assets/images/xmrto.png', height: 36, width: 36);
|
||||||
break;
|
break;
|
||||||
case ExchangeProviderDescription.changeNow:
|
case ExchangeProviderDescription.changeNow:
|
||||||
image = Image.asset('assets/images/change_now.png');
|
image = Image.asset('assets/images/changenow.png', height: 36, width: 36);
|
||||||
break;
|
break;
|
||||||
case ExchangeProviderDescription.morphToken:
|
case ExchangeProviderDescription.morphToken:
|
||||||
image = Image.asset('assets/images/morph_icon.png');
|
image = Image.asset('assets/images/morph.png', height: 36, width: 36);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
image = null;
|
image = null;
|
||||||
}
|
}
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,13 +4,13 @@ import 'package:cake_wallet/src/domain/common/transaction_direction.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
|
||||||
class TransactionRow extends StatelessWidget {
|
class TransactionRow extends StatelessWidget {
|
||||||
TransactionRow(
|
TransactionRow({
|
||||||
{this.direction,
|
this.direction,
|
||||||
this.formattedDate,
|
this.formattedDate,
|
||||||
this.formattedAmount,
|
this.formattedAmount,
|
||||||
this.formattedFiatAmount,
|
this.formattedFiatAmount,
|
||||||
this.isPending,
|
this.isPending,
|
||||||
@required this.onTap});
|
@required this.onTap});
|
||||||
|
|
||||||
final VoidCallback onTap;
|
final VoidCallback onTap;
|
||||||
final TransactionDirection direction;
|
final TransactionDirection direction;
|
||||||
|
@ -24,78 +24,74 @@ class TransactionRow extends StatelessWidget {
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 41,
|
height: 52,
|
||||||
color: Theme.of(context).backgroundColor,
|
color: Colors.transparent,
|
||||||
padding: EdgeInsets.only(left: 20, right: 20),
|
padding: EdgeInsets.only(left: 24, right: 24),
|
||||||
child: Row(children: <Widget>[
|
child: Row(
|
||||||
Container(
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
height: 36,
|
children: <Widget>[
|
||||||
width: 36,
|
Container(
|
||||||
decoration: BoxDecoration(
|
height: 36,
|
||||||
shape: BoxShape.circle,
|
width: 36,
|
||||||
color: Theme.of(context).primaryTextTheme.display3.color),
|
decoration: BoxDecoration(
|
||||||
child: Image.asset(direction == TransactionDirection.incoming
|
shape: BoxShape.circle,
|
||||||
? 'assets/images/down_arrow.png'
|
color: PaletteDark.wildNightBlue
|
||||||
: 'assets/images/up_arrow.png'),
|
),
|
||||||
),
|
child: Image.asset(
|
||||||
Expanded(
|
direction == TransactionDirection.incoming
|
||||||
child: Padding(
|
? 'assets/images/down_arrow.png'
|
||||||
padding: const EdgeInsets.only(left: 10),
|
: 'assets/images/up_arrow.png'),
|
||||||
child: Column(
|
),
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
Expanded(
|
||||||
children: <Widget>[
|
child: Padding(
|
||||||
Row(
|
padding: const EdgeInsets.only(left: 12),
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
child: Container(
|
||||||
children: <Widget>[
|
height: 46,
|
||||||
Text(
|
child: Column(
|
||||||
(direction == TransactionDirection.incoming
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
? S.of(context).received
|
mainAxisSize: MainAxisSize.max,
|
||||||
: S.of(context).sent) +
|
children: <Widget>[
|
||||||
(isPending ? S.of(context).pending : ''),
|
Row(
|
||||||
style: TextStyle(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
fontSize: 16,
|
children: <Widget>[
|
||||||
fontWeight: FontWeight.w500,
|
Text(
|
||||||
color: Theme.of(context)
|
(direction == TransactionDirection.incoming
|
||||||
.primaryTextTheme
|
? S.of(context).received
|
||||||
.title
|
: S.of(context).sent) +
|
||||||
.color)),
|
(isPending ? S.of(context).pending : ''),
|
||||||
Text(
|
style: TextStyle(
|
||||||
direction == TransactionDirection.incoming
|
fontSize: 16,
|
||||||
? formattedAmount
|
fontWeight: FontWeight.w500,
|
||||||
: '- ' + formattedAmount,
|
color: Colors.white
|
||||||
style: TextStyle(
|
)),
|
||||||
fontSize: 16,
|
Text(direction == TransactionDirection.incoming
|
||||||
fontWeight: FontWeight.w500,
|
? formattedAmount
|
||||||
color: Theme.of(context)
|
: '- ' + formattedAmount,
|
||||||
.primaryTextTheme
|
style: TextStyle(
|
||||||
.title
|
fontSize: 16,
|
||||||
.color))
|
fontWeight: FontWeight.w500,
|
||||||
]),
|
color: Colors.white
|
||||||
Row(
|
))
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
]),
|
||||||
children: <Widget>[
|
Row(
|
||||||
Text(formattedDate,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
style: TextStyle(
|
children: <Widget>[
|
||||||
fontSize: 14,
|
Text(formattedDate,
|
||||||
color: Theme.of(context)
|
style: TextStyle(
|
||||||
.primaryTextTheme
|
fontSize: 14,
|
||||||
.headline
|
color: PaletteDark.darkCyanBlue)),
|
||||||
.color)),
|
Text(direction == TransactionDirection.incoming
|
||||||
Text(
|
? formattedFiatAmount
|
||||||
direction == TransactionDirection.incoming
|
: '- ' + formattedFiatAmount,
|
||||||
? formattedFiatAmount
|
style: TextStyle(
|
||||||
: '- ' + formattedFiatAmount,
|
fontSize: 14,
|
||||||
style: TextStyle(
|
color: PaletteDark.darkCyanBlue))
|
||||||
fontSize: 14,
|
]),
|
||||||
color: Theme.of(context)
|
],
|
||||||
.primaryTextTheme
|
),
|
||||||
.headline
|
),
|
||||||
.color))
|
))
|
||||||
]),
|
]),
|
||||||
],
|
|
||||||
),
|
|
||||||
))
|
|
||||||
]),
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
98
lib/src/screens/dashboard/widgets/transactions_page.dart
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||||
|
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/dashboard/widgets/header_row.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/dashboard/widgets/date_section_raw.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/dashboard/widgets/trade_row.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/dashboard/widgets/transaction_raw.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/date_section_item.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:cake_wallet/routes.dart';
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
|
||||||
|
class TransactionsPage extends StatelessWidget {
|
||||||
|
TransactionsPage({@required this.dashboardViewModel});
|
||||||
|
|
||||||
|
final DashboardViewModel dashboardViewModel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: 24,
|
||||||
|
bottom: 24
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: <Widget>[
|
||||||
|
HeaderRow(dashboardViewModel: dashboardViewModel),
|
||||||
|
Expanded(
|
||||||
|
child: Observer(
|
||||||
|
builder: (_) {
|
||||||
|
final items = dashboardViewModel.items;
|
||||||
|
|
||||||
|
return items?.isNotEmpty ?? false
|
||||||
|
? ListView.builder(
|
||||||
|
itemCount: items.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
|
||||||
|
final item = items[index];
|
||||||
|
|
||||||
|
if (item is DateSectionItem) {
|
||||||
|
return DateSectionRaw(date: item.date);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item is TransactionListItem) {
|
||||||
|
final transaction = item.transaction;
|
||||||
|
|
||||||
|
return TransactionRow(
|
||||||
|
onTap: () => Navigator.of(context).pushNamed(
|
||||||
|
Routes.transactionDetails,
|
||||||
|
arguments: transaction),
|
||||||
|
direction: transaction.direction,
|
||||||
|
formattedDate: DateFormat('HH:mm')
|
||||||
|
.format(transaction.date),
|
||||||
|
formattedAmount: item.formattedCryptoAmount,
|
||||||
|
formattedFiatAmount: item.formattedFiatAmount,
|
||||||
|
isPending: transaction.isPending);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item is TradeListItem) {
|
||||||
|
final trade = item.trade;
|
||||||
|
|
||||||
|
return TradeRow(
|
||||||
|
onTap: () => Navigator.of(context).pushNamed(
|
||||||
|
Routes.tradeDetails,
|
||||||
|
arguments: trade),
|
||||||
|
provider: trade.provider,
|
||||||
|
from: trade.from,
|
||||||
|
to: trade.to,
|
||||||
|
createdAtFormattedDate:
|
||||||
|
DateFormat('HH:mm').format(trade.createdAt),
|
||||||
|
formattedAmount: item.tradeFormattedAmount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
color: Theme.of(context).backgroundColor,
|
||||||
|
height: 1);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
: Center(
|
||||||
|
child: Text(
|
||||||
|
S.of(context).placeholder_transactions,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.grey
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,508 +0,0 @@
|
||||||
import 'dart:async';
|
|
||||||
import 'package:cake_wallet/palette.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
|
||||||
import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
|
|
||||||
import 'package:cake_wallet/src/stores/settings/settings_store.dart';
|
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
|
||||||
import 'package:cake_wallet/src/domain/common/sync_status.dart';
|
|
||||||
import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart';
|
|
||||||
import 'package:cake_wallet/routes.dart';
|
|
||||||
import 'package:cake_wallet/view_model/dashboard_view_model.dart';
|
|
||||||
|
|
||||||
class WalletCard extends StatefulWidget {
|
|
||||||
WalletCard({this.walletVM});
|
|
||||||
|
|
||||||
final DashboardViewModel walletVM;
|
|
||||||
|
|
||||||
@override
|
|
||||||
WalletCardState createState() => WalletCardState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class WalletCardState extends State<WalletCard> {
|
|
||||||
final _syncingObserverKey = GlobalKey();
|
|
||||||
final _balanceObserverKey = GlobalKey();
|
|
||||||
final _addressObserverKey = GlobalKey();
|
|
||||||
|
|
||||||
double cardWidth;
|
|
||||||
double cardHeight;
|
|
||||||
double screenWidth;
|
|
||||||
double opacity;
|
|
||||||
bool isDraw;
|
|
||||||
bool isFrontSide;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
cardWidth = 0;
|
|
||||||
cardHeight = 220;
|
|
||||||
screenWidth = 0;
|
|
||||||
opacity = 0;
|
|
||||||
isDraw = false;
|
|
||||||
isFrontSide = true;
|
|
||||||
super.initState();
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback(afterLayout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void afterLayout(dynamic _) {
|
|
||||||
screenWidth = MediaQuery.of(context).size.width - 20;
|
|
||||||
setState(() {
|
|
||||||
cardWidth = screenWidth;
|
|
||||||
opacity = 1;
|
|
||||||
});
|
|
||||||
Timer(Duration(milliseconds: 500), () => setState(() => isDraw = true));
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final colorsSync = [
|
|
||||||
Theme.of(context).cardTheme.color,
|
|
||||||
Theme.of(context).hoverColor
|
|
||||||
];
|
|
||||||
|
|
||||||
return Container(
|
|
||||||
width: double.infinity,
|
|
||||||
height: cardHeight,
|
|
||||||
alignment: Alignment.centerRight,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(14), bottomLeft: Radius.circular(14))),
|
|
||||||
child: AnimatedContainer(
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
width: cardWidth,
|
|
||||||
height: cardHeight,
|
|
||||||
duration: Duration(milliseconds: 500),
|
|
||||||
curve: Curves.fastOutSlowIn,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(14),
|
|
||||||
bottomLeft: Radius.circular(14)),
|
|
||||||
color: Theme.of(context).focusColor),
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(10), bottomLeft: Radius.circular(10)),
|
|
||||||
child: Container(
|
|
||||||
width: cardWidth,
|
|
||||||
height: cardHeight,
|
|
||||||
color: Theme.of(context).cardColor,
|
|
||||||
child: isFrontSide
|
|
||||||
? frontSide(colorsSync)
|
|
||||||
: InkWell(
|
|
||||||
onTap: () => setState(() => isFrontSide = true),
|
|
||||||
child: backSide(colorsSync)),
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget frontSide(List<Color> colorsSync) {
|
|
||||||
final settingsStore = Provider.of<SettingsStore>(context);
|
|
||||||
final triangleButton = Image.asset(
|
|
||||||
'assets/images/triangle.png',
|
|
||||||
color: Theme.of(context).primaryTextTheme.title.color,
|
|
||||||
);
|
|
||||||
|
|
||||||
return Observer(
|
|
||||||
key: _syncingObserverKey,
|
|
||||||
builder: (_) {
|
|
||||||
final status = widget.walletVM.status;
|
|
||||||
final statusText = status.title();
|
|
||||||
final progress = status.progress();
|
|
||||||
final indicatorOffset = progress * cardWidth;
|
|
||||||
final indicatorWidth =
|
|
||||||
progress <= 1 ? cardWidth - indicatorOffset : 0.0;
|
|
||||||
var descriptionText = '';
|
|
||||||
|
|
||||||
if (status is SyncingSyncStatus) {
|
|
||||||
descriptionText = S.of(context).Blocks_remaining(status.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status is FailedSyncStatus) {
|
|
||||||
descriptionText = S.of(context).please_try_to_connect_to_another_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Container(
|
|
||||||
width: cardWidth,
|
|
||||||
height: cardHeight,
|
|
||||||
color: Colors.white,
|
|
||||||
child: Stack(
|
|
||||||
children: <Widget>[
|
|
||||||
progress <= 1
|
|
||||||
? Positioned(
|
|
||||||
left: indicatorOffset,
|
|
||||||
top: 0,
|
|
||||||
bottom: 0,
|
|
||||||
child: Container(
|
|
||||||
width: indicatorWidth,
|
|
||||||
height: cardHeight,
|
|
||||||
color: Color.fromRGBO(227, 238, 249, 1),
|
|
||||||
))
|
|
||||||
: Offstage(),
|
|
||||||
isDraw
|
|
||||||
? Positioned(
|
|
||||||
left: 24,
|
|
||||||
right: 24,
|
|
||||||
top: 32,
|
|
||||||
bottom: 24,
|
|
||||||
child: Container(
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: <Widget>[
|
|
||||||
Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: <Widget>[
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: <Widget>[
|
|
||||||
InkWell(
|
|
||||||
onTap: () => Navigator.of(context)
|
|
||||||
.pushNamed(Routes.walletList),
|
|
||||||
child: Row(
|
|
||||||
children: <Widget>[
|
|
||||||
Text(
|
|
||||||
widget.walletVM.name,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.primaryTextTheme
|
|
||||||
.title
|
|
||||||
.color),
|
|
||||||
),
|
|
||||||
SizedBox(width: 10),
|
|
||||||
triangleButton
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 5),
|
|
||||||
if (widget.walletVM.subname?.isNotEmpty ??
|
|
||||||
false)
|
|
||||||
Text(
|
|
||||||
widget.walletVM.subname,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.primaryTextTheme
|
|
||||||
.caption
|
|
||||||
.color),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
onTap: () =>
|
|
||||||
setState(() => isFrontSide = false),
|
|
||||||
child: Container(
|
|
||||||
width: 98,
|
|
||||||
height: 32,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.accentTextTheme
|
|
||||||
.subtitle
|
|
||||||
.backgroundColor,
|
|
||||||
border: Border.all(
|
|
||||||
color: Color.fromRGBO(
|
|
||||||
219, 231, 237, 1)),
|
|
||||||
// FIXME
|
|
||||||
borderRadius: BorderRadius.all(
|
|
||||||
Radius.circular(16))),
|
|
||||||
child: Text(
|
|
||||||
'Receive',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.primaryTextTheme
|
|
||||||
.title
|
|
||||||
.color),
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
status is SyncedSyncStatus
|
|
||||||
? Observer(
|
|
||||||
key: _balanceObserverKey,
|
|
||||||
builder: (_) {
|
|
||||||
final balanceDisplayMode =
|
|
||||||
BalanceDisplayMode.availableBalance;
|
|
||||||
// settingsStore.balanceDisplayMode;
|
|
||||||
final symbol =
|
|
||||||
settingsStore.fiatCurrency.toString();
|
|
||||||
var balance = '---';
|
|
||||||
var fiatBalance = '---';
|
|
||||||
|
|
||||||
if (balanceDisplayMode ==
|
|
||||||
BalanceDisplayMode.availableBalance) {
|
|
||||||
balance = widget.walletVM.balance
|
|
||||||
.unlockedBalance ??
|
|
||||||
'0.0';
|
|
||||||
fiatBalance = '\$ 0.00';
|
|
||||||
// '$symbol ${balanceStore.fiatUnlockedBalance}';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (balanceDisplayMode ==
|
|
||||||
BalanceDisplayMode.fullBalance) {
|
|
||||||
balance = widget.walletVM.balance
|
|
||||||
.totalBalance ??
|
|
||||||
'0.0';
|
|
||||||
fiatBalance = '\$ 0.00';
|
|
||||||
// '$symbol ${balanceStore.fiatFullBalance}';
|
|
||||||
}
|
|
||||||
|
|
||||||
return Row(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment.end,
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
children: <Widget>[
|
|
||||||
Column(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment.start,
|
|
||||||
children: <Widget>[
|
|
||||||
Text(
|
|
||||||
balanceDisplayMode.toString(),
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.primaryTextTheme
|
|
||||||
.caption
|
|
||||||
.color),
|
|
||||||
),
|
|
||||||
SizedBox(height: 5),
|
|
||||||
Container(
|
|
||||||
height: 36,
|
|
||||||
child: Text(
|
|
||||||
balance,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 32,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.primaryTextTheme
|
|
||||||
.title
|
|
||||||
.color,
|
|
||||||
fontWeight:
|
|
||||||
FontWeight.bold),
|
|
||||||
))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
fiatBalance,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
// FIXME
|
|
||||||
// color: Theme.of(context)
|
|
||||||
// .primaryTextTheme
|
|
||||||
// .title
|
|
||||||
// .color,
|
|
||||||
color: Color.fromRGBO(
|
|
||||||
72, 89, 109, 1)),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
})
|
|
||||||
: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
children: <Widget>[
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment.start,
|
|
||||||
children: <Widget>[
|
|
||||||
Text(
|
|
||||||
statusText,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.primaryTextTheme
|
|
||||||
.caption
|
|
||||||
.color),
|
|
||||||
),
|
|
||||||
SizedBox(height: 5),
|
|
||||||
Text(
|
|
||||||
descriptionText,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.primaryTextTheme
|
|
||||||
.title
|
|
||||||
.color),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
))
|
|
||||||
: Offstage()
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget backSide(List<Color> colorsSync) {
|
|
||||||
final rightArrow = Image.asset('assets/images/right_arrow.png',
|
|
||||||
color: Theme.of(context).primaryTextTheme.title.color);
|
|
||||||
var messageBoxHeight = 0.0;
|
|
||||||
var messageBoxWidth = cardWidth - 10;
|
|
||||||
|
|
||||||
return Observer(
|
|
||||||
key: _addressObserverKey,
|
|
||||||
builder: (_) {
|
|
||||||
return Container(
|
|
||||||
width: cardWidth,
|
|
||||||
height: cardHeight,
|
|
||||||
alignment: Alignment.topCenter,
|
|
||||||
child: Stack(
|
|
||||||
alignment: Alignment.topRight,
|
|
||||||
children: <Widget>[
|
|
||||||
Container(
|
|
||||||
width: cardWidth,
|
|
||||||
height: cardHeight,
|
|
||||||
padding:
|
|
||||||
EdgeInsets.only(left: 24, right: 24, top: 32, bottom: 32),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(10),
|
|
||||||
bottomLeft: Radius.circular(10)),
|
|
||||||
gradient: LinearGradient(
|
|
||||||
colors: colorsSync,
|
|
||||||
begin: Alignment.topCenter,
|
|
||||||
end: Alignment.bottomCenter)),
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: <Widget>[
|
|
||||||
Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: <Widget>[
|
|
||||||
Expanded(
|
|
||||||
child: Container(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: <Widget>[
|
|
||||||
Text(
|
|
||||||
S.current.card_address,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.primaryTextTheme
|
|
||||||
.caption
|
|
||||||
.color),
|
|
||||||
),
|
|
||||||
SizedBox(height: 10),
|
|
||||||
GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
Clipboard.setData(ClipboardData(
|
|
||||||
text: widget.walletVM.address));
|
|
||||||
_addressObserverKey.currentState
|
|
||||||
.setState(() {
|
|
||||||
messageBoxHeight = 20;
|
|
||||||
messageBoxWidth = cardWidth;
|
|
||||||
});
|
|
||||||
Timer(Duration(milliseconds: 1000), () {
|
|
||||||
try {
|
|
||||||
_addressObserverKey.currentState
|
|
||||||
.setState(() {
|
|
||||||
messageBoxHeight = 0;
|
|
||||||
messageBoxWidth = cardWidth - 10;
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
print('${e.toString()}');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
widget.walletVM.address,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.primaryTextTheme
|
|
||||||
.title
|
|
||||||
.color),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
SizedBox(width: 10),
|
|
||||||
Container(
|
|
||||||
width: 90,
|
|
||||||
height: 90,
|
|
||||||
child: QrImage(
|
|
||||||
data: widget.walletVM.address,
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
foregroundColor: Theme.of(context)
|
|
||||||
.primaryTextTheme
|
|
||||||
.caption
|
|
||||||
.color),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
height: 44,
|
|
||||||
padding: EdgeInsets.only(left: 20, right: 20),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(22)),
|
|
||||||
color: Theme.of(context)
|
|
||||||
.primaryTextTheme
|
|
||||||
.overline
|
|
||||||
.color),
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () =>
|
|
||||||
Navigator.of(context, rootNavigator: true)
|
|
||||||
.pushNamed(Routes.receive),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: <Widget>[
|
|
||||||
Text(
|
|
||||||
S.of(context).addresses,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.primaryTextTheme
|
|
||||||
.title
|
|
||||||
.color),
|
|
||||||
),
|
|
||||||
rightArrow
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
AnimatedContainer(
|
|
||||||
width: messageBoxWidth,
|
|
||||||
height: messageBoxHeight,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
duration: Duration(milliseconds: 500),
|
|
||||||
curve: Curves.fastOutSlowIn,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.only(topLeft: Radius.circular(10)),
|
|
||||||
color: Colors.green),
|
|
||||||
child: Text(
|
|
||||||
S.of(context).copied_to_clipboard,
|
|
||||||
style: TextStyle(fontSize: 10, color: Colors.white),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
62
lib/store/dashboard/trade_filter_store.dart
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
import 'package:cake_wallet/core/wallet_base.dart';
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart';
|
||||||
|
|
||||||
|
part 'trade_filter_store.g.dart';
|
||||||
|
|
||||||
|
class TradeFilterStore = TradeFilterStoreBase with _$TradeFilterStore;
|
||||||
|
|
||||||
|
abstract class TradeFilterStoreBase with Store {
|
||||||
|
TradeFilterStoreBase(
|
||||||
|
{this.displayXMRTO = true,
|
||||||
|
this.displayChangeNow = true,
|
||||||
|
this.displayMorphToken = true,
|
||||||
|
this.wallet});
|
||||||
|
|
||||||
|
@observable
|
||||||
|
bool displayXMRTO;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
bool displayChangeNow;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
bool displayMorphToken;
|
||||||
|
|
||||||
|
WalletBase wallet;
|
||||||
|
|
||||||
|
@action
|
||||||
|
void toggleDisplayExchange(ExchangeProviderDescription provider) {
|
||||||
|
switch (provider) {
|
||||||
|
case ExchangeProviderDescription.changeNow:
|
||||||
|
displayChangeNow = !displayChangeNow;
|
||||||
|
break;
|
||||||
|
case ExchangeProviderDescription.xmrto:
|
||||||
|
displayXMRTO = !displayXMRTO;
|
||||||
|
break;
|
||||||
|
case ExchangeProviderDescription.morphToken:
|
||||||
|
displayMorphToken = !displayMorphToken;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TradeListItem> filtered({List<TradeListItem> trades}) {
|
||||||
|
final _trades =
|
||||||
|
trades.where((item) => item.trade.walletId == wallet.id).toList();
|
||||||
|
final needToFilter = !displayChangeNow || !displayXMRTO || !displayMorphToken;
|
||||||
|
|
||||||
|
return needToFilter
|
||||||
|
? trades
|
||||||
|
.where((item) =>
|
||||||
|
(displayXMRTO &&
|
||||||
|
item.trade.provider == ExchangeProviderDescription.xmrto) ||
|
||||||
|
(displayChangeNow &&
|
||||||
|
item.trade.provider ==
|
||||||
|
ExchangeProviderDescription.changeNow) ||
|
||||||
|
(displayMorphToken &&
|
||||||
|
item.trade.provider ==
|
||||||
|
ExchangeProviderDescription.morphToken))
|
||||||
|
.toList()
|
||||||
|
: _trades;
|
||||||
|
}
|
||||||
|
}
|
35
lib/store/dashboard/trades_store.dart
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:cake_wallet/src/domain/exchange/trade.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
|
import 'package:cake_wallet/store/settings_store.dart';
|
||||||
|
|
||||||
|
part 'trades_store.g.dart';
|
||||||
|
|
||||||
|
class TradesStore = TradesStoreBase with _$TradesStore;
|
||||||
|
|
||||||
|
abstract class TradesStoreBase with Store {
|
||||||
|
TradesStoreBase({this.tradesSource, this.settingsStore}) {
|
||||||
|
trades = <TradeListItem>[];
|
||||||
|
|
||||||
|
_onTradesChanged =
|
||||||
|
tradesSource.watch().listen((_) async => await updateTradeList());
|
||||||
|
|
||||||
|
updateTradeList();
|
||||||
|
}
|
||||||
|
|
||||||
|
Box<Trade> tradesSource;
|
||||||
|
StreamSubscription<BoxEvent> _onTradesChanged;
|
||||||
|
SettingsStore settingsStore;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
List<TradeListItem> trades;
|
||||||
|
|
||||||
|
@action
|
||||||
|
Future updateTradeList() async => trades =
|
||||||
|
tradesSource.values.map((trade) => TradeListItem(
|
||||||
|
trade: trade,
|
||||||
|
displayMode: settingsStore.balanceDisplayMode)).toList();
|
||||||
|
}
|
69
lib/store/dashboard/transaction_filter_store.dart
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/common/transaction_direction.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart';
|
||||||
|
|
||||||
|
part 'transaction_filter_store.g.dart';
|
||||||
|
|
||||||
|
class TransactionFilterStore = TransactionFilterStoreBase
|
||||||
|
with _$TransactionFilterStore;
|
||||||
|
|
||||||
|
abstract class TransactionFilterStoreBase with Store {
|
||||||
|
TransactionFilterStoreBase(
|
||||||
|
{this.displayIncoming = true, this.displayOutgoing = true});
|
||||||
|
|
||||||
|
@observable
|
||||||
|
bool displayIncoming;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
bool displayOutgoing;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
DateTime startDate;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
DateTime endDate;
|
||||||
|
|
||||||
|
@action
|
||||||
|
void toggleIncoming() => displayIncoming = !displayIncoming;
|
||||||
|
|
||||||
|
@action
|
||||||
|
void toggleOutgoing() => displayOutgoing = !displayOutgoing;
|
||||||
|
|
||||||
|
@action
|
||||||
|
void changeStartDate(DateTime date) => startDate = date;
|
||||||
|
|
||||||
|
@action
|
||||||
|
void changeEndDate(DateTime date) => endDate = date;
|
||||||
|
|
||||||
|
List<TransactionListItem> filtered({List<TransactionListItem> transactions}) {
|
||||||
|
var _transactions = <TransactionListItem>[];
|
||||||
|
final needToFilter = !displayOutgoing ||
|
||||||
|
!displayIncoming ||
|
||||||
|
(startDate != null && endDate != null);
|
||||||
|
|
||||||
|
if (needToFilter) {
|
||||||
|
_transactions = transactions.where((item) {
|
||||||
|
var allowed = true;
|
||||||
|
|
||||||
|
if (allowed && startDate != null && endDate != null) {
|
||||||
|
allowed = startDate.isBefore(item.transaction.date) &&
|
||||||
|
endDate.isAfter(item.transaction.date);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allowed && (!displayOutgoing || !displayIncoming)) {
|
||||||
|
allowed = (displayOutgoing &&
|
||||||
|
item.transaction.direction ==
|
||||||
|
TransactionDirection.outgoing) ||
|
||||||
|
(displayIncoming &&
|
||||||
|
item.transaction.direction == TransactionDirection.incoming);
|
||||||
|
}
|
||||||
|
|
||||||
|
return allowed;
|
||||||
|
}).toList();
|
||||||
|
} else {
|
||||||
|
_transactions = transactions;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _transactions;
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ import 'palette.dart';
|
||||||
class Themes {
|
class Themes {
|
||||||
|
|
||||||
static final ThemeData lightTheme = ThemeData(
|
static final ThemeData lightTheme = ThemeData(
|
||||||
fontFamily: 'Avenir Next',
|
fontFamily: 'Poppins',
|
||||||
brightness: Brightness.light,
|
brightness: Brightness.light,
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
focusColor: Colors.white, // wallet card border
|
focusColor: Colors.white, // wallet card border
|
||||||
|
@ -73,7 +73,7 @@ class Themes {
|
||||||
|
|
||||||
|
|
||||||
static final ThemeData darkTheme = ThemeData(
|
static final ThemeData darkTheme = ThemeData(
|
||||||
fontFamily: 'Avenir Next',
|
fontFamily: 'Poppins',
|
||||||
brightness: Brightness.dark,
|
brightness: Brightness.dark,
|
||||||
backgroundColor: PaletteDark.darkNightBlue,
|
backgroundColor: PaletteDark.darkNightBlue,
|
||||||
focusColor: PaletteDark.lightDistantBlue, // wallet card border
|
focusColor: PaletteDark.lightDistantBlue, // wallet card border
|
||||||
|
|
32
lib/view_model/dashboard/action_list_display_mode.dart
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
enum ActionListDisplayMode { transactions, trades }
|
||||||
|
|
||||||
|
int serializeActionlistDisplayModes(List<ActionListDisplayMode> modes) {
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
|
for (final mode in modes) {
|
||||||
|
switch (mode) {
|
||||||
|
case ActionListDisplayMode.trades:
|
||||||
|
i += 1;
|
||||||
|
break;
|
||||||
|
case ActionListDisplayMode.transactions:
|
||||||
|
i += 10;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ActionListDisplayMode> deserializeActionlistDisplayModes(int raw) {
|
||||||
|
final modes = List<ActionListDisplayMode>();
|
||||||
|
|
||||||
|
if (raw == 1 || raw - 10 == 1) {
|
||||||
|
modes.add(ActionListDisplayMode.trades);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (raw >= 10) {
|
||||||
|
modes.add(ActionListDisplayMode.transactions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return modes;
|
||||||
|
}
|
3
lib/view_model/dashboard/action_list_item.dart
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
abstract class ActionListItem {
|
||||||
|
DateTime get date;
|
||||||
|
}
|
115
lib/view_model/dashboard/balance_view_model.dart
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart';
|
||||||
|
import 'package:cake_wallet/core/wallet_base.dart';
|
||||||
|
import 'package:cake_wallet/monero/monero_wallet.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/common/calculate_fiat_amount.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/wallet_balance.dart';
|
||||||
|
import 'package:cake_wallet/store/settings_store.dart';
|
||||||
|
import 'package:cake_wallet/src/stores/price/price_store.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
|
|
||||||
|
part 'balance_view_model.g.dart';
|
||||||
|
|
||||||
|
class BalanceViewModel = BalanceViewModelBase with _$BalanceViewModel;
|
||||||
|
|
||||||
|
abstract class BalanceViewModelBase with Store {
|
||||||
|
BalanceViewModelBase({
|
||||||
|
@required this.wallet,
|
||||||
|
@required this.settingsStore,
|
||||||
|
@required this.priceStore
|
||||||
|
});
|
||||||
|
|
||||||
|
final WalletBase wallet;
|
||||||
|
final SettingsStore settingsStore;
|
||||||
|
final PriceStore priceStore;
|
||||||
|
|
||||||
|
WalletBalance _getWalletBalance() {
|
||||||
|
final _wallet = wallet;
|
||||||
|
|
||||||
|
if (_wallet is MoneroWallet) {
|
||||||
|
return WalletBalance(
|
||||||
|
unlockedBalance: _wallet.balance.formattedUnlockedBalance,
|
||||||
|
totalBalance: _wallet.balance.formattedFullBalance);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_wallet is BitcoinWallet) {
|
||||||
|
return WalletBalance(
|
||||||
|
unlockedBalance: _wallet.balance.confirmedFormatted,
|
||||||
|
totalBalance: _wallet.balance.unconfirmedFormatted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String _getFiatBalance({double price, String cryptoAmount}) {
|
||||||
|
if (cryptoAmount == null) {
|
||||||
|
return '0.00';
|
||||||
|
}
|
||||||
|
|
||||||
|
return calculateFiatAmount(price: price, cryptoAmount: cryptoAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed
|
||||||
|
double get price {
|
||||||
|
String symbol;
|
||||||
|
final _wallet = wallet;
|
||||||
|
|
||||||
|
if (_wallet is MoneroWallet) {
|
||||||
|
symbol = PriceStoreBase.generateSymbolForPair(
|
||||||
|
fiat: settingsStore.fiatCurrency, crypto: CryptoCurrency.xmr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_wallet is BitcoinWallet) {
|
||||||
|
symbol = PriceStoreBase.generateSymbolForPair(
|
||||||
|
fiat: settingsStore.fiatCurrency, crypto: CryptoCurrency.btc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return priceStore.prices[symbol];
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed
|
||||||
|
String get cryptoBalance {
|
||||||
|
final walletBalance = _getWalletBalance();
|
||||||
|
final displayMode = settingsStore.balanceDisplayMode;
|
||||||
|
var balance = '---';
|
||||||
|
|
||||||
|
if (displayMode == BalanceDisplayMode.availableBalance) {
|
||||||
|
balance = walletBalance.unlockedBalance ?? '0.0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (displayMode == BalanceDisplayMode.fullBalance) {
|
||||||
|
balance = walletBalance.totalBalance ?? '0.0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed
|
||||||
|
String get fiatBalance {
|
||||||
|
final walletBalance = _getWalletBalance();
|
||||||
|
final displayMode = settingsStore.balanceDisplayMode;
|
||||||
|
final fiatCurrency = settingsStore.fiatCurrency;
|
||||||
|
var balance = '---';
|
||||||
|
|
||||||
|
final totalBalance = _getFiatBalance(
|
||||||
|
price: price,
|
||||||
|
cryptoAmount: walletBalance.totalBalance
|
||||||
|
);
|
||||||
|
|
||||||
|
final unlockedBalance = _getFiatBalance(
|
||||||
|
price: price,
|
||||||
|
cryptoAmount: walletBalance.unlockedBalance
|
||||||
|
);
|
||||||
|
|
||||||
|
if (displayMode == BalanceDisplayMode.availableBalance) {
|
||||||
|
balance = fiatCurrency.toString() + ' ' + unlockedBalance ?? '0.00';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (displayMode == BalanceDisplayMode.fullBalance) {
|
||||||
|
balance = fiatCurrency.toString() + ' ' + totalBalance ?? '0.00';
|
||||||
|
}
|
||||||
|
|
||||||
|
return balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
145
lib/view_model/dashboard/dashboard_view_model.dart
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
import 'package:cake_wallet/bitcoin/bitcoin_transaction_info.dart';
|
||||||
|
import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart';
|
||||||
|
import 'package:cake_wallet/monero/monero_wallet.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/common/transaction_direction.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/common/transaction_info.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/exchange/trade.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/action_list_item.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/action_list_display_mode.dart';
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
|
import 'package:cake_wallet/core/wallet_base.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/common/sync_status.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||||
|
import 'package:cake_wallet/store/app_store.dart';
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:cake_wallet/store/dashboard/trades_store.dart';
|
||||||
|
import 'package:cake_wallet/store/dashboard/trade_filter_store.dart';
|
||||||
|
import 'package:cake_wallet/store/dashboard/transaction_filter_store.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/formatted_item_list.dart';
|
||||||
|
|
||||||
|
part 'dashboard_view_model.g.dart';
|
||||||
|
|
||||||
|
class DashboardViewModel = DashboardViewModelBase with _$DashboardViewModel;
|
||||||
|
|
||||||
|
abstract class DashboardViewModelBase with Store {
|
||||||
|
DashboardViewModelBase({
|
||||||
|
this.balanceViewModel,
|
||||||
|
this.appStore,
|
||||||
|
this.tradesStore,
|
||||||
|
this.tradeFilterStore,
|
||||||
|
this.transactionFilterStore}) {
|
||||||
|
|
||||||
|
name = appStore.wallet?.name;
|
||||||
|
wallet ??= appStore.wallet;
|
||||||
|
type = wallet.type;
|
||||||
|
|
||||||
|
transactions = ObservableList.of(wallet.transactionHistory.transactions
|
||||||
|
.map((transaction) => TransactionListItem(
|
||||||
|
transaction: transaction,
|
||||||
|
price: price,
|
||||||
|
fiatCurrency: appStore.settingsStore.fiatCurrency,
|
||||||
|
displayMode: balanceDisplayMode)));
|
||||||
|
|
||||||
|
_reaction = reaction((_) => appStore.wallet, _onWalletChange);
|
||||||
|
|
||||||
|
final _wallet = wallet;
|
||||||
|
|
||||||
|
if (_wallet is MoneroWallet) {
|
||||||
|
subname = _wallet.account?.label;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPage = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@observable
|
||||||
|
WalletType type;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
String name;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
double currentPage;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
ObservableList<TransactionListItem> transactions;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
String subname;
|
||||||
|
|
||||||
|
@computed
|
||||||
|
String get address => wallet.address;
|
||||||
|
|
||||||
|
@computed
|
||||||
|
SyncStatus get status => wallet.syncStatus;
|
||||||
|
|
||||||
|
@computed
|
||||||
|
String get syncStatusText {
|
||||||
|
var statusText = '';
|
||||||
|
|
||||||
|
if (status is SyncingSyncStatus) {
|
||||||
|
statusText = S.current
|
||||||
|
.Blocks_remaining(
|
||||||
|
status.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status is FailedSyncStatus) {
|
||||||
|
statusText = S
|
||||||
|
.current
|
||||||
|
.please_try_to_connect_to_another_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return statusText;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed
|
||||||
|
BalanceDisplayMode get balanceDisplayMode =>
|
||||||
|
appStore.settingsStore.balanceDisplayMode;
|
||||||
|
|
||||||
|
@computed
|
||||||
|
List<TradeListItem> get trades => tradesStore.trades;
|
||||||
|
|
||||||
|
@computed
|
||||||
|
double get price => balanceViewModel.price;
|
||||||
|
|
||||||
|
@computed
|
||||||
|
List<ActionListItem> get items {
|
||||||
|
final _items = <ActionListItem>[];
|
||||||
|
|
||||||
|
_items
|
||||||
|
.addAll(transactionFilterStore.filtered(transactions: transactions));
|
||||||
|
_items.addAll(tradeFilterStore.filtered(trades: trades));
|
||||||
|
|
||||||
|
return formattedItemsList(_items);
|
||||||
|
}
|
||||||
|
|
||||||
|
WalletBase wallet;
|
||||||
|
|
||||||
|
BalanceViewModel balanceViewModel;
|
||||||
|
|
||||||
|
AppStore appStore;
|
||||||
|
|
||||||
|
TradesStore tradesStore;
|
||||||
|
|
||||||
|
TradeFilterStore tradeFilterStore;
|
||||||
|
|
||||||
|
TransactionFilterStore transactionFilterStore;
|
||||||
|
|
||||||
|
ReactionDisposer _reaction;
|
||||||
|
|
||||||
|
void _onWalletChange(WalletBase wallet) {
|
||||||
|
name = wallet.name;
|
||||||
|
transactions.clear();
|
||||||
|
transactions.addAll(wallet.transactionHistory.transactions
|
||||||
|
.map((transaction) => TransactionListItem(
|
||||||
|
transaction: transaction,
|
||||||
|
price: price,
|
||||||
|
fiatCurrency: appStore.settingsStore.fiatCurrency,
|
||||||
|
displayMode: balanceDisplayMode)));
|
||||||
|
}
|
||||||
|
}
|
8
lib/view_model/dashboard/date_section_item.dart
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/action_list_item.dart';
|
||||||
|
|
||||||
|
class DateSectionItem extends ActionListItem {
|
||||||
|
DateSectionItem(this.date);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final DateTime date;
|
||||||
|
}
|
34
lib/view_model/dashboard/formatted_item_list.dart
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/action_list_item.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/date_section_item.dart';
|
||||||
|
|
||||||
|
List<ActionListItem> formattedItemsList(List<ActionListItem> items) {
|
||||||
|
final formattedList = <ActionListItem>[];
|
||||||
|
DateTime lastDate;
|
||||||
|
items.sort((a, b) => b.date.compareTo(a.date));
|
||||||
|
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
final transaction = items[i];
|
||||||
|
|
||||||
|
if (lastDate == null) {
|
||||||
|
lastDate = transaction.date;
|
||||||
|
formattedList.add(DateSectionItem(transaction.date));
|
||||||
|
formattedList.add(transaction);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final isCurrentDay = lastDate.year == transaction.date.year &&
|
||||||
|
lastDate.month == transaction.date.month &&
|
||||||
|
lastDate.day == transaction.date.day;
|
||||||
|
|
||||||
|
if (isCurrentDay) {
|
||||||
|
formattedList.add(transaction);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastDate = transaction.date;
|
||||||
|
formattedList.add(DateSectionItem(transaction.date));
|
||||||
|
formattedList.add(transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
return formattedList;
|
||||||
|
}
|
21
lib/view_model/dashboard/trade_list_item.dart
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import 'package:cake_wallet/src/domain/exchange/trade.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/action_list_item.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
|
||||||
|
|
||||||
|
class TradeListItem extends ActionListItem {
|
||||||
|
TradeListItem({this.trade, this.displayMode});
|
||||||
|
|
||||||
|
final Trade trade;
|
||||||
|
final BalanceDisplayMode displayMode;
|
||||||
|
|
||||||
|
String get tradeFormattedAmount {
|
||||||
|
return trade.amount != null
|
||||||
|
? displayMode == BalanceDisplayMode.hiddenBalance
|
||||||
|
? '---'
|
||||||
|
: trade.amountFormatted()
|
||||||
|
: trade.amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
DateTime get date => trade.createdAt;
|
||||||
|
}
|
54
lib/view_model/dashboard/transaction_list_item.dart
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/common/fiat_currency.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/common/transaction_info.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/action_list_item.dart';
|
||||||
|
import 'package:cake_wallet/bitcoin/bitcoin_transaction_info.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/monero/monero_transaction_info.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/monero/monero_amount_format.dart';
|
||||||
|
import 'package:cake_wallet/bitcoin/bitcoin_amount_format.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/common/calculate_fiat_amount_raw.dart';
|
||||||
|
|
||||||
|
class TransactionListItem extends ActionListItem {
|
||||||
|
TransactionListItem({
|
||||||
|
this.transaction,
|
||||||
|
this.price,
|
||||||
|
this.fiatCurrency,
|
||||||
|
this.displayMode
|
||||||
|
});
|
||||||
|
|
||||||
|
final TransactionInfo transaction;
|
||||||
|
final double price;
|
||||||
|
final FiatCurrency fiatCurrency;
|
||||||
|
final BalanceDisplayMode displayMode;
|
||||||
|
|
||||||
|
String get formattedCryptoAmount {
|
||||||
|
|
||||||
|
return displayMode == BalanceDisplayMode.hiddenBalance
|
||||||
|
? '---'
|
||||||
|
: transaction.amountFormatted();
|
||||||
|
}
|
||||||
|
|
||||||
|
String get formattedFiatAmount {
|
||||||
|
|
||||||
|
if (transaction is MoneroTransactionInfo) {
|
||||||
|
final amount = calculateFiatAmountRaw(
|
||||||
|
cryptoAmount: moneroAmountToDouble(amount: transaction.amount),
|
||||||
|
price: price);
|
||||||
|
transaction.changeFiatAmount(amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transaction is BitcoinTransactionInfo) {
|
||||||
|
final amount = calculateFiatAmountRaw(
|
||||||
|
cryptoAmount: bitcoinAmountToDouble(amount: transaction.amount),
|
||||||
|
price: price);
|
||||||
|
transaction.changeFiatAmount(amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
return displayMode == BalanceDisplayMode.hiddenBalance
|
||||||
|
? '---'
|
||||||
|
: fiatCurrency.title + ' ' + transaction.fiatAmount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
DateTime get date => transaction.date;
|
||||||
|
}
|
6
lib/view_model/dashboard/wallet_balance.dart
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
class WalletBalance {
|
||||||
|
WalletBalance({this.unlockedBalance, this.totalBalance});
|
||||||
|
|
||||||
|
String unlockedBalance;
|
||||||
|
String totalBalance;
|
||||||
|
}
|
|
@ -1,169 +0,0 @@
|
||||||
import 'package:cake_wallet/bitcoin/bitcoin_transaction_info.dart';
|
|
||||||
import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart';
|
|
||||||
import 'package:cake_wallet/monero/monero_wallet.dart';
|
|
||||||
import 'package:cake_wallet/src/domain/common/transaction_direction.dart';
|
|
||||||
import 'package:cake_wallet/src/domain/common/transaction_info.dart';
|
|
||||||
import 'package:cake_wallet/src/stores/action_list/transaction_list_item.dart';
|
|
||||||
import 'package:mobx/mobx.dart';
|
|
||||||
import 'package:cake_wallet/core/wallet_base.dart';
|
|
||||||
import 'package:cake_wallet/src/domain/common/sync_status.dart';
|
|
||||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
|
||||||
import 'package:cake_wallet/store/app_store.dart';
|
|
||||||
|
|
||||||
part 'dashboard_view_model.g.dart';
|
|
||||||
|
|
||||||
class DashboardViewModel = DashboardViewModelBase with _$DashboardViewModel;
|
|
||||||
|
|
||||||
class WalletBalace {
|
|
||||||
WalletBalace({this.unlockedBalance, this.totalBalance});
|
|
||||||
|
|
||||||
final String unlockedBalance;
|
|
||||||
final String totalBalance;
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class DashboardViewModelBase with Store {
|
|
||||||
DashboardViewModelBase({this.appStore}) {
|
|
||||||
name = appStore.wallet?.name;
|
|
||||||
wallet ??= appStore.wallet;
|
|
||||||
type = wallet.type;
|
|
||||||
transactions = ObservableList.of(wallet.transactionHistory.transactions
|
|
||||||
.map((transaction) => TransactionListItem(transaction: transaction)));
|
|
||||||
_reaction = reaction((_) => appStore.wallet, _onWalletChange);
|
|
||||||
|
|
||||||
final _wallet = wallet;
|
|
||||||
|
|
||||||
if (_wallet is MoneroWallet) {
|
|
||||||
subname = _wallet.account?.label;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@observable
|
|
||||||
WalletType type;
|
|
||||||
|
|
||||||
@observable
|
|
||||||
String name;
|
|
||||||
|
|
||||||
@computed
|
|
||||||
String get address => wallet.address;
|
|
||||||
|
|
||||||
@computed
|
|
||||||
SyncStatus get status => wallet.syncStatus;
|
|
||||||
|
|
||||||
@computed
|
|
||||||
WalletBalace get balance {
|
|
||||||
final wallet = this.wallet;
|
|
||||||
|
|
||||||
if (wallet is MoneroWallet) {
|
|
||||||
return WalletBalace(
|
|
||||||
unlockedBalance: wallet.balance.formattedUnlockedBalance,
|
|
||||||
totalBalance: wallet.balance.formattedFullBalance);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wallet is BitcoinWallet) {
|
|
||||||
return WalletBalace(
|
|
||||||
unlockedBalance: wallet.balance.confirmedFormatted,
|
|
||||||
totalBalance: wallet.balance.unconfirmedFormatted);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@observable
|
|
||||||
ObservableList<Object> transactions;
|
|
||||||
// ObservableList.of([
|
|
||||||
// TransactionListItem(transaction: BitcoinTransactionInfo(
|
|
||||||
// id: '',
|
|
||||||
// height: 0,
|
|
||||||
// amount: 0,
|
|
||||||
// direction: TransactionDirection.incoming,
|
|
||||||
// date: DateTime.now(),
|
|
||||||
// isPending: false
|
|
||||||
// )),
|
|
||||||
// TransactionListItem(transaction: BitcoinTransactionInfo(
|
|
||||||
// id: '',
|
|
||||||
// height: 0,
|
|
||||||
// amount: 0,
|
|
||||||
// direction: TransactionDirection.incoming,
|
|
||||||
// date: DateTime.now(),
|
|
||||||
// isPending: false
|
|
||||||
// )),
|
|
||||||
// TransactionListItem(transaction: BitcoinTransactionInfo(
|
|
||||||
// id: '',
|
|
||||||
// height: 0,
|
|
||||||
// amount: 0,
|
|
||||||
// direction: TransactionDirection.incoming,
|
|
||||||
// date: DateTime.now(),
|
|
||||||
// isPending: false
|
|
||||||
// )),
|
|
||||||
// TransactionListItem(transaction: BitcoinTransactionInfo(
|
|
||||||
// id: '',
|
|
||||||
// height: 0,
|
|
||||||
// amount: 0,
|
|
||||||
// direction: TransactionDirection.incoming,
|
|
||||||
// date: DateTime.now(),
|
|
||||||
// isPending: false
|
|
||||||
// )),
|
|
||||||
// TransactionListItem(transaction: BitcoinTransactionInfo(
|
|
||||||
// id: '',
|
|
||||||
// height: 0,
|
|
||||||
// amount: 0,
|
|
||||||
// direction: TransactionDirection.incoming,
|
|
||||||
// date: DateTime.now(),
|
|
||||||
// isPending: false
|
|
||||||
// )),
|
|
||||||
// TransactionListItem(transaction: BitcoinTransactionInfo(
|
|
||||||
// id: '',
|
|
||||||
// height: 0,
|
|
||||||
// amount: 0,
|
|
||||||
// direction: TransactionDirection.incoming,
|
|
||||||
// date: DateTime.now(),
|
|
||||||
// isPending: false
|
|
||||||
// )),
|
|
||||||
// TransactionListItem(transaction: BitcoinTransactionInfo(
|
|
||||||
// id: '',
|
|
||||||
// height: 0,
|
|
||||||
// amount: 0,
|
|
||||||
// direction: TransactionDirection.incoming,
|
|
||||||
// date: DateTime.now(),
|
|
||||||
// isPending: false
|
|
||||||
// )),
|
|
||||||
// TransactionListItem(transaction: BitcoinTransactionInfo(
|
|
||||||
// id: '',
|
|
||||||
// height: 0,
|
|
||||||
// amount: 0,
|
|
||||||
// direction: TransactionDirection.incoming,
|
|
||||||
// date: DateTime.now(),
|
|
||||||
// isPending: false
|
|
||||||
// )),
|
|
||||||
// TransactionListItem(transaction: BitcoinTransactionInfo(
|
|
||||||
// id: '',
|
|
||||||
// height: 0,
|
|
||||||
// amount: 0,
|
|
||||||
// direction: TransactionDirection.incoming,
|
|
||||||
// date: DateTime.now(),
|
|
||||||
// isPending: false
|
|
||||||
// )),
|
|
||||||
// TransactionListItem(transaction: BitcoinTransactionInfo(
|
|
||||||
// id: '',
|
|
||||||
// height: 0,
|
|
||||||
// amount: 0,
|
|
||||||
// direction: TransactionDirection.incoming,
|
|
||||||
// date: DateTime.now(),
|
|
||||||
// isPending: false
|
|
||||||
// )),
|
|
||||||
// ]);
|
|
||||||
|
|
||||||
@observable
|
|
||||||
String subname;
|
|
||||||
|
|
||||||
WalletBase wallet;
|
|
||||||
|
|
||||||
AppStore appStore;
|
|
||||||
|
|
||||||
ReactionDisposer _reaction;
|
|
||||||
|
|
||||||
void _onWalletChange(WalletBase wallet) {
|
|
||||||
name = wallet.name;
|
|
||||||
transactions.clear();
|
|
||||||
transactions.addAll(wallet.transactionHistory.transactions
|
|
||||||
.map((transaction) => TransactionListItem(transaction: transaction)));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -267,6 +267,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.7"
|
version: "3.0.7"
|
||||||
|
dots_indicator:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: dots_indicator
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.0"
|
||||||
dotted_border:
|
dotted_border:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -50,6 +50,7 @@ dependencies:
|
||||||
devicelocale: ^0.2.1
|
devicelocale: ^0.2.1
|
||||||
auto_size_text: ^2.1.0
|
auto_size_text: ^2.1.0
|
||||||
dotted_border: ^1.0.5
|
dotted_border: ^1.0.5
|
||||||
|
dots_indicator: ^1.2.0
|
||||||
|
|
||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
|
@ -107,6 +108,11 @@ flutter:
|
||||||
- asset: assets/fonts/Montserrat-Regular.ttf
|
- asset: assets/fonts/Montserrat-Regular.ttf
|
||||||
- asset: assets/fonts/Montserrat-Bold.ttf
|
- asset: assets/fonts/Montserrat-Bold.ttf
|
||||||
- asset: assets/fonts/Montserrat-SemiBold.ttf
|
- asset: assets/fonts/Montserrat-SemiBold.ttf
|
||||||
|
- family: Poppins
|
||||||
|
fonts:
|
||||||
|
- asset: assets/fonts/Poppins-Regular.ttf
|
||||||
|
- asset: assets/fonts/Poppins-Medium.ttf
|
||||||
|
- asset: assets/fonts/Poppins-Bold.ttf
|
||||||
|
|
||||||
|
|
||||||
# To add assets to your application, add an assets section, like this:
|
# To add assets to your application, add an assets section, like this:
|
||||||
|
|
|
@ -137,6 +137,7 @@
|
||||||
"share_address" : "Share address",
|
"share_address" : "Share address",
|
||||||
"receive_amount" : "Amount",
|
"receive_amount" : "Amount",
|
||||||
"subaddresses" : "Subaddresses",
|
"subaddresses" : "Subaddresses",
|
||||||
|
"addresses" : "Addresses",
|
||||||
"rename" : "Rename",
|
"rename" : "Rename",
|
||||||
"choose_account" : "Choose account",
|
"choose_account" : "Choose account",
|
||||||
"create_new_account" : "Create new account",
|
"create_new_account" : "Create new account",
|
||||||
|
|