mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-22 19:49:22 +00:00
rework trade details screen (#449)
* create standart list card item * create standart list status item * update localization * fix date format * fix theme gradient * PR comments * fix issues from code review
This commit is contained in:
parent
04be884357
commit
0aee6e1b8d
15 changed files with 296 additions and 31 deletions
|
@ -574,7 +574,8 @@ Future setup(
|
|||
(WalletType type, _) => PreSeedPage(type));
|
||||
|
||||
getIt.registerFactoryParam<TradeDetailsViewModel, Trade, void>((trade, _) =>
|
||||
TradeDetailsViewModel(tradeForDetails: trade, trades: _tradesSource));
|
||||
TradeDetailsViewModel(tradeForDetails: trade, trades: _tradesSource,
|
||||
settingsStore: getIt.get<SettingsStore>()));
|
||||
|
||||
getIt.registerFactory(() => BackupService(
|
||||
getIt.get<FlutterSecureStorage>(),
|
||||
|
|
|
@ -2,20 +2,56 @@ import 'package:flutter/material.dart';
|
|||
import 'package:cake_wallet/palette.dart';
|
||||
|
||||
class SyncIndicatorIcon extends StatelessWidget {
|
||||
SyncIndicatorIcon({this.isSynced});
|
||||
SyncIndicatorIcon(
|
||||
{this.boolMode = true,
|
||||
this.isSynced = false,
|
||||
this.value = waiting,
|
||||
this.size = 4.0});
|
||||
|
||||
final bool boolMode;
|
||||
final bool isSynced;
|
||||
final String value;
|
||||
final double size;
|
||||
|
||||
static const String waiting = 'waiting';
|
||||
static const String actionRequired = 'action required';
|
||||
static const String created = 'created';
|
||||
static const String fetching = 'fetching';
|
||||
static const String finished = 'finished';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Color indicatorColor;
|
||||
|
||||
if (boolMode) {
|
||||
indicatorColor = isSynced
|
||||
? PaletteDark.brightGreen
|
||||
: Theme.of(context).textTheme.caption.color;
|
||||
} else {
|
||||
switch (value.toLowerCase()) {
|
||||
case waiting:
|
||||
indicatorColor = Colors.red;
|
||||
break;
|
||||
case actionRequired:
|
||||
indicatorColor = Theme.of(context).textTheme.display3.decorationColor;
|
||||
break;
|
||||
case created:
|
||||
indicatorColor = PaletteDark.brightGreen;
|
||||
break;
|
||||
case fetching:
|
||||
indicatorColor = Colors.red;
|
||||
break;
|
||||
case finished:
|
||||
indicatorColor = PaletteDark.brightGreen;
|
||||
break;
|
||||
default:
|
||||
indicatorColor = Colors.red;
|
||||
}
|
||||
}
|
||||
return Container(
|
||||
height: 4,
|
||||
width: 4,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: isSynced
|
||||
? PaletteDark.brightGreen
|
||||
: Theme.of(context).textTheme.caption.color),
|
||||
);
|
||||
height: size,
|
||||
width: size,
|
||||
decoration:
|
||||
BoxDecoration(shape: BoxShape.circle, color: indicatorColor));
|
||||
}
|
||||
}
|
||||
|
|
35
lib/src/screens/trade_details/trade_details_list_card.dart
Normal file
35
lib/src/screens/trade_details/trade_details_list_card.dart
Normal file
|
@ -0,0 +1,35 @@
|
|||
import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
|
||||
class TradeDetailsListCardItem extends StandartListItem {
|
||||
TradeDetailsListCardItem(
|
||||
{String title,
|
||||
String value,
|
||||
this.id,
|
||||
this.createdAt,
|
||||
this.pair,
|
||||
this.onTap})
|
||||
: super(title: title, value: value);
|
||||
|
||||
factory TradeDetailsListCardItem.tradeDetails(
|
||||
{@required String id,
|
||||
@required String createdAt,
|
||||
@required CryptoCurrency from,
|
||||
@required CryptoCurrency to,
|
||||
@required Function onTap}) {
|
||||
return TradeDetailsListCardItem(
|
||||
id: '${S.current.trade_details_id} ${formatAsText(id)}',
|
||||
createdAt: formatAsText(createdAt),
|
||||
pair: '${formatAsText(from)} → ${formatAsText(to)}',
|
||||
onTap: onTap);
|
||||
}
|
||||
|
||||
final String id;
|
||||
final String createdAt;
|
||||
final String pair;
|
||||
final Function onTap;
|
||||
|
||||
static String formatAsText<T>(T value) => value?.toString() ?? '';
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
import 'package:cake_wallet/src/widgets/standard_list.dart';
|
||||
import 'package:cake_wallet/src/widgets/standart_list_card.dart';
|
||||
import 'package:cake_wallet/src/widgets/standart_list_status_row.dart';
|
||||
import 'package:cake_wallet/utils/show_bar.dart';
|
||||
import 'package:cake_wallet/view_model/trade_details_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -9,6 +11,8 @@ import 'package:cake_wallet/generated/i18n.dart';
|
|||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/standart_list_row.dart';
|
||||
import 'package:cake_wallet/src/screens/trade_details/track_trade_list_item.dart';
|
||||
import 'package:cake_wallet/src/screens/trade_details/trade_details_list_card.dart';
|
||||
import 'package:cake_wallet/src/screens/trade_details/trade_details_status_item.dart';
|
||||
|
||||
class TradeDetailsPage extends BasePage {
|
||||
TradeDetailsPage(this.tradeDetailsViewModel);
|
||||
|
@ -58,7 +62,23 @@ class TradeDetailsPageBodyState extends State<TradeDetailsPageBody> {
|
|||
onTap: item.onTap,
|
||||
child: StandartListRow(
|
||||
title: '${item.title}', value: '${item.value}'));
|
||||
} else {
|
||||
}
|
||||
|
||||
if (item is DetailsListStatusItem) {
|
||||
return StandartListStatusRow(
|
||||
title: item.title,
|
||||
value: item.value);
|
||||
}
|
||||
|
||||
if (item is TradeDetailsListCardItem) {
|
||||
return TradeDatailsStandartListCard(
|
||||
id: item.id,
|
||||
create: item.createdAt,
|
||||
pair: item.pair,
|
||||
currentTheme: tradeDetailsViewModel.settingsStore.currentTheme.type,
|
||||
onTap: item.onTap,);
|
||||
}
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(text: '${item.value}'));
|
||||
|
@ -66,7 +86,6 @@ class TradeDetailsPageBodyState extends State<TradeDetailsPageBody> {
|
|||
},
|
||||
child: StandartListRow(
|
||||
title: '${item.title}', value: '${item.value}'));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart';
|
||||
|
||||
class DetailsListStatusItem extends StandartListItem {
|
||||
DetailsListStatusItem(
|
||||
{String title, String value})
|
||||
: super(title: title, value: value);
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:cake_wallet/src/widgets/standart_list_card.dart';
|
||||
import 'package:cake_wallet/src/widgets/standart_list_status_row.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
@ -212,6 +214,10 @@ class SectionStandardList extends StatelessWidget {
|
|||
return Container();
|
||||
}
|
||||
|
||||
if (row is StandartListStatusRow || row is TradeDatailsStandartListCard) {
|
||||
return Container();
|
||||
}
|
||||
|
||||
final nextRow = totalRows[index + 1];
|
||||
|
||||
// If current row is pre last and last row is separator.
|
||||
|
|
77
lib/src/widgets/standart_list_card.dart
Normal file
77
lib/src/widgets/standart_list_card.dart
Normal file
|
@ -0,0 +1,77 @@
|
|||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
|
||||
class TradeDatailsStandartListCard extends StatelessWidget {
|
||||
TradeDatailsStandartListCard(
|
||||
{this.id, this.create, this.pair, this.onTap, this.currentTheme});
|
||||
|
||||
final String id;
|
||||
final String create;
|
||||
final String pair;
|
||||
final ThemeType currentTheme;
|
||||
final Function onTap;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final darkTheme = currentTheme == ThemeType.dark;
|
||||
|
||||
final baseGradient = LinearGradient(colors: [
|
||||
Theme.of(context).primaryTextTheme.subtitle.color,
|
||||
Theme.of(context).primaryTextTheme.subtitle.decorationColor,
|
||||
], begin: Alignment.centerLeft, end: Alignment.centerRight);
|
||||
|
||||
final gradient = LinearGradient(colors: [
|
||||
PaletteDark.wildNightBlue,
|
||||
PaletteDark.oceanBlue,
|
||||
], begin: Alignment.bottomCenter, end: Alignment.topCenter);
|
||||
|
||||
final textColor = Colors.white;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0),
|
||||
child: GestureDetector(
|
||||
onTap: () => onTap(context),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15.0),
|
||||
gradient: darkTheme ? gradient : baseGradient),
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 20.0, vertical: 16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(id,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w400,
|
||||
color: textColor)),
|
||||
SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
Text(create,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w400,
|
||||
color: textColor)),
|
||||
SizedBox(
|
||||
height: 35,
|
||||
),
|
||||
Text(pair,
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.bold,
|
||||
color: textColor)),
|
||||
]),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
66
lib/src/widgets/standart_list_status_row.dart
Normal file
66
lib/src/widgets/standart_list_status_row.dart
Normal file
|
@ -0,0 +1,66 @@
|
|||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator_icon.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class StandartListStatusRow extends StatelessWidget {
|
||||
StandartListStatusRow({this.title, this.value});
|
||||
|
||||
final String title;
|
||||
final String value;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
color: Theme.of(context).backgroundColor,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(left: 24, top: 16, bottom: 16, right: 24),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(title,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).primaryTextTheme.overline.color),
|
||||
textAlign: TextAlign.left),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 12),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).accentTextTheme.display2.color,
|
||||
borderRadius: BorderRadius.circular(30.0),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
SyncIndicatorIcon(
|
||||
boolMode: false,
|
||||
value: value,
|
||||
size: 6,
|
||||
),
|
||||
SizedBox(
|
||||
width: 5,
|
||||
),
|
||||
Text(value,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.title
|
||||
.color))
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -3,21 +3,21 @@ import 'package:cake_wallet/di.dart';
|
|||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
|
||||
class DateFormatter {
|
||||
static String currentLocalFormat({bool hasTime = true}) {
|
||||
static String currentLocalFormat({bool hasTime = true, bool reverse = false}) {
|
||||
final isUSA = getIt.get<SettingsStore>().languageCode.toLowerCase() == 'en';
|
||||
final format =
|
||||
isUSA ? usaStyleFormat(hasTime) : regularStyleFormat(hasTime);
|
||||
isUSA ? usaStyleFormat(hasTime, reverse) : regularStyleFormat(hasTime, reverse);
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
static DateFormat withCurrentLocal({bool hasTime = true}) => DateFormat(
|
||||
currentLocalFormat(hasTime: hasTime),
|
||||
static DateFormat withCurrentLocal({bool hasTime = true, bool reverse = false}) => DateFormat(
|
||||
currentLocalFormat(hasTime: hasTime, reverse: reverse),
|
||||
getIt.get<SettingsStore>().languageCode);
|
||||
|
||||
static String usaStyleFormat(bool hasTime) =>
|
||||
hasTime ? 'yyyy.MM.dd, HH:mm' : 'yyyy.MM.dd';
|
||||
static String usaStyleFormat(bool hasTime, bool reverse) =>
|
||||
hasTime ? (reverse ? 'HH:mm yyyy.MM.dd' : 'yyyy.MM.dd, HH:mm') : 'yyyy.MM.dd';
|
||||
|
||||
static String regularStyleFormat(bool hasTime) =>
|
||||
hasTime ? 'dd.MM.yyyy, HH:mm' : 'dd.MM.yyyy';
|
||||
static String regularStyleFormat(bool hasTime, bool reverse) =>
|
||||
hasTime ? (reverse ? 'HH:mm dd.MM.yyyy' : 'dd.MM.yyyy, HH:mm') : 'dd.MM.yyyy';
|
||||
}
|
||||
|
|
|
@ -7,12 +7,18 @@ import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart'
|
|||
import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart';
|
||||
import 'package:cake_wallet/exchange/trade.dart';
|
||||
import 'package:cake_wallet/exchange/xmrto/xmrto_exchange_provider.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/utils/date_formatter.dart';
|
||||
import 'package:cake_wallet/utils/show_bar.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart';
|
||||
import 'package:cake_wallet/src/screens/trade_details/track_trade_list_item.dart';
|
||||
import 'package:cake_wallet/src/screens/trade_details/trade_details_list_card.dart';
|
||||
import 'package:cake_wallet/src/screens/trade_details/trade_details_status_item.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
part 'trade_details_view_model.g.dart';
|
||||
|
||||
|
@ -20,7 +26,7 @@ class TradeDetailsViewModel = TradeDetailsViewModelBase
|
|||
with _$TradeDetailsViewModel;
|
||||
|
||||
abstract class TradeDetailsViewModelBase with Store {
|
||||
TradeDetailsViewModelBase({Trade tradeForDetails, this.trades}) {
|
||||
TradeDetailsViewModelBase({Trade tradeForDetails, this.trades, this.settingsStore}) {
|
||||
trade = tradeForDetails;
|
||||
|
||||
switch (trade.provider) {
|
||||
|
@ -62,6 +68,8 @@ abstract class TradeDetailsViewModelBase with Store {
|
|||
|
||||
Timer timer;
|
||||
|
||||
final SettingsStore settingsStore;
|
||||
|
||||
@action
|
||||
Future<void> _updateTrade() async {
|
||||
try {
|
||||
|
@ -80,18 +88,28 @@ abstract class TradeDetailsViewModelBase with Store {
|
|||
}
|
||||
|
||||
void _updateItems() {
|
||||
final dateFormat = DateFormatter.withCurrentLocal();
|
||||
final dateFormat = DateFormatter.withCurrentLocal(reverse: true);
|
||||
|
||||
items?.clear();
|
||||
|
||||
items.addAll([
|
||||
StandartListItem(title: S.current.trade_details_id, value: trade.id),
|
||||
StandartListItem(
|
||||
items.add(
|
||||
DetailsListStatusItem(
|
||||
title: S.current.trade_details_state,
|
||||
value: trade.state != null
|
||||
? trade.state.toString()
|
||||
: S.current.trade_details_fetching)
|
||||
]);
|
||||
);
|
||||
|
||||
items.add(TradeDetailsListCardItem.tradeDetails(
|
||||
id: trade.id,
|
||||
createdAt: dateFormat.format(trade.createdAt),
|
||||
from: trade.from,
|
||||
to: trade.to,
|
||||
onTap: (BuildContext context) {
|
||||
Clipboard.setData(ClipboardData(text: '${trade.id}'));
|
||||
showBar<void>(context, S.of(context).copied_to_clipboard);
|
||||
},
|
||||
));
|
||||
|
||||
if (trade.provider != null) {
|
||||
items.add(StandartListItem(
|
||||
|
|
|
@ -276,7 +276,7 @@
|
|||
|
||||
"trade_details_title" : "Trade Details",
|
||||
"trade_details_id" : "ID",
|
||||
"trade_details_state" : "State",
|
||||
"trade_details_state" : "Status",
|
||||
"trade_details_fetching" : "Fetching",
|
||||
"trade_details_provider" : "Provider",
|
||||
"trade_details_created_at" : "Created at",
|
||||
|
|
|
@ -274,7 +274,7 @@
|
|||
|
||||
"trade_details_title" : "Détails de l'échange",
|
||||
"trade_details_id" : "ID",
|
||||
"trade_details_state" : "État",
|
||||
"trade_details_state" : "Statut",
|
||||
"trade_details_fetching" : "Récupération",
|
||||
"trade_details_provider" : "Fournisseur",
|
||||
"trade_details_created_at" : "Créé le",
|
||||
|
|
|
@ -276,7 +276,7 @@
|
|||
|
||||
"trade_details_title" : "व्यापार विवरण",
|
||||
"trade_details_id" : "आईडी",
|
||||
"trade_details_state" : "राज्य",
|
||||
"trade_details_state" : "दर्जा",
|
||||
"trade_details_fetching" : "ला रहा है",
|
||||
"trade_details_provider" : "प्रदाता",
|
||||
"trade_details_created_at" : "पर बनाया गया",
|
||||
|
|
|
@ -276,7 +276,7 @@
|
|||
|
||||
"trade_details_title" : "Detalji razmjene",
|
||||
"trade_details_id" : "ID",
|
||||
"trade_details_state" : "Stanje",
|
||||
"trade_details_state" : "Status",
|
||||
"trade_details_fetching" : "Dohvaćanje",
|
||||
"trade_details_provider" : "Pružatelj",
|
||||
"trade_details_created_at" : "Stvoreno u",
|
||||
|
|
|
@ -276,7 +276,7 @@
|
|||
|
||||
"trade_details_title" : "Handelsgegevens",
|
||||
"trade_details_id" : "ID",
|
||||
"trade_details_state" : "Staat",
|
||||
"trade_details_state" : "Toestand",
|
||||
"trade_details_fetching" : "Ophalen",
|
||||
"trade_details_provider" : "Leverancier",
|
||||
"trade_details_created_at" : "Gemaakt bij",
|
||||
|
|
Loading…
Reference in a new issue