CAKE-30 | created settings_version_cell, language_row, version_list_item; applied new design to settings, faq, disclaimer, pin code, change language pages; fixed items of settings page

This commit is contained in:
OleksandrSobol 2020-09-07 20:35:34 +03:00
parent dab3c1c8b4
commit 30665aac1c
20 changed files with 278 additions and 176 deletions

View file

@ -90,6 +90,8 @@ class PaletteDark {
static const Color distantBlue = Color.fromRGBO(72, 85, 131, 1.0);
static const Color moderateVioletBlue = Color.fromRGBO(62, 73, 113, 1.0);
static const Color deepVioletBlue = Color.fromRGBO(52, 66, 104, 1.0);
static const Color lightPurpleBlue = Color.fromRGBO(120, 133, 170, 1.0);
static const Color indicatorVioletBlue = Color.fromRGBO(59, 72, 119, 1.0);
// FIXME: Rename.
static const Color eee = Color.fromRGBO(236, 239, 245, 1.0);

View file

@ -30,7 +30,7 @@ class Language with ChangeNotifier {
}
static Future<String> localeDetection() async {
String locale = await Devicelocale.currentLocale;
var locale = await Devicelocale.currentLocale;
locale = Intl.shortLocale(locale);
return languages.keys.contains(locale) ? locale : 'en';

View file

@ -1,4 +1,5 @@
import 'dart:ui';
import 'package:cake_wallet/palette.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
@ -132,6 +133,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
_fileText,
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.normal,
color: Theme.of(context).primaryTextTheme.title.color
),
))
@ -169,7 +171,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
xmrtoUrl,
textAlign: TextAlign.left,
style: TextStyle(
color: Colors.blue,
color: Palette.blueCraiola,
fontSize: 14.0,
fontWeight: FontWeight.normal,
decoration: TextDecoration.underline),
@ -190,7 +192,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
changenowUrl,
textAlign: TextAlign.left,
style: TextStyle(
color: Colors.blue,
color: Palette.blueCraiola,
fontSize: 14.0,
fontWeight: FontWeight.normal,
decoration: TextDecoration.underline),
@ -211,7 +213,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
morphUrl,
textAlign: TextAlign.left,
style: TextStyle(
color: Colors.blue,
color: Palette.blueCraiola,
fontSize: 14.0,
fontWeight: FontWeight.normal,
decoration: TextDecoration.underline),

View file

