cake_wallet/lib/src/screens/settings/settings.dart

432 lines
17 KiB
Dart
Raw Normal View History

2020-01-08 12:26:34 +00:00
import 'package:cake_wallet/src/screens/auth/auth_page.dart';
2020-01-04 19:31:52 +00:00
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:cake_wallet/palette.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:provider/provider.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/generated/i18n.dart';
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_priority.dart';
import 'package:cake_wallet/src/stores/settings/settings_store.dart';
import 'package:cake_wallet/src/stores/action_list/action_list_display_mode.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/screens/settings/attributes.dart';
import 'package:cake_wallet/src/screens/disclaimer/disclaimer_page.dart';
import 'package:cake_wallet/src/screens/settings/items/settings_item.dart';
import 'package:cake_wallet/src/screens/settings/items/item_headers.dart';
import 'package:cake_wallet/src/widgets/present_picker.dart';
2020-01-04 19:31:52 +00:00
// Settings widgets
import 'package:cake_wallet/src/screens/settings/widgets/settings_arrow_list_row.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_header_list_row.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_link_list_row.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_switch_list_row.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_text_list_row.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_raw_widget_list_row.dart';
class SettingsPage extends BasePage {
2020-01-08 12:26:34 +00:00
@override
2020-01-04 19:31:52 +00:00
String get title => S.current.settings_title;
2020-01-08 12:26:34 +00:00
@override
2020-01-04 19:31:52 +00:00
bool get isModalBackButton => true;
2020-01-08 12:26:34 +00:00
@override
2020-01-04 19:31:52 +00:00
Color get backgroundColor => Palette.lightGrey2;
@override
Widget body(BuildContext context) {
return SettingsForm();
}
}
class SettingsForm extends StatefulWidget {
@override
2020-01-08 12:26:34 +00:00
SettingsFormState createState() => SettingsFormState();
2020-01-04 19:31:52 +00:00
}
class SettingsFormState extends State<SettingsForm> {
final _telegramImage = Image.asset('assets/images/Telegram.png');
final _twitterImage = Image.asset('assets/images/Twitter.png');
final _changeNowImage = Image.asset('assets/images/change_now.png');
final _xmrBtcImage = Image.asset('assets/images/xmr_btc.png');
final _morphImage = Image.asset('assets/images/morph_icon.png');
2020-01-04 19:31:52 +00:00
final _emailUrl = 'mailto:support@cakewallet.com';
final _telegramUrl = 'https:t.me/cakewallet_bot';
2020-01-04 19:31:52 +00:00
final _twitterUrl = 'https:twitter.com/CakewalletXMR';
final _changeNowUrl = 'mailto:support@changenow.io';
final _xmrToUrl = 'mailto:support@xmr.to';
final _morphUrl = 'mailto:support@morphtoken.com';
2020-01-04 19:31:52 +00:00
2020-01-08 12:26:34 +00:00
final _items = List<SettingsItem>();
2020-01-04 19:31:52 +00:00
2020-01-08 12:26:34 +00:00
void _launchUrl(String url) async {
2020-01-04 19:31:52 +00:00
if (await canLaunch(url)) await launch(url);
}
2020-01-08 12:26:34 +00:00
void _setSettingsList() {
2020-01-04 19:31:52 +00:00
final settingsStore = Provider.of<SettingsStore>(context);
settingsStore.setItemHeaders();
_items.addAll([
SettingsItem(title: ItemHeaders.nodes, attribute: Attributes.header),
SettingsItem(
onTaped: () => Navigator.of(context).pushNamed(Routes.nodeList),
title: ItemHeaders.currentNode,
widget: Observer(
builder: (_) => Text(
settingsStore.node == null ? '' : settingsStore.node.uri,
textAlign: TextAlign.right,
2020-01-04 19:31:52 +00:00
style: TextStyle(
fontSize: 16.0,
color:
Theme.of(context).primaryTextTheme.subtitle.color),
)),
attribute: Attributes.widget),
SettingsItem(title: ItemHeaders.wallets, attribute: Attributes.header),
SettingsItem(
onTaped: () => _setBalance(context),
title: ItemHeaders.displayBalanceAs,
widget: Observer(
builder: (_) => Text(
settingsStore.balanceDisplayMode.toString(),
textAlign: TextAlign.right,
2020-01-04 19:31:52 +00:00
style: TextStyle(
fontSize: 16.0,
color:
Theme.of(context).primaryTextTheme.subtitle.color),
)),
attribute: Attributes.widget),
SettingsItem(
onTaped: () => _setCurrency(context),
title: ItemHeaders.currency,
widget: Observer(
builder: (_) => Text(
settingsStore.fiatCurrency.toString(),
textAlign: TextAlign.right,
2020-01-04 19:31:52 +00:00
style: TextStyle(
fontSize: 16.0,
color:
Theme.of(context).primaryTextTheme.subtitle.color),
)),
attribute: Attributes.widget),
SettingsItem(
onTaped: () => _setTransactionPriority(context),
title: ItemHeaders.feePriority,
widget: Observer(
builder: (_) => Text(
settingsStore.transactionPriority.toString(),
textAlign: TextAlign.right,
2020-01-04 19:31:52 +00:00
style: TextStyle(
fontSize: 16.0,
color:
Theme.of(context).primaryTextTheme.subtitle.color),
)),
attribute: Attributes.widget),
SettingsItem(
title: ItemHeaders.saveRecipientAddress,
attribute: Attributes.switcher),
SettingsItem(title: ItemHeaders.personal, attribute: Attributes.header),
SettingsItem(
onTaped: () {
Navigator.of(context).pushNamed(Routes.auth,
2020-01-08 12:26:34 +00:00
arguments: (bool isAuthenticatedSuccessfully,
AuthPageState auth) =>
2020-01-04 19:31:52 +00:00
isAuthenticatedSuccessfully
? Navigator.of(context).popAndPushNamed(Routes.setupPin,
2020-01-08 12:26:34 +00:00
arguments:
(BuildContext setupPinContext, String _) =>
Navigator.of(context).pop())
2020-01-04 19:31:52 +00:00
: null);
},
title: ItemHeaders.changePIN,
attribute: Attributes.arrow),
SettingsItem(
onTaped: () => Navigator.pushNamed(context, Routes.changeLanguage),
title: ItemHeaders.changeLanguage,
attribute: Attributes.arrow),
SettingsItem(
title: ItemHeaders.allowBiometricalAuthentication,
attribute: Attributes.switcher),
SettingsItem(title: ItemHeaders.darkMode, attribute: Attributes.switcher),
SettingsItem(
widgetBuilder: (context) {
return PopupMenuButton<ActionListDisplayMode>(
itemBuilder: (context) => [
PopupMenuItem(
value: ActionListDisplayMode.transactions,
child: Observer(
builder: (_) => Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(S
.of(context)
.settings_transactions),
Checkbox(
value: settingsStore
.actionlistDisplayMode
.contains(ActionListDisplayMode
.transactions),
onChanged: (value) => settingsStore
.toggleTransactionsDisplay(),
)
]))),
PopupMenuItem(
value: ActionListDisplayMode.trades,
child: Observer(
builder: (_) => Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(S.of(context).settings_trades),
Checkbox(
value: settingsStore
.actionlistDisplayMode
.contains(
ActionListDisplayMode.trades),
onChanged: (value) => settingsStore
.toggleTradesDisplay(),
)
])))
],
child: Container(
height: 56,
padding: EdgeInsets.only(left: 20, right: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(S.of(context).settings_display_on_dashboard_list,
style: TextStyle(
fontSize: 16,
color: Theme.of(context)
.primaryTextTheme
.title
.color)),
Observer(builder: (_) {
var title = '';
if (settingsStore.actionlistDisplayMode.length ==
ActionListDisplayMode.values.length) {
title = S.of(context).settings_all;
}
if (title.isEmpty &&
settingsStore.actionlistDisplayMode
.contains(ActionListDisplayMode.trades)) {
title = S.of(context).settings_only_trades;
}
if (title.isEmpty &&
settingsStore.actionlistDisplayMode.contains(
ActionListDisplayMode.transactions)) {
title = S.of(context).settings_only_transactions;
}
if (title.isEmpty) {
title = S.of(context).settings_none;
}
return Text(title,
style: TextStyle(
fontSize: 16.0,
color: Theme.of(context)
.primaryTextTheme
.subtitle
.color));
})
]),
));
},
attribute: Attributes.rawWidget),
SettingsItem(title: ItemHeaders.support, attribute: Attributes.header),
SettingsItem(
onTaped: () => _launchUrl(_emailUrl),
title: 'Email',
link: 'support@cakewallet.com',
2020-01-04 19:31:52 +00:00
image: null,
attribute: Attributes.link),
SettingsItem(
onTaped: () => _launchUrl(_telegramUrl),
title: 'Telegram',
link: 't.me/cakewallet_bot',
2020-01-04 19:31:52 +00:00
image: _telegramImage,
attribute: Attributes.link),
SettingsItem(
onTaped: () => _launchUrl(_twitterUrl),
title: 'Twitter',
link: 'twitter.com/CakewalletXMR',
image: _twitterImage,
attribute: Attributes.link),
SettingsItem(
onTaped: () => _launchUrl(_changeNowUrl),
title: 'ChangeNow',
link: 'support@changenow.io',
image: _changeNowImage,
attribute: Attributes.link),
SettingsItem(
onTaped: () => _launchUrl(_xmrToUrl),
title: 'XMR.to',
link: 'support@xmr.to',
image: _xmrBtcImage,
attribute: Attributes.link),
SettingsItem(
onTaped: () => _launchUrl(_morphUrl),
title: 'MorphToken',
link: 'support@morphtoken.com',
image: _morphImage,
attribute: Attributes.link),
2020-01-04 19:31:52 +00:00
SettingsItem(
onTaped: () {
Navigator.push(
context,
2020-01-08 12:26:34 +00:00
CupertinoPageRoute<void>(
2020-01-04 19:31:52 +00:00
builder: (BuildContext context) => DisclaimerPage()));
},
title: ItemHeaders.termsAndConditions,
attribute: Attributes.arrow),
SettingsItem(
onTaped: () => Navigator.pushNamed(context, Routes.faq),
title: ItemHeaders.faq,
attribute: Attributes.arrow)
]);
setState(() {});
}
2020-01-08 12:26:34 +00:00
void _afterLayout(dynamic _) => _setSettingsList();
2020-01-04 19:31:52 +00:00
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
}
Widget _getWidget(SettingsItem item) {
switch (item.attribute) {
case Attributes.arrow:
return SettingsArrowListRow(
onTaped: item.onTaped,
title: item.title,
);
case Attributes.header:
return SettingsHeaderListRow(
title: item.title,
);
case Attributes.link:
return SettingsLinktListRow(
onTaped: item.onTaped,
title: item.title,
link: item.link,
image: item.image,
);
case Attributes.switcher:
return SettingsSwitchListRow(
title: item.title,
);
case Attributes.widget:
return SettingsTextListRow(
onTaped: item.onTaped,
title: item.title,
widget: item.widget,
);
case Attributes.rawWidget:
return SettingRawWidgetListRow(widgetBuilder: item.widgetBuilder);
default:
return Offstage();
}
}
@override
Widget build(BuildContext context) {
final settingsStore = Provider.of<SettingsStore>(context);
settingsStore.setItemHeaders();
return SingleChildScrollView(
child: Column(
children: <Widget>[
ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: _items.length,
itemBuilder: (context, index) {
final item = _items[index];
bool _isDrawDivider = true;
if (item.attribute == Attributes.header || item == _items.last) {
2020-01-04 19:31:52 +00:00
_isDrawDivider = false;
} else {
2020-01-08 12:26:34 +00:00
if (_items[index + 1].attribute == Attributes.header) {
2020-01-04 19:31:52 +00:00
_isDrawDivider = false;
2020-01-08 12:26:34 +00:00
}
2020-01-04 19:31:52 +00:00
}
return Column(
children: <Widget>[
_getWidget(item),
_isDrawDivider
? Container(
color: Theme.of(context)
.accentTextTheme
.headline
.backgroundColor,
padding: EdgeInsets.only(
left: 20.0,
right: 20.0,
),
child: Divider(
color: Theme.of(context).dividerColor,
height: 1.0,
),
)
: Offstage()
],
);
}),
ListTile(
contentPadding: EdgeInsets.only(left: 20.0),
title: Text(
settingsStore.itemHeaders[ItemHeaders.version],
style: TextStyle(
fontSize: 14.0, color: Palette.wildDarkBlue)
),
2020-01-04 19:31:52 +00:00
)
],
));
}
2020-01-08 12:26:34 +00:00
Future<void> _setBalance(BuildContext context) async {
2020-01-04 19:31:52 +00:00
final settingsStore = Provider.of<SettingsStore>(context);
final selectedDisplayMode =
await presentPicker(context, BalanceDisplayMode.all);
2020-01-04 19:31:52 +00:00
if (selectedDisplayMode != null) {
2020-01-08 12:26:34 +00:00
await settingsStore.setCurrentBalanceDisplayMode(
2020-01-04 19:31:52 +00:00
balanceDisplayMode: selectedDisplayMode);
}
}
2020-01-08 12:26:34 +00:00
Future<void> _setCurrency(BuildContext context) async {
2020-01-04 19:31:52 +00:00
final settingsStore = Provider.of<SettingsStore>(context);
final selectedCurrency = await presentPicker(context, FiatCurrency.all);
2020-01-04 19:31:52 +00:00
if (selectedCurrency != null) {
2020-01-08 12:26:34 +00:00
await settingsStore.setCurrentFiatCurrency(currency: selectedCurrency);
2020-01-04 19:31:52 +00:00
}
}
2020-01-08 12:26:34 +00:00
Future<void> _setTransactionPriority(BuildContext context) async {
2020-01-04 19:31:52 +00:00
final settingsStore = Provider.of<SettingsStore>(context);
final selectedPriority =
await presentPicker(context, TransactionPriority.all);
2020-01-04 19:31:52 +00:00
if (selectedPriority != null) {
2020-01-08 12:26:34 +00:00
await settingsStore.setCurrentTransactionPriority(
priority: selectedPriority);
2020-01-04 19:31:52 +00:00
}
}
}