@ -1,4 +1,6 @@
import 'dart:convert';
import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/src/widgets/standard_list.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
@ -27,12 +29,10 @@ class FaqFormState extends State<FaqForm> {
@override
Widget build(BuildContext context) {
final addIcon = Icon(Icons.add, color: Theme.of(context).primaryTextTheme.title.color);
final removeIcon = Icon(Icons.remove, color: Colors.green);
final removeIcon = Icon(Icons.remove, color: Palette.blueCraiola);
return Container(
padding: EdgeInsets.only(top: 12),
child: Container(
color: Theme.of(context).accentTextTheme.headline.color,
padding: EdgeInsets.only(top: 12, left: 24),
child: FutureBuilder(
builder: (context, snapshot) {
final faqItems = jsonDecode(snapshot.data.toString()) as List;
@ -42,40 +42,33 @@ class FaqFormState extends State<FaqForm> {
}
return SingleChildScrollView(
child: ListView.separated(
child: Column(
children: <Widget>[
StandardListSeparator(),
ListView.separated(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
final itemTitle = faqItems[index]["question"].toString();
final itemChild = faqItems[index]["answer"].toString();
return ExpansionTile(
title: Padding(
padding: EdgeInsets.only(left: 8, top: 12, bottom: 12),
child: Text(
return ListTileTheme(
contentPadding: EdgeInsets.fromLTRB(0, 6, 24, 6),
child: ExpansionTile(
title: Text(
itemTitle,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
fontWeight: FontWeight.w500,
color: colors[index]
),
),
),
trailing: Padding(
padding: EdgeInsets.only(right: 24),
child: Container(
width: double.minPositive,
child: Center(
child: icons[index]
),
),
),
backgroundColor: Theme.of(context).accentTextTheme.headline.backgroundColor,
trailing: icons[index],
onExpansionChanged: (value) {
setState(() {
if (value) {
icons[index] = removeIcon;
colors[index] = Colors.green;
colors[index] = Palette.blueCraiola;
} else {
icons[index] = addIcon;
colors[index] = Theme.of(context).primaryTextTheme.title.color;
@ -89,14 +82,13 @@ class FaqFormState extends State<FaqForm> {
Expanded(
child: Container(
padding: EdgeInsets.only(
left: 24.0,
right: 24.0,
bottom: 8
),
child: Text(
itemChild,
style: TextStyle(
fontSize: 12,
fontSize: 14,
fontWeight: FontWeight.normal,
color: Theme.of(context).primaryTextTheme.title.color
),
),
@ -104,17 +96,19 @@ class FaqFormState extends State<FaqForm> {
],
)
],
),
);
},
separatorBuilder: (_, __) =>
Container(color: Theme.of(context).dividerColor, height: 1.0),
StandardListSeparator(),
itemCount: faqItems == null ? 0 : faqItems.length,
)
],
),
);
},
future: rootBundle.loadString(getFaqPath(context)),
),
),
);
}

View file

@ -108,7 +108,7 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
Text(title,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
fontWeight: FontWeight.w500,
color: Theme.of(context).primaryTextTheme.title.color)),
Spacer(flex: 3),
Container(
@ -126,7 +126,7 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
shape: BoxShape.circle,
color: isFilled
? Theme.of(context).primaryTextTheme.title.color
: Theme.of(context).primaryTextTheme.caption.color,
: Theme.of(context).accentTextTheme.body1.color,
));
}),
),
@ -143,7 +143,8 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
_changePinLengthText(),
style: TextStyle(
fontSize: 14.0,
color: Theme.of(context).primaryTextTheme.caption.color),
fontWeight: FontWeight.normal,
color: Theme.of(context).accentTextTheme.body1.decorationColor),
))
],
Spacer(flex: 1),
@ -227,7 +228,7 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
child: Text('$index',
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.bold,
fontWeight: FontWeight.w600,
color: Theme.of(context)
.primaryTextTheme
.title

View file

@ -1,3 +1,5 @@
import 'package:cake_wallet/src/screens/settings/widgets/language_row.dart';
import 'package:cake_wallet/src/widgets/standard_list.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart';
@ -16,29 +18,13 @@ class ChangeLanguage extends BasePage {
final settingsStore = Provider.of<SettingsStore>(context);
final currentLanguage = Provider.of<Language>(context);
final currentColor = Colors.green;
final notCurrentColor = Theme.of(context).primaryTextTheme.title.color;
final shortDivider = Container(
height: 1,
padding: EdgeInsets.only(left: 24),
color: Theme.of(context).accentTextTheme.title.backgroundColor,
child: Container(
height: 1,
color: Theme.of(context).dividerColor,
),
);
final longDivider = Container(
height: 1,
color: Theme.of(context).dividerColor,
);
return Container(
padding: EdgeInsets.only(top: 10.0),
child: ListView.builder(
itemCount: languages.values.length,
itemBuilder: (BuildContext context, int index) {
child: SectionStandardList(
sectionCount: 1,
context: context,
itemCounter: (int sectionIndex) => languages.values.length,
itemBuilder: (_, sectionIndex, index) {
final item = languages.values.elementAt(index);
final code = languages.keys.elementAt(index);
@ -46,26 +32,10 @@ class ChangeLanguage extends BasePage {
? false
: code == settingsStore.languageCode;
return Column(
children: <Widget>[
index == 0 ? longDivider : Offstage(),
Container(
padding: EdgeInsets.only(top: 4, bottom: 4),
color: Theme.of(context).accentTextTheme.title.backgroundColor,
child: ListTile(
contentPadding: EdgeInsets.only(left: 24, right: 24),
title: Text(
item,
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w600,
color: isCurrent ? currentColor : notCurrentColor
),
),
trailing: isCurrent
? Icon(Icons.done, color: currentColor)
: Offstage(),
onTap: () async {
return LanguageRow(
title: item,
isSelected: isCurrent,
handler: (context) async {
if (!isCurrent) {
await showDialog<void>(
context: context,
@ -86,12 +56,6 @@ class ChangeLanguage extends BasePage {
});
}
},
),
),
item == languages.values.last
? longDivider
: shortDivider
],
);
},
)

View file

@ -1,3 +1,5 @@
import 'package:cake_wallet/src/screens/settings/widgets/settings_version_cell.dart';
import 'package:cake_wallet/view_model/settings/version_list_item.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
@ -41,6 +43,8 @@ class SettingsPage extends BasePage {
return SettingsPickerCell<dynamic>(
title: item.title,
selectedItem: item.selectedItem(),
setItem: (dynamic value) => item.setItem(value),
isAlwaysShowScrollThumb: item.isAlwaysShowScrollThumb,
items: item.items);
});
}
@ -55,7 +59,7 @@ class SettingsPage extends BasePage {
}
if (item is RegularListItem) {
return SettingsCellWithArrow(title: item.title);
return SettingsCellWithArrow(title: item.title, handler: item.handler);
}
if (item is LinkListItem) {
@ -66,6 +70,13 @@ class SettingsPage extends BasePage {
linkTitle: item.linkTitle);
}
if (item is VersionListItem) {
return Observer(builder: (_) {
return SettingsVersionCell(
title: S.of(context).version(settingsViewModel.currentVersion));
});
}
return Container();
});
}

View file

@ -0,0 +1,30 @@
import 'package:cake_wallet/palette.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/src/widgets/standard_list.dart';
class LanguageRow extends StandardListRow {
LanguageRow({@required String title, @required this.isSelected, @required Function(BuildContext context) handler}) :
super(title: title, isSelected: isSelected, onTap: handler);
@override
final bool isSelected;
@override
Widget buildCenter(BuildContext context, {@required bool hasLeftOffset}) {
return Expanded(
child: Row(mainAxisAlignment: MainAxisAlignment.start, children: [
if (hasLeftOffset) SizedBox(width: 10),
Text(title,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: titleColor(context)))
]));
}
@override
Widget buildTrailing(BuildContext context) =>
isSelected
? Icon(Icons.done, color: Palette.blueCraiola)
: Offstage();
}

View file

@ -2,11 +2,11 @@ import 'package:flutter/material.dart';
import 'package:cake_wallet/src/widgets/standard_list.dart';
class SettingsCellWithArrow extends StandardListRow {
SettingsCellWithArrow({@required String title})
: super(title: title, isSelected: false);
SettingsCellWithArrow({@required String title, @required Function(BuildContext context) handler})
: super(title: title, isSelected: false, onTap: handler);
@override
Widget buildTrailing(BuildContext context) =>
Image.asset('assets/images/select_arrow.png',
color: Theme.of(context).primaryTextTheme.caption.color);
color: Theme.of(context).primaryTextTheme.overline.color);
}

View file

@ -1,5 +1,7 @@
import 'package:cake_wallet/palette.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/src/widgets/standard_list.dart';
import 'package:url_launcher/url_launcher.dart';
class SettingsLinkProviderCell extends StandardListRow {
SettingsLinkProviderCell(
@ -7,7 +9,7 @@ class SettingsLinkProviderCell extends StandardListRow {
@required this.icon,
@required this.link,
@required this.linkTitle})
: super(title: title, isSelected: false);
: super(title: title, isSelected: false, onTap: (BuildContext context) => _launchUrl(link) );
final String icon;
final String link;
@ -20,5 +22,11 @@ class SettingsLinkProviderCell extends StandardListRow {
@override
Widget buildTrailing(BuildContext context) => Text(linkTitle,
style: TextStyle(
fontSize: 14.0, fontWeight: FontWeight.w500, color: Colors.blue));
fontSize: 14.0,
fontWeight: FontWeight.w500,
color: Palette.blueCraiola));
static void _launchUrl(String url) async {
if (await canLaunch(url)) await launch(url);
}
}

View file

@ -4,7 +4,8 @@ import 'package:cake_wallet/src/widgets/standard_list.dart';
import 'package:cake_wallet/generated/i18n.dart';
class SettingsPickerCell<ItemType> extends StandardListRow {
SettingsPickerCell({@required String title, this.selectedItem, this.items})
SettingsPickerCell({@required String title, this.selectedItem, this.items,
this.setItem, this.isAlwaysShowScrollThumb})
: super(
title: title,
isSelected: false,
@ -18,11 +19,14 @@ class SettingsPickerCell<ItemType> extends StandardListRow {
selectedAtIndex: selectedAtIndex,
title: S.current.please_select,
mainAxisAlignment: MainAxisAlignment.center,
onItemSelected: (Object _) {}));
isAlwaysShowScrollThumb: isAlwaysShowScrollThumb,
onItemSelected: (ItemType value) => setItem(value)));
});
final ItemType selectedItem;
final List<ItemType> items;
final Function(ItemType) setItem;
final bool isAlwaysShowScrollThumb;
@override
Widget buildTrailing(BuildContext context) {
@ -32,7 +36,7 @@ class SettingsPickerCell<ItemType> extends StandardListRow {
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w500,
color: Theme.of(context).primaryTextTheme.caption.color),
color: Theme.of(context).primaryTextTheme.overline.color),
);
}
}

View file

@ -0,0 +1,28 @@
import 'package:flutter/material.dart';
class SettingsVersionCell extends StatelessWidget {
SettingsVersionCell({@required this.title});
final String title;
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(bottom: 24),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
title,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.normal,
color: Theme.of(context).primaryTextTheme.overline.color
),
)
],
),
);
}
}

View file

@ -53,7 +53,7 @@ class _SetupPinCodeFormState<WidgetType extends SetupPinCodeForm>
state.clear();
} else {
if (listEquals<int>(state.pin, _originalPin)) {
final String pin = state.pin.fold("", (ac, val) => ac + '$val');
final String pin = state.pin.fold('', (ac, val) => ac + '$val');
_userStore.set(password: pin);
_settingsStore.setDefaultPinLength(pinLength: state.pinLength);

View file

@ -123,9 +123,7 @@ class PickerState<Item> extends State<Picker> {
mainAxisAlignment: widget.mainAxisAlignment,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
image != null
? image
: Offstage(),
image ?? Offstage(),
Padding(
padding: EdgeInsets.only(
left: image != null ? 12 : 0

View file

@ -41,18 +41,17 @@ class StandardListRow extends StatelessWidget {
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.normal,
color: _titleColor(context)))
color: titleColor(context)))
]));
}
Widget buildTrailing(BuildContext context) => null;
Color _titleColor(BuildContext context) => isSelected
Color titleColor(BuildContext context) => isSelected
? Palette.blueCraiola
: Theme.of(context).primaryTextTheme.title.color;
Color _backgroundColor(BuildContext context) {
// return Theme.of(context).accentTextTheme.subtitle.decorationColor;
return Theme.of(context).backgroundColor;
}
}
@ -114,16 +113,20 @@ class SectionStandardList extends StatelessWidget {
{@required this.itemCounter,
@required this.itemBuilder,
@required this.sectionCount,
this.hasTopSeparator = false,
BuildContext context})
: totalRows = transform(context, sectionCount, itemCounter, itemBuilder);
: totalRows = transform(hasTopSeparator, context, sectionCount,
itemCounter, itemBuilder);
final int sectionCount;
final bool hasTopSeparator;
final int Function(int sectionIndex) itemCounter;
final Widget Function(BuildContext context, int sectionIndex, int itemIndex)
itemBuilder;
final List<Widget> totalRows;
static List<Widget> transform(
bool hasTopSeparator,
BuildContext context,
int sectionCount,
int Function(int sectionIndex) itemCounter,
@ -132,9 +135,9 @@ class SectionStandardList extends StatelessWidget {
final items = <Widget>[];
for (var sectionIndex = 0; sectionIndex < sectionCount; sectionIndex++) {
/*if (sectionIndex == 0) {
items.add(StandardListSeparator());
}*/
if ((sectionIndex == 0)&&(hasTopSeparator)) {
items.add(StandardListSeparator(padding: EdgeInsets.only(left: 24)));
}
final itemCount = itemCounter(sectionIndex);

View file

@ -26,7 +26,7 @@ class StandartSwitchState extends State<StandartSwitch> {
decoration: BoxDecoration(
color: widget.value
? Colors.green
: PaletteDark.distantBlue,
: Theme.of(context).accentTextTheme.display4.color,
borderRadius: BorderRadius.all(Radius.circular(14.0))),
child: Container(
width: 24.0,

View file

@ -160,6 +160,13 @@ class Themes {
color: Palette.darkGray, // hint text (new wallet page)
decorationColor: Palette.periwinkleCraiola // underline (new wallet page)
),
display4: TextStyle(
color: Palette.darkGray, // switch background (settings page)
),
body1: TextStyle(
color: Palette.darkGray, // indicators (PIN code)
decorationColor: Palette.darkGray // switch (PIN code)
)
),
@ -331,6 +338,13 @@ class Themes {
color: PaletteDark.cyanBlue, // hint text (new wallet page)
decorationColor: PaletteDark.darkGrey // underline (new wallet page)
),
display4: TextStyle(
color: PaletteDark.deepVioletBlue, // switch background (settings page)
),
body1: TextStyle(
color: PaletteDark.indicatorVioletBlue, // indicators (PIN code)
decorationColor: PaletteDark.lightPurpleBlue // switch (PIN code)
)
),

View file

@ -5,9 +5,13 @@ class PickerListItem<ItemType> extends SettingsListItem {
PickerListItem(
{@required String title,
@required this.selectedItem,
@required this.items})
@required this.setItem,
@required this.items,
this.isAlwaysShowScrollThumb = false})
: super(title);
final ItemType Function() selectedItem;
final Function(ItemType value) setItem;
final List<ItemType> items;
final bool isAlwaysShowScrollThumb;
}

View file

@ -1,6 +1,7 @@
import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/store/theme_changer_store.dart';
import 'package:cake_wallet/themes.dart';
import 'package:cake_wallet/view_model/settings/version_list_item.dart';
import 'package:flutter/cupertino.dart';
import 'package:mobx/mobx.dart';
import 'package:cake_wallet/routes.dart';
@ -17,6 +18,7 @@ import 'package:cake_wallet/view_model/settings/picker_list_item.dart';
import 'package:cake_wallet/view_model/settings/regular_list_item.dart';
import 'package:cake_wallet/view_model/settings/settings_list_item.dart';
import 'package:cake_wallet/view_model/settings/switcher_list_item.dart';
import 'package:package_info/package_info.dart';
part 'settings_view_model.g.dart';
@ -24,19 +26,27 @@ class SettingsViewModel = SettingsViewModelBase with _$SettingsViewModel;
abstract class SettingsViewModelBase with Store {
SettingsViewModelBase(this._settingsStore) : itemHeaders = {} {
currentVersion = '';
PackageInfo.fromPlatform().then((PackageInfo packageInfo) => currentVersion = packageInfo.version);
sections = [
[
PickerListItem(
title: S.current.settings_display_balance_as,
items: BalanceDisplayMode.all,
setItem: (dynamic value) => balanceDisplayMode = value as BalanceDisplayMode,
selectedItem: () => balanceDisplayMode),
PickerListItem(
title: S.current.settings_currency,
items: FiatCurrency.all,
setItem: (dynamic value) => fiatCurrency = value as FiatCurrency,
isAlwaysShowScrollThumb: true,
selectedItem: () => fiatCurrency),
PickerListItem(
title: S.current.settings_fee_priority,
items: TransactionPriority.all,
setItem: (dynamic value) => transactionPriority = value as TransactionPriority,
isAlwaysShowScrollThumb: true,
selectedItem: () => transactionPriority),
SwitcherListItem(
title: S.current.settings_save_recipient_address,
@ -111,11 +121,22 @@ abstract class SettingsViewModelBase with Store {
title: S.current.settings_terms_and_conditions,
handler: (BuildContext context) =>
Navigator.of(context).pushNamed(Routes.disclaimer),
),
RegularListItem(
title: S.current.faq,
handler: (BuildContext context) =>
Navigator.pushNamed(context, Routes.faq),
)
],
[
VersionListItem(title: currentVersion)
]
];
}
@observable
String currentVersion;
@computed
Node get node => _settingsStore.node;
@ -150,6 +171,18 @@ abstract class SettingsViewModelBase with Store {
set allowBiometricalAuthentication(bool value) =>
_settingsStore.allowBiometricalAuthentication = value;
@action
set balanceDisplayMode(BalanceDisplayMode value) =>
_settingsStore.balanceDisplayMode = value;
@action
set fiatCurrency(FiatCurrency value) =>
_settingsStore.fiatCurrency = value;
@action
set transactionPriority(TransactionPriority value) =>
_settingsStore.transactionPriority = value;
// @observable
// bool isDarkTheme;
//

View file

@ -0,0 +1,6 @@
import 'package:flutter/foundation.dart';
import 'package:cake_wallet/view_model/settings/settings_list_item.dart';
class VersionListItem extends SettingsListItem {
VersionListItem({@required String title}) : super(title);
}