Rework settings pickers (#398)
Updated pickers and settings screen
Omar Hatem committed
Jun 29, 2022 at 14:38 UTC
dc623f3293fba818c937f79af5b8d63bcb58b689
78 files changed
+601
-358
assets/images/flags/aus.png
Binary files /dev/null and b/assets/images/flags/aus.png differ
assets/images/flags/bgr.png
Binary files /dev/null and b/assets/images/flags/bgr.png differ
assets/images/flags/bra.png
Binary files /dev/null and b/assets/images/flags/bra.png differ
assets/images/flags/cad.png
Binary files /dev/null and b/assets/images/flags/cad.png differ
assets/images/flags/che.png
Binary files /dev/null and b/assets/images/flags/che.png differ
assets/images/flags/chn.png
Binary files /dev/null and b/assets/images/flags/chn.png differ
assets/images/flags/czk.png
Binary files /dev/null and b/assets/images/flags/czk.png differ
assets/images/flags/deu.png
Binary files /dev/null and b/assets/images/flags/deu.png differ
assets/images/flags/dnk.png
Binary files /dev/null and b/assets/images/flags/dnk.png differ
assets/images/flags/esp.png
Binary files /dev/null and b/assets/images/flags/esp.png differ
assets/images/flags/eur.png
Binary files /dev/null and b/assets/images/flags/eur.png differ
assets/images/flags/fra.png
Binary files /dev/null and b/assets/images/flags/fra.png differ
assets/images/flags/gbr.png
Binary files /dev/null and b/assets/images/flags/gbr.png differ
assets/images/flags/hkg.png
Binary files /dev/null and b/assets/images/flags/hkg.png differ
assets/images/flags/hrv.png
Binary files /dev/null and b/assets/images/flags/hrv.png differ
assets/images/flags/hun.png
Binary files /dev/null and b/assets/images/flags/hun.png differ
assets/images/flags/idn.png
Binary files /dev/null and b/assets/images/flags/idn.png differ
assets/images/flags/ind.png
Binary files /dev/null and b/assets/images/flags/ind.png differ
assets/images/flags/isl.png
Binary files /dev/null and b/assets/images/flags/isl.png differ
assets/images/flags/isr.png
Binary files /dev/null and b/assets/images/flags/isr.png differ
assets/images/flags/ita.png
Binary files /dev/null and b/assets/images/flags/ita.png differ
assets/images/flags/jpn.png
Binary files /dev/null and b/assets/images/flags/jpn.png differ
assets/images/flags/kor.png
Binary files /dev/null and b/assets/images/flags/kor.png differ
assets/images/flags/mex.png
Binary files /dev/null and b/assets/images/flags/mex.png differ
assets/images/flags/mys.png
Binary files /dev/null and b/assets/images/flags/mys.png differ
assets/images/flags/nld.png
Binary files /dev/null and b/assets/images/flags/nld.png differ
assets/images/flags/nor.png
Binary files /dev/null and b/assets/images/flags/nor.png differ
assets/images/flags/nzl.png
Binary files /dev/null and b/assets/images/flags/nzl.png differ
assets/images/flags/phl.png
Binary files /dev/null and b/assets/images/flags/phl.png differ
assets/images/flags/pol.png
Binary files /dev/null and b/assets/images/flags/pol.png differ
assets/images/flags/prt.png
Binary files /dev/null and b/assets/images/flags/prt.png differ
assets/images/flags/rou.png
Binary files /dev/null and b/assets/images/flags/rou.png differ
assets/images/flags/rus.png
Binary files /dev/null and b/assets/images/flags/rus.png differ
assets/images/flags/saf.png
Binary files /dev/null and b/assets/images/flags/saf.png differ
assets/images/flags/sgp.png
Binary files /dev/null and b/assets/images/flags/sgp.png differ
assets/images/flags/swe.png
Binary files /dev/null and b/assets/images/flags/swe.png differ
assets/images/flags/tha.png
Binary files /dev/null and b/assets/images/flags/tha.png differ
assets/images/flags/ukr.png
Binary files /dev/null and b/assets/images/flags/ukr.png differ
assets/images/flags/usa.png
Binary files /dev/null and b/assets/images/flags/usa.png differ
assets/images/flags/ven.png
Binary files /dev/null and b/assets/images/flags/ven.png differ
assets/images/search_icon.png
Binary files /dev/null and b/assets/images/search_icon.png differ
lib/di.dart
-3
@@ -38,7 +38,6 @@ import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart';
38
import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart';
39
import 'package:cake_wallet/src/screens/seed/wallet_seed_page.dart';
40
import 'package:cake_wallet/src/screens/send/send_template_page.dart';
41
-import 'package:cake_wallet/src/screens/settings/change_language.dart';
41
import 'package:cake_wallet/src/screens/settings/settings.dart';
42
import 'package:cake_wallet/src/screens/setup_pin_code/setup_pin_code.dart';
43
import 'package:cake_wallet/src/screens/support/support_page.dart';
@@ -507,8 +506,6 @@ Future setup(
506
507
getIt.registerFactory(() => FaqPage(getIt.get<SettingsStore>()));
508
510
- getIt.registerFactory(() => LanguageListPage(getIt.get<SettingsStore>()));
511
-
509
getIt.registerFactoryParam<WalletRestoreViewModel, WalletType, void>(
510
(type, _) => WalletRestoreViewModel(getIt.get<AppStore>(),
511
getIt.get<WalletCreationService>(param1: type), _walletInfoSource,
lib/entities/fiat_currency.dart
+37
-34
@@ -1,43 +1,46 @@
1
import 'package:cw_core/enumerable_item.dart';
2
3
class FiatCurrency extends EnumerableItem<String> with Serializable<String> {
4
- const FiatCurrency({String symbol}) : super(title: symbol, raw: symbol);
4
+ const FiatCurrency({String symbol, this.countryCode, this.fullName}) : super(title: symbol, raw: symbol);
5
+
6
+ final String countryCode;
7
+ final String fullName;
8
9
static List<FiatCurrency> get all => _all.values.toList();
10
8
- static const aud = FiatCurrency(symbol: 'AUD');
9
- static const bgn = FiatCurrency(symbol: 'BGN');
10
- static const brl = FiatCurrency(symbol: 'BRL');
11
- static const cad = FiatCurrency(symbol: 'CAD');
12
- static const chf = FiatCurrency(symbol: 'CHF');
13
- static const cny = FiatCurrency(symbol: 'CNY');
14
- static const czk = FiatCurrency(symbol: 'CZK');
15
- static const eur = FiatCurrency(symbol: 'EUR');
16
- static const dkk = FiatCurrency(symbol: 'DKK');
17
- static const gbp = FiatCurrency(symbol: 'GBP');
18
- static const hkd = FiatCurrency(symbol: 'HKD');
19
- static const hrk = FiatCurrency(symbol: 'HRK');
20
- static const huf = FiatCurrency(symbol: 'HUF');
21
- static const idr = FiatCurrency(symbol: 'IDR');
22
- static const ils = FiatCurrency(symbol: 'ILS');
23
- static const inr = FiatCurrency(symbol: 'INR');
24
- static const isk = FiatCurrency(symbol: 'ISK');
25
- static const jpy = FiatCurrency(symbol: 'JPY');
26
- static const krw = FiatCurrency(symbol: 'KRW');
27
- static const mxn = FiatCurrency(symbol: 'MXN');
28
- static const myr = FiatCurrency(symbol: 'MYR');
29
- static const nok = FiatCurrency(symbol: 'NOK');
30
- static const nzd = FiatCurrency(symbol: 'NZD');
31
- static const php = FiatCurrency(symbol: 'PHP');
32
- static const pln = FiatCurrency(symbol: 'PLN');
33
- static const ron = FiatCurrency(symbol: 'RON');
34
- static const rub = FiatCurrency(symbol: 'RUB');
35
- static const sek = FiatCurrency(symbol: 'SEK');
36
- static const sgd = FiatCurrency(symbol: 'SGD');
37
- static const thb = FiatCurrency(symbol: 'THB');
38
- static const usd = FiatCurrency(symbol: 'USD');
39
- static const zar = FiatCurrency(symbol: 'ZAR');
40
- static const vef = FiatCurrency(symbol: 'VEF');
11
+ static const aud = FiatCurrency(symbol: 'AUD', countryCode: "aus", fullName: "Australian Dollar");
12
+ static const bgn = FiatCurrency(symbol: 'BGN', countryCode: "bgr", fullName: "Bulgarian Lev");
13
+ static const brl = FiatCurrency(symbol: 'BRL', countryCode: "bra", fullName: "Brazilian Real");
14
+ static const cad = FiatCurrency(symbol: 'CAD', countryCode: "cad", fullName: "Canadian Dollar");
15
+ static const chf = FiatCurrency(symbol: 'CHF', countryCode: "che", fullName: "Swiss Franc");
16
+ static const cny = FiatCurrency(symbol: 'CNY', countryCode: "chn", fullName: "Chinese Yuan");
17
+ static const czk = FiatCurrency(symbol: 'CZK', countryCode: "czk", fullName: "Czech Koruna");
18
+ static const eur = FiatCurrency(symbol: 'EUR', countryCode: "eur", fullName: "Euro");
19
+ static const dkk = FiatCurrency(symbol: 'DKK', countryCode: "dnk", fullName: "Danish Krone");
20
+ static const gbp = FiatCurrency(symbol: 'GBP', countryCode: "gbr", fullName: "Pound sterling");
21
+ static const hkd = FiatCurrency(symbol: 'HKD', countryCode: "hkg", fullName: "Hong Kong Dollar");
22
+ static const hrk = FiatCurrency(symbol: 'HRK', countryCode: "hrv", fullName: "Croatian Kuna");
23
+ static const huf = FiatCurrency(symbol: 'HUF', countryCode: "hun", fullName: "Hungarian Forint");
24
+ static const idr = FiatCurrency(symbol: 'IDR', countryCode: "idn", fullName: "Indonesian Rupiah");
25
+ static const ils = FiatCurrency(symbol: 'ILS', countryCode: "isr", fullName: "Israeli New Shekel");
26
+ static const inr = FiatCurrency(symbol: 'INR', countryCode: "ind", fullName: "Indian Rupee");
27
+ static const isk = FiatCurrency(symbol: 'ISK', countryCode: "isl", fullName: "Icelandic Króna");
28
+ static const jpy = FiatCurrency(symbol: 'JPY', countryCode: "jpn", fullName: "Japanese Yen equals");
29
+ static const krw = FiatCurrency(symbol: 'KRW', countryCode: "kor", fullName: "South Korean won");
30
+ static const mxn = FiatCurrency(symbol: 'MXN', countryCode: "mex", fullName: "Mexican Peso");
31
+ static const myr = FiatCurrency(symbol: 'MYR', countryCode: "mys", fullName: "Malaysian Ringgit");
32
+ static const nok = FiatCurrency(symbol: 'NOK', countryCode: "nor", fullName: "Norwegian Krone");
33
+ static const nzd = FiatCurrency(symbol: 'NZD', countryCode: "nzl", fullName: "New Zealand Dollar");
34
+ static const php = FiatCurrency(symbol: 'PHP', countryCode: "phl", fullName: "Philippine peso");
35
+ static const pln = FiatCurrency(symbol: 'PLN', countryCode: "pol", fullName: "Poland złoty");
36
+ static const ron = FiatCurrency(symbol: 'RON', countryCode: "rou", fullName: "Romanian Leu");
37
+ static const rub = FiatCurrency(symbol: 'RUB', countryCode: "rus", fullName: "Russian Ruble");
38
+ static const sek = FiatCurrency(symbol: 'SEK', countryCode: "swe", fullName: "Swedish Krona");
39
+ static const sgd = FiatCurrency(symbol: 'SGD', countryCode: "sgp", fullName: "Singapore Dollar");
40
+ static const thb = FiatCurrency(symbol: 'THB', countryCode: "tha", fullName: "Thai Baht");
41
+ static const usd = FiatCurrency(symbol: 'USD', countryCode: "usa", fullName: "United States Dollar");
42
+ static const zar = FiatCurrency(symbol: 'ZAR', countryCode: "saf", fullName: "South African Rand");
43
+ static const vef = FiatCurrency(symbol: 'VEF', countryCode: "ven", fullName: "Venezuelan Bolívar");
44
45
static final _all = {
46
FiatCurrency.aud.raw: FiatCurrency.aud,
lib/entities/language_service.dart
+19
@@ -20,6 +20,25 @@ class LanguageService {
20
'hr': 'Hrvatski (Croatian)',
21
'it': 'Italiano (Italian)'
22
};
23
+
24
+ static const Map<String, String> localeCountryCode = {
25
+ 'en': 'usa',
26
+ 'de': 'deu',
27
+ 'es': 'esp',
28
+ 'fr': 'fra',
29
+ 'hi': 'ind',
30
+ 'ja': 'jpn',
31
+ 'ko': 'kor',
32
+ 'nl': 'nld',
33
+ 'pl': 'pol',
34
+ 'pt': 'prt',
35
+ 'ru': 'rus',
36
+ 'uk': 'ukr',
37
+ 'zh': 'chn',
38
+ 'hr': 'hrv',
39
+ 'it': 'ita'
40
+ };
41
+
42
static final list = <String, String> {};
43
44
static void loadLocaleList() {
lib/router.dart
-5
@@ -47,7 +47,6 @@ import 'package:cake_wallet/src/screens/monero_accounts/monero_account_edit_or_c
47
import 'package:cake_wallet/src/screens/contact/contact_list_page.dart';
48
import 'package:cake_wallet/src/screens/contact/contact_page.dart';
49
import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart';
50
-import 'package:cake_wallet/src/screens/settings/change_language.dart';
50
import 'package:cake_wallet/src/screens/restore/restore_wallet_from_seed_details.dart';
51
import 'package:cake_wallet/src/screens/exchange/exchange_page.dart';
52
import 'package:cake_wallet/src/screens/settings/settings.dart';
@@ -359,10 +358,6 @@ Route<dynamic> createRoute(RouteSettings settings) {
358
case Routes.faq:
359
return MaterialPageRoute<void>(builder: (_) => getIt.get<FaqPage>());
360
362
- case Routes.changeLanguage:
363
- return MaterialPageRoute<void>(
364
- builder: (_) => getIt.get<LanguageListPage>());
365
-
361
case Routes.preSeed:
362
return MaterialPageRoute<void>(
363
builder: (_) =>
lib/routes.dart
-1
@@ -41,7 +41,6 @@ class Routes {
41
static const unlock = '/auth_not_closable';
42
static const rescan = '/rescan';
43
static const faq = '/faq';
44
- static const changeLanguage = '/change_language';
44
static const newWalletType = '/new_wallet_type';
45
static const sendTemplate = '/send_template';
46
static const exchangeTemplate = '/exchange_template';
lib/src/screens/settings/change_language.dart
deleted
-63
@@ -1,63 +0,0 @@
1
-import 'package:cake_wallet/src/screens/settings/widgets/language_row.dart';
2
-import 'package:cake_wallet/src/widgets/standard_list.dart';
3
-import 'package:cake_wallet/store/settings_store.dart';
4
-import 'package:cake_wallet/utils/show_pop_up.dart';
5
-import 'package:flutter/material.dart';
6
-import 'package:flutter/cupertino.dart';
7
-import 'package:flutter_mobx/flutter_mobx.dart';
8
-import 'package:cake_wallet/generated/i18n.dart';
9
-import 'package:cake_wallet/entities/language_service.dart';
10
-import 'package:cake_wallet/src/screens/base_page.dart';
11
-import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
12
-
13
-class LanguageListPage extends BasePage {
14
- LanguageListPage(this.settingsStore);
15
-
16
- final SettingsStore settingsStore;
17
-
18
- @override
19
- String get title => S.current.settings_change_language;
20
-
21
- @override
22
- Widget body(BuildContext context) {
23
- return Container(
24
- padding: EdgeInsets.only(top: 10.0),
25
- child: SectionStandardList(
26
- sectionCount: 1,
27
- context: context,
28
- itemCounter: (int sectionIndex) => LanguageService.list.values.length,
29
- itemBuilder: (_, sectionIndex, index) {
30
- return Observer(builder: (BuildContext context) {
31
- final item = LanguageService.list.values.elementAt(index);
32
- final code = LanguageService.list.keys.elementAt(index);
33
- final isCurrent = code == settingsStore.languageCode ?? false;
34
-
35
- return LanguageRow(
36
- title: item,
37
- isSelected: isCurrent,
38
- handler: (context) async {
39
- if (!isCurrent) {
40
- await showPopUp<void>(
41
- context: context,
42
- builder: (BuildContext context) {
43
- return AlertWithTwoActions(
44
- alertTitle: S.of(context).change_language,
45
- alertContent:
46
- S.of(context).change_language_to(item),
47
- rightButtonText: S.of(context).change,
48
- leftButtonText: S.of(context).cancel,
49
- actionRightButton: () {
50
- settingsStore.languageCode = code;
51
- Navigator.of(context).pop();
52
- },
53
- actionLeftButton: () =>
54
- Navigator.of(context).pop());
55
- });
56
- }
57
- },
58
- );
59
- });
60
- },
61
- ));
62
- }
63
-}
lib/src/screens/settings/settings.dart
+10
@@ -1,4 +1,6 @@
1
+import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart';
2
import 'package:cake_wallet/src/screens/settings/widgets/settings_version_cell.dart';
3
+import 'package:cake_wallet/view_model/settings/choices_list_item.dart';
4
import 'package:cake_wallet/view_model/settings/version_list_item.dart';
5
import 'package:flutter/material.dart';
6
import 'package:flutter/cupertino.dart';
@@ -46,6 +48,10 @@ class SettingsPage extends BasePage {
48
selectedItem: item.selectedItem(),
49
items: item.items,
50
onItemSelected: (dynamic value) => item.onItemSelected(value),
51
+ images: item.images,
52
+ searchHintText: item.searchHintText,
53
+ isGridView: item.isGridView,
54
+ matchingCriteria: (dynamic value, String searchText) => item.matchingCriteria(value, searchText),
55
);
56
});
57
}
@@ -80,6 +86,10 @@ class SettingsPage extends BasePage {
86
});
87
}
88
89
+ if (item is ChoicesListItem) {
90
+ return SettingsChoicesCell(item);
91
+ }
92
+
93
return Container();
94
});
95
}
lib/src/screens/settings/widgets/language_row.dart
deleted
-30
@@ -1,30 +0,0 @@
1
-import 'package:cake_wallet/palette.dart';
2
-import 'package:flutter/material.dart';
3
-import 'package:cake_wallet/src/widgets/standard_list.dart';
4
-
5
-class LanguageRow extends StandardListRow {
6
- LanguageRow({@required String title, @required this.isSelected, @required Function(BuildContext context) handler}) :
7
- super(title: title, isSelected: isSelected, onTap: handler);
8
-
9
- @override
10
- final bool isSelected;
11
-
12
- @override
13
- Widget buildCenter(BuildContext context, {@required bool hasLeftOffset}) {
14
- return Expanded(
15
- child: Row(mainAxisAlignment: MainAxisAlignment.start, children: [
16
- if (hasLeftOffset) SizedBox(width: 10),
17
- Text(title,
18
- style: TextStyle(
19
- fontSize: 14,
20
- fontWeight: FontWeight.w500,
21
- color: titleColor(context)))
22
- ]));
23
- }
24
-
25
- @override
26
- Widget buildTrailing(BuildContext context) =>
27
- isSelected
28
- ? Icon(Icons.done, color: Palette.blueCraiola)
29
- : Offstage();
30
-}
\ No newline at end of file
lib/src/screens/settings/widgets/settings_choices_cell.dart
new
+71
@@ -0,0 +1,71 @@
1
+import 'package:cake_wallet/view_model/settings/choices_list_item.dart';
2
+import 'package:flutter/material.dart';
3
+
4
+class SettingsChoicesCell extends StatelessWidget {
5
+ const SettingsChoicesCell(this.choicesListItem, {Key key}) : super(key: key);
6
+
7
+ final ChoicesListItem choicesListItem;
8
+
9
+ @override
10
+ Widget build(BuildContext context) {
11
+ return Container(
12
+ color: Theme.of(context).backgroundColor,
13
+ padding: EdgeInsets.all(24),
14
+ child: Column(
15
+ mainAxisSize: MainAxisSize.min,
16
+ crossAxisAlignment: CrossAxisAlignment.start,
17
+ children: [
18
+ Row(
19
+ children: [
20
+ Text(
21
+ choicesListItem.title,
22
+ style: TextStyle(
23
+ fontSize: 14,
24
+ fontWeight: FontWeight.normal,
25
+ color: Theme.of(context).primaryTextTheme.title.color,
26
+ ),
27
+ ),
28
+ ],
29
+ ),
30
+ const SizedBox(height: 24),
31
+ Center(
32
+ child: SingleChildScrollView(
33
+ scrollDirection: Axis.horizontal,
34
+ child: Container(
35
+ decoration: BoxDecoration(
36
+ borderRadius: BorderRadius.circular(30),
37
+ color: Theme.of(context).accentTextTheme.display2.color,
38
+ ),
39
+ child: Row(
40
+ mainAxisAlignment: MainAxisAlignment.center,
41
+ children: choicesListItem.items.map((dynamic e) {
42
+ final isSelected = choicesListItem.selectedItem == e;
43
+ return GestureDetector(
44
+ onTap: () {
45
+ choicesListItem.onItemSelected?.call(e);
46
+ },
47
+ child: Container(
48
+ padding: EdgeInsets.symmetric(horizontal: 32, vertical: 8),
49
+ decoration: BoxDecoration(
50
+ borderRadius: BorderRadius.circular(30),
51
+ color: isSelected ? Theme.of(context).accentTextTheme.body2.color : null,
52
+ ),
53
+ child: Text(
54
+ choicesListItem.displayItem?.call(e) ?? e.toString(),
55
+ style: TextStyle(
56
+ color: isSelected ? Colors.white : Theme.of(context).primaryTextTheme.caption.color,
57
+ fontWeight: isSelected ? FontWeight.w700 : FontWeight.normal,
58
+ ),
59
+ ),
60
+ ),
61
+ );
62
+ }).toList(),
63
+ ),
64
+ ),
65
+ ),
66
+ ),
67
+ ],
68
+ ),
69
+ );
70
+ }
71
+}
lib/src/screens/settings/widgets/settings_picker_cell.dart
+30
-19
@@ -2,7 +2,6 @@ import 'package:cake_wallet/utils/show_pop_up.dart';
2
import 'package:flutter/material.dart';
3
import 'package:cake_wallet/src/widgets/picker.dart';
4
import 'package:cake_wallet/src/widgets/standard_list.dart';
5
-import 'package:cake_wallet/generated/i18n.dart';
5
6
class SettingsPickerCell<ItemType> extends StandardListRow {
7
SettingsPickerCell(
@@ -10,29 +9,43 @@ class SettingsPickerCell<ItemType> extends StandardListRow {
9
@required this.displayItem,
10
this.selectedItem,
11
this.items,
12
+ this.images,
13
+ this.searchHintText,
14
+ this.isGridView = false,
15
+ this.matchingCriteria,
16
this.onItemSelected})
17
: super(
15
- title: title,
16
- isSelected: false,
17
- onTap: (BuildContext context) async {
18
- final selectedAtIndex = items.indexOf(selectedItem);
18
+ title: title,
19
+ isSelected: false,
20
+ onTap: (BuildContext context) async {
21
+ final selectedAtIndex = items.indexOf(selectedItem);
22
20
- await showPopUp<void>(
21
- context: context,
22
- builder: (_) => Picker(
23
- items: items,
24
- displayItem: displayItem,
25
- selectedAtIndex: selectedAtIndex,
26
- title: S.current.please_select,
27
- mainAxisAlignment: MainAxisAlignment.center,
28
- onItemSelected: (ItemType item) =>
29
- onItemSelected?.call(item)));
30
- });
23
+ await showPopUp<void>(
24
+ context: context,
25
+ builder: (_) => Picker(
26
+ items: items,
27
+ displayItem: displayItem,
28
+ selectedAtIndex: selectedAtIndex,
29
+ mainAxisAlignment: MainAxisAlignment.start,
30
+ onItemSelected: (ItemType item) => onItemSelected?.call(item),
31
+ images: images,
32
+ isSeparated: false,
33
+ hintText: searchHintText,
34
+ isGridView: isGridView,
35
+ matchingCriteria: matchingCriteria,
36
+ ),
37
+ );
38
+ },
39
+ );
40
41
final ItemType selectedItem;
42
final List<ItemType> items;
43
final void Function(ItemType item) onItemSelected;
44
final String Function(ItemType item) displayItem;
45
+ final List<Image> images;
46
+ final String searchHintText;
47
+ final bool isGridView;
48
+ final bool Function(ItemType, String) matchingCriteria;
49
50
@override
51
Widget buildTrailing(BuildContext context) {
@@ -40,9 +53,7 @@ class SettingsPickerCell<ItemType> extends StandardListRow {
53
displayItem?.call(selectedItem) ?? selectedItem.toString(),
54
textAlign: TextAlign.right,
55
style: TextStyle(
43
- fontSize: 14.0,
44
- fontWeight: FontWeight.w500,
45
- color: Theme.of(context).primaryTextTheme.overline.color),
56
+ fontSize: 14.0, fontWeight: FontWeight.w500, color: Theme.of(context).primaryTextTheme.overline.color),
57
);
58
}
59
}
lib/src/widgets/alert_background.dart
+13
-9
@@ -10,15 +10,19 @@ class AlertBackground extends StatelessWidget {
10
11
@override
12
Widget build(BuildContext context) {
13
- return Container(
14
- height: double.infinity,
15
- width: double.infinity,
16
- color: Colors.transparent,
17
- child: BackdropFilter(
18
- filter: ImageFilter.blur(sigmaX: 3.0, sigmaY: 3.0),
19
- child: Container(
20
- decoration: BoxDecoration(color: PaletteDark.darkNightBlue.withOpacity(0.75)),
21
- child: child,
13
+ return Scaffold(
14
+ resizeToAvoidBottomInset: false,
15
+ backgroundColor: Colors.transparent,
16
+ body: Container(
17
+ height: double.infinity,
18
+ width: double.infinity,
19
+ color: Colors.transparent,
20
+ child: BackdropFilter(
21
+ filter: ImageFilter.blur(sigmaX: 3.0, sigmaY: 3.0),
22
+ child: Container(
23
+ decoration: BoxDecoration(color: PaletteDark.darkNightBlue.withOpacity(0.75)),
24
+ child: child,
25
+ ),
26
),
27
),
28
);
lib/src/widgets/picker.dart
+245
-147
@@ -2,7 +2,6 @@ import 'dart:ui';
2
import 'package:flutter/cupertino.dart';
3
import 'package:flutter/material.dart';
4
import 'package:cake_wallet/src/widgets/alert_background.dart';
5
-import 'package:cake_wallet/src/widgets/cake_scrollbar.dart';
5
import 'package:cake_wallet/src/widgets/alert_close_button.dart';
6
import 'package:cake_wallet/palette.dart';
7
@@ -10,13 +9,19 @@ class Picker<Item extends Object> extends StatefulWidget {
9
Picker({
10
@required this.selectedAtIndex,
11
@required this.items,
13
- @required this.title,
12
@required this.onItemSelected,
13
+ this.title,
14
this.displayItem,
15
this.images,
16
this.description,
17
this.mainAxisAlignment = MainAxisAlignment.start,
19
- });
18
+ this.isGridView = false,
19
+ this.isSeparated = true,
20
+ this.hintText,
21
+ this.matchingCriteria,
22
+ }) : assert(hintText == null ||
23
+ matchingCriteria !=
24
+ null); // make sure that if the search field is enabled then there is a searching criteria provided
25
26
final int selectedAtIndex;
27
final List<Item> items;
@@ -26,6 +31,10 @@ class Picker<Item extends Object> extends StatefulWidget {
31
final Function(Item) onItemSelected;
32
final MainAxisAlignment mainAxisAlignment;
33
final String Function(Item) displayItem;
34
+ final bool isGridView;
35
+ final bool isSeparated;
36
+ final String hintText;
37
+ final bool Function(Item, String) matchingCriteria;
38
39
@override
40
PickerState createState() => PickerState<Item>(items, images, onItemSelected);
@@ -35,8 +44,10 @@ class PickerState<Item> extends State<Picker> {
44
PickerState(this.items, this.images, this.onItemSelected);
45
46
final Function(Item) onItemSelected;
38
- final List<Item> items;
39
- final List<Image> images;
47
+ List<Item> items;
48
+ List<Image> images;
49
+
50
+ final TextEditingController searchController = TextEditingController();
51
52
final closeButton = Image.asset(
53
'assets/images/close.png',
@@ -44,161 +55,248 @@ class PickerState<Item> extends State<Picker> {
55
);
56
ScrollController controller = ScrollController();
57
47
- final double backgroundHeight = 193;
48
- final double thumbHeight = 72;
49
- double fromTop = 0;
50
-
58
@override
52
- Widget build(BuildContext context) {
53
- controller.addListener(() {
54
- fromTop = controller.hasClients
55
- ? (controller.offset /
56
- controller.position.maxScrollExtent *
57
- (backgroundHeight - thumbHeight))
58
- : 0;
59
+ void initState() {
60
+ super.initState();
61
+
62
+ searchController.addListener(() {
63
+ items = [];
64
+ images = [];
65
+ for (int i=0;i<widget.items.length;i++) {
66
+ if (widget.matchingCriteria?.call(widget.items[i], searchController.text) ?? true) {
67
+ items.add(widget.items[i] as Item);
68
+ images.add(widget.images[i]);
69
+ }
70
+ }
71
setState(() {});
72
});
73
+ }
74
62
- final isShowScrollThumb = items != null ? items.length > 3 : false;
63
-
75
+ @override
76
+ Widget build(BuildContext context) {
77
return AlertBackground(
65
- child: Stack(
66
- alignment: Alignment.center,
67
- children: <Widget>[
68
- Column(
69
- mainAxisSize: MainAxisSize.min,
70
- children: <Widget>[
71
- Container(
72
- padding: EdgeInsets.only(left: 24, right: 24),
73
- child: Text(
74
- widget.title,
75
- textAlign: TextAlign.center,
76
- style: TextStyle(
77
- fontSize: 18,
78
- fontFamily: 'Lato',
79
- fontWeight: FontWeight.bold,
80
- decoration: TextDecoration.none,
81
- color: Colors.white),
82
- ),
83
- ),
84
- Padding(
85
- padding: EdgeInsets.only(left: 24, right: 24, top: 24),
86
- child: GestureDetector(
87
- onTap: () => null,
88
- child: ClipRRect(
89
- borderRadius: BorderRadius.all(Radius.circular(14)),
90
- child: Container(
91
- height: 233,
78
+ child: Stack(
79
+ alignment: Alignment.center,
80
+ children: <Widget>[
81
+ Column(
82
+ mainAxisSize: MainAxisSize.min,
83
+ children: <Widget>[
84
+ if (widget.title?.isNotEmpty ?? false)
85
+ Container(
86
+ padding: EdgeInsets.symmetric(horizontal: 24),
87
+ child: Text(
88
+ widget.title,
89
+ textAlign: TextAlign.center,
90
+ style: TextStyle(
91
+ fontSize: 18,
92
+ fontFamily: 'Lato',
93
+ fontWeight: FontWeight.bold,
94
+ decoration: TextDecoration.none,
95
+ color: Colors.white,
96
+ ),
97
+ ),
98
+ ),
99
+ Padding(
100
+ padding: EdgeInsets.only(left: 24, right: 24, top: 24),
101
+ child: GestureDetector(
102
+ onTap: () => null,
103
+ child: ClipRRect(
104
+ borderRadius: BorderRadius.all(Radius.circular(30)),
105
+ child: Container(
106
color: Theme.of(context).accentTextTheme.title.color,
93
- child: Stack(
94
- alignment: Alignment.center,
95
- children: <Widget>[
96
- ListView.separated(
97
- padding: EdgeInsets.all(0),
98
- controller: controller,
99
- separatorBuilder: (context, index) => Divider(
100
- color: Theme.of(context)
101
- .accentTextTheme
102
- .title
103
- .backgroundColor,
107
+ child: ConstrainedBox(
108
+ constraints: BoxConstraints(
109
+ maxHeight: MediaQuery.of(context).size.height * 0.65,
110
+ ),
111
+ child: Column(
112
+ mainAxisSize: MainAxisSize.min,
113
+ children: [
114
+ if (widget.hintText != null)
115
+ Padding(
116
+ padding: const EdgeInsets.all(16),
117
+ child: TextFormField(
118
+ controller: searchController,
119
+ style: TextStyle(color: Theme.of(context).primaryTextTheme.title.color),
120
+ decoration: InputDecoration(
121
+ hintText: widget.hintText,
122
+ prefixIcon: Image.asset("assets/images/search_icon.png"),
123
+ filled: true,
124
+ fillColor: Theme.of(context).accentTextTheme.display2.color,
125
+ alignLabelWithHint: false,
126
+ contentPadding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16),
127
+ enabledBorder: OutlineInputBorder(
128
+ borderRadius: BorderRadius.circular(14),
129
+ borderSide: const BorderSide(
130
+ color: Colors.transparent,
131
+ )),
132
+ focusedBorder: OutlineInputBorder(
133
+ borderRadius: BorderRadius.circular(14),
134
+ borderSide: const BorderSide(
135
+ color: Colors.transparent,
136
+ )),
137
+ ),
138
+ ),
139
+ ),
140
+ Divider(
141
+ color: Theme.of(context).accentTextTheme.title.backgroundColor,
142
height: 1,
143
),
106
- itemCount: items == null ? 0 : items.length,
107
- itemBuilder: (context, index) {
108
- final item = items[index];
109
- final image =
110
- images != null ? images[index] : null;
111
- final isItemSelected =
112
- index == widget.selectedAtIndex;
113
-
114
- final color = isItemSelected
115
- ? Theme.of(context).textTheme.body2.color
116
- : Theme.of(context)
117
- .accentTextTheme
118
- .title
119
- .color;
120
- final textColor = isItemSelected
121
- ? Palette.blueCraiola
122
- : Theme.of(context)
123
- .primaryTextTheme
124
- .title
125
- .color;
126
-
127
- return GestureDetector(
128
- onTap: () {
129
- if (onItemSelected == null) {
130
- return;
131
- }
132
- Navigator.of(context).pop();
133
- onItemSelected(item);
134
- },
135
- child: Container(
136
- height: 77,
137
- padding: EdgeInsets.only(left: 24, right: 24),
138
- color: color,
139
- child: Row(
140
- mainAxisSize: MainAxisSize.max,
141
- mainAxisAlignment: widget.mainAxisAlignment,
142
- crossAxisAlignment:
143
- CrossAxisAlignment.center,
144
- children: <Widget>[
145
- image ?? Offstage(),
146
- Padding(
147
- padding: EdgeInsets.only(
148
- left: image != null ? 12 : 0),
149
- child: Text(
150
- widget.displayItem?.call(item) ??
151
- item.toString(),
152
- style: TextStyle(
153
- fontSize: 18,
154
- fontFamily: 'Lato',
155
- fontWeight: FontWeight.w600,
156
- color: textColor,
157
- decoration: TextDecoration.none,
144
+ if (widget.selectedAtIndex != -1) buildSelectedItem(),
145
+ Flexible(
146
+ child: Stack(
147
+ alignment: Alignment.center,
148
+ children: <Widget>[
149
+ (items?.length ?? 0) > 3 ? Scrollbar(
150
+ controller: controller,
151
+ child: itemsList(),
152
+ ) : itemsList(),
153
+ (widget.description?.isNotEmpty ?? false)
154
+ ? Positioned(
155
+ bottom: 24,
156
+ left: 24,
157
+ right: 24,
158
+ child: Text(
159
+ widget.description,
160
+ textAlign: TextAlign.center,
161
+ style: TextStyle(
162
+ fontSize: 12,
163
+ fontWeight: FontWeight.w500,
164
+ fontFamily: 'Lato',
165
+ decoration: TextDecoration.none,
166
+ color: Theme.of(context).primaryTextTheme.title.color,
167
+ ),
168
),
159
- ),
160
- )
161
- ],
162
- ),
163
- ),
164
- );
165
- },
166
- ),
167
- ((widget.description != null) &&
168
- (widget.description.isNotEmpty))
169
- ? Positioned(
170
- bottom: 24,
171
- left: 24,
172
- right: 24,
173
- child: Text(
174
- widget.description,
175
- textAlign: TextAlign.center,
176
- style: TextStyle(
177
- fontSize: 12,
178
- fontWeight: FontWeight.w500,
179
- fontFamily: 'Lato',
180
- decoration: TextDecoration.none,
181
- color: Theme.of(context)
182
- .primaryTextTheme
183
- .title
184
- .color),
185
- ))
186
- : Offstage(),
187
- isShowScrollThumb
188
- ? CakeScrollbar(
189
- backgroundHeight: backgroundHeight,
190
- thumbHeight: thumbHeight,
191
- fromTop: fromTop)
192
- : Offstage(),
193
- ],
194
- )),
169
+ )
170
+ : Offstage(),
171
+ ],
172
+ ),
173
+ ),
174
+ ],
175
+ ),
176
+ ),
177
+ ),
178
+ ),
179
),
180
+ )
181
+ ],
182
+ ),
183
+ AlertCloseButton(image: closeButton)
184
+ ],
185
+ ),
186
+ );
187
+ }
188
+
189
+ Widget itemsList() {
190
+ return Container(
191
+ color: Theme.of(context).accentTextTheme.headline6.backgroundColor,
192
+ child: widget.isGridView
193
+ ? GridView.builder(
194
+ padding: EdgeInsets.zero,
195
+ controller: controller,
196
+ itemCount: items == null || items.isEmpty ? 0 : items.length,
197
+ gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
198
+ crossAxisCount: 2,
199
+ crossAxisSpacing: 2,
200
+ childAspectRatio: 3,
201
),
202
+ itemBuilder: (context, index) => buildItem(index),
203
)
204
+ : ListView.separated(
205
+ padding: EdgeInsets.zero,
206
+ controller: controller,
207
+ shrinkWrap: true,
208
+ separatorBuilder: (context, index) => widget.isSeparated
209
+ ? Divider(
210
+ color: Theme.of(context).accentTextTheme.title.backgroundColor,
211
+ height: 1,
212
+ )
213
+ : const SizedBox(),
214
+ itemCount: items == null || items.isEmpty ? 0 : items.length,
215
+ itemBuilder: (context, index) => buildItem(index),
216
+ ),
217
+ );
218
+ }
219
+
220
+ Widget buildItem(int index) {
221
+ /// don't show selected item in the list view
222
+ if (widget.items[widget.selectedAtIndex] == items[index] && !widget.isGridView) {
223
+ return const SizedBox();
224
+ }
225
+
226
+ final item = items[index];
227
+ final image = images != null ? images[index] : null;
228
+
229
+ return GestureDetector(
230
+ onTap: () {
231
+ if (onItemSelected == null) {
232
+ return;
233
+ }
234
+ Navigator.of(context).pop();
235
+ onItemSelected(item);
236
+ },
237
+ child: Container(
238
+ height: 55,
239
+ color: Theme.of(context).accentTextTheme.headline6.color,
240
+ padding: EdgeInsets.only(left: 24, right: 24),
241
+ child: Row(
242
+ mainAxisSize: MainAxisSize.max,
243
+ mainAxisAlignment: widget.mainAxisAlignment,
244
+ crossAxisAlignment: CrossAxisAlignment.center,
245
+ children: <Widget>[
246
+ image ?? Offstage(),
247
+ Expanded(
248
+ child: Padding(
249
+ padding: EdgeInsets.only(left: image != null ? 12 : 0),
250
+ child: Text(
251
+ widget.displayItem?.call(item) ?? item.toString(),
252
+ style: TextStyle(
253
+ fontSize: 14,
254
+ fontFamily: 'Lato',
255
+ fontWeight: FontWeight.w600,
256
+ color: Theme.of(context).primaryTextTheme.title.color,
257
+ decoration: TextDecoration.none,
258
+ ),
259
+ ),
260
+ ),
261
+ ),
262
],
263
),
200
- AlertCloseButton(image: closeButton)
201
- ],
202
- ));
264
+ ),
265
+ );
266
+ }
267
+
268
+ Widget buildSelectedItem() {
269
+ final item = widget.items[widget.selectedAtIndex];
270
+ final image = images != null ? widget.images[widget.selectedAtIndex] : null;
271
+
272
+ return Container(
273
+ height: 55,
274
+ color: Theme.of(context).accentTextTheme.headline6.color,
275
+ padding: EdgeInsets.only(left: 24, right: 24),
276
+ child: Row(
277
+ mainAxisSize: MainAxisSize.max,
278
+ mainAxisAlignment: widget.mainAxisAlignment,
279
+ crossAxisAlignment: CrossAxisAlignment.center,
280
+ children: <Widget>[
281
+ image ?? Offstage(),
282
+ Expanded(
283
+ child: Padding(
284
+ padding: EdgeInsets.only(left: image != null ? 12 : 0),
285
+ child: Text(
286
+ widget.displayItem?.call(item) ?? item.toString(),
287
+ style: TextStyle(
288
+ fontSize: 16,
289
+ fontFamily: 'Lato',
290
+ fontWeight: FontWeight.w700,
291
+ color: Theme.of(context).primaryTextTheme.title.color,
292
+ decoration: TextDecoration.none,
293
+ ),
294
+ ),
295
+ ),
296
+ ),
297
+ Icon(Icons.check_circle, color: Theme.of(context).accentTextTheme.body2.color),
298
+ ],
299
+ ),
300
+ );
301
}
302
}
lib/src/widgets/standard_list.dart
+9
-5
@@ -37,11 +37,15 @@ class StandardListRow extends StatelessWidget {
37
return Expanded(
38
child: Row(mainAxisAlignment: MainAxisAlignment.start, children: [
39
if (hasLeftOffset) SizedBox(width: 10),
40
- Text(title,
41
- style: TextStyle(
42
- fontSize: 14,
43
- fontWeight: FontWeight.normal,
44
- color: titleColor(context)))
40
+ Expanded(
41
+ child: Text(title,
42
+ style: TextStyle(
43
+ fontSize: 14,
44
+ fontWeight: FontWeight.normal,
45
+ color: titleColor(context),
46
+ ),
47
+ ),
48
+ )
49
]));
50
}
51
lib/src/widgets/standart_switch.dart
+1
-1
@@ -24,7 +24,7 @@ class StandartSwitchState extends State<StandartSwitch> {
24
height: 28,
25
decoration: BoxDecoration(
26
color: widget.value
27
- ? Colors.green
27
+ ? Theme.of(context).accentTextTheme.body2.color
28
: Theme.of(context).accentTextTheme.display4.color,
29
borderRadius: BorderRadius.all(Radius.circular(14.0))),
30
child: Container(
lib/themes/bright_theme.dart
+8
@@ -78,6 +78,14 @@ class BrightTheme extends ThemeBase {
78
decorationColor: Colors.white, // menu background
79
)
80
),
81
+ scrollbarTheme: ScrollbarThemeData(
82
+ thumbColor: MaterialStateProperty.all(Palette.moderatePurpleBlue),
83
+ trackColor: MaterialStateProperty.all(Palette.periwinkleCraiola),
84
+ radius: Radius.circular(3),
85
+ thickness: MaterialStateProperty.all(6),
86
+ isAlwaysShown: true,
87
+ crossAxisMargin: 6,
88
+ ),
89
primaryTextTheme: TextTheme(
90
title: TextStyle(
91
color: Palette.darkBlueCraiola, // title color
lib/themes/dark_theme.dart
+8
@@ -77,6 +77,14 @@ class DarkTheme extends ThemeBase {
77
decorationColor: PaletteDark.deepPurpleBlue, // menu background
78
)
79
),
80
+ scrollbarTheme: ScrollbarThemeData(
81
+ thumbColor: MaterialStateProperty.all(PaletteDark.wildBlueGrey),
82
+ trackColor: MaterialStateProperty.all(PaletteDark.violetBlue),
83
+ radius: Radius.circular(3),
84
+ thickness: MaterialStateProperty.all(6),
85
+ isAlwaysShown: true,
86
+ crossAxisMargin: 6,
87
+ ),
88
primaryTextTheme: TextTheme(
89
title: TextStyle(
90
color: Colors.white, // title color
lib/themes/light_theme.dart
+8
@@ -78,6 +78,14 @@ class LightTheme extends ThemeBase {
78
decorationColor: Colors.white, // menu background
79
)
80
),
81
+ scrollbarTheme: ScrollbarThemeData(
82
+ thumbColor: MaterialStateProperty.all(Palette.moderatePurpleBlue),
83
+ trackColor: MaterialStateProperty.all(Palette.periwinkleCraiola),
84
+ radius: Radius.circular(3),
85
+ thickness: MaterialStateProperty.all(6),
86
+ isAlwaysShown: true,
87
+ crossAxisMargin: 6,
88
+ ),
89
primaryTextTheme: TextTheme(
90
title: TextStyle(
91
color: Palette.darkBlueCraiola, // title color
lib/themes/theme_list.dart
+1
-1
@@ -4,7 +4,7 @@ import 'package:cake_wallet/themes/light_theme.dart';
4
import 'package:cake_wallet/themes/theme_base.dart';
5
6
class ThemeList {
7
- static final all = [lightTheme, brightTheme, darkTheme];
7
+ static final all = [brightTheme, lightTheme, darkTheme];
8
9
static final lightTheme = LightTheme(raw: 0);
10
static final brightTheme = BrightTheme(raw: 1);
lib/view_model/settings/choices_list_item.dart
new
+25
@@ -0,0 +1,25 @@
1
+import 'package:flutter/foundation.dart';
2
+import 'package:cake_wallet/view_model/settings/settings_list_item.dart';
3
+import 'package:flutter/material.dart';
4
+
5
+class ChoicesListItem<ItemType> extends SettingsListItem {
6
+ ChoicesListItem(
7
+ {@required String title,
8
+ @required this.selectedItem,
9
+ @required this.items,
10
+ this.displayItem,
11
+ void Function(ItemType item) onItemSelected})
12
+ : _onItemSelected = onItemSelected,
13
+ super(title);
14
+
15
+ final ItemType selectedItem;
16
+ final List<ItemType> items;
17
+ final String Function(ItemType item) displayItem;
18
+ final void Function(ItemType item) _onItemSelected;
19
+
20
+ void onItemSelected(dynamic item) {
21
+ if (item is ItemType) {
22
+ _onItemSelected?.call(item);
23
+ }
24
+ }
25
+}
lib/view_model/settings/picker_list_item.dart
+18
-1
@@ -1,5 +1,6 @@
1
import 'package:flutter/foundation.dart';
2
import 'package:cake_wallet/view_model/settings/settings_list_item.dart';
3
+import 'package:flutter/material.dart';
4
5
class PickerListItem<ItemType> extends SettingsListItem {
6
PickerListItem(
@@ -7,18 +8,34 @@ class PickerListItem<ItemType> extends SettingsListItem {
8
@required this.selectedItem,
9
@required this.items,
10
this.displayItem,
10
- void Function(ItemType item) onItemSelected})
11
+ this.images,
12
+ this.searchHintText,
13
+ this.isGridView = false,
14
+ void Function(ItemType item) onItemSelected,
15
+ bool Function(ItemType item, String searchText) matchingCriteria})
16
: _onItemSelected = onItemSelected,
17
+ _matchingCriteria = matchingCriteria,
18
super(title);
19
20
final ItemType Function() selectedItem;
21
final List<ItemType> items;
22
final String Function(ItemType item) displayItem;
23
final void Function(ItemType item) _onItemSelected;
24
+ final List<Image> images;
25
+ final String searchHintText;
26
+ final bool isGridView;
27
+ final bool Function(ItemType, String) _matchingCriteria;
28
29
void onItemSelected(dynamic item) {
30
if (item is ItemType) {
31
_onItemSelected?.call(item);
32
}
33
}
34
+
35
+ bool matchingCriteria(dynamic item, String searchText) {
36
+ if (item is ItemType) {
37
+ return _matchingCriteria?.call(item, searchText);
38
+ }
39
+ return true;
40
+ }
41
}
lib/view_model/settings/settings_view_model.dart
+51
-23
@@ -1,6 +1,7 @@
1
+import 'package:cake_wallet/di.dart';
2
+import 'package:cake_wallet/entities/language_service.dart';
3
import 'package:cake_wallet/store/yat/yat_store.dart';
2
-import 'package:cake_wallet/utils/show_pop_up.dart';
3
-import 'package:cake_wallet/view_model/settings/link_list_item.dart';
4
+import 'package:cake_wallet/view_model/settings/choices_list_item.dart';
5
import 'package:flutter/cupertino.dart';
6
import 'package:mobx/mobx.dart';
7
import 'package:package_info/package_info.dart';
@@ -75,7 +76,7 @@ abstract class SettingsViewModelBase with Store {
76
//var connectYatUrl = YatLink.baseUrl + YatLink.signInSuffix;
77
//final connectYatUrlParameters =
78
// _yatStore.defineQueryParameters();
78
-
79
+
80
//if (connectYatUrlParameters.isNotEmpty) {
81
// connectYatUrl += YatLink.queryParameter + connectYatUrlParameters;
82
//}
@@ -83,7 +84,7 @@ abstract class SettingsViewModelBase with Store {
84
//var manageYatUrl = YatLink.baseUrl + YatLink.managePath;
85
//final manageYatUrlParameters =
86
// _yatStore.defineQueryParameters();
86
-
87
+
88
//if (manageYatUrlParameters.isNotEmpty) {
89
// manageYatUrl += YatLink.queryParameter + manageYatUrlParameters;
90
//}
@@ -91,27 +92,41 @@ abstract class SettingsViewModelBase with Store {
92
//var createNewYatUrl = YatLink.startFlowUrl;
93
//final createNewYatUrlParameters =
94
// _yatStore.defineQueryParameters();
94
-
95
+
96
//if (createNewYatUrlParameters.isNotEmpty) {
97
// createNewYatUrl += '?sub1=' + createNewYatUrlParameters;
98
//}
99
99
-
100
+
101
sections = [
102
[
102
- PickerListItem(
103
- title: S.current.settings_display_balance_as,
104
- items: BalanceDisplayMode.all,
105
- selectedItem: () => balanceDisplayMode,
106
- onItemSelected: (BalanceDisplayMode mode) =>
107
- _settingsStore.balanceDisplayMode = mode),
103
+ SwitcherListItem(
104
+ title: S.current.settings_display_balance,
105
+ value: () => balanceDisplayMode == BalanceDisplayMode.displayableBalance,
106
+ onValueChange: (_, bool value) {
107
+ if (value) {
108
+ _settingsStore.balanceDisplayMode = BalanceDisplayMode.displayableBalance;
109
+ } else {
110
+ _settingsStore.balanceDisplayMode = BalanceDisplayMode.hiddenBalance;
111
+ }
112
+ },
113
+ ),
114
if (!isHaven)
115
PickerListItem(
116
title: S.current.settings_currency,
117
+ searchHintText: S.current.search_currency,
118
items: FiatCurrency.all,
119
selectedItem: () => fiatCurrency,
120
onItemSelected: (FiatCurrency currency) =>
114
- setFiatCurrency(currency)),
121
+ setFiatCurrency(currency),
122
+ images: FiatCurrency.all.map(
123
+ (e) => Image.asset("assets/images/flags/${e.countryCode}.png"))
124
+ .toList(),
125
+ isGridView: true,
126
+ matchingCriteria: (FiatCurrency currency, String searchText) {
127
+ return currency.title.toLowerCase().contains(searchText) || currency.fullName.toLowerCase().contains(searchText);
128
+ },
129
+ ),
130
PickerListItem(
131
title: S.current.settings_fee_priority,
132
items: priorityForWalletType(wallet.type),
@@ -150,10 +165,23 @@ abstract class SettingsViewModelBase with Store {
165
}
166
});
167
}),
153
- RegularListItem(
154
- title: S.current.settings_change_language,
155
- handler: (BuildContext context) =>
156
- Navigator.of(context).pushNamed(Routes.changeLanguage),
168
+ PickerListItem(
169
+ title: S.current.settings_change_language,
170
+ searchHintText: S.current.search_language,
171
+ items: LanguageService.list.keys.toList(),
172
+ displayItem: (dynamic code) {
173
+ return LanguageService.list[code];
174
+ },
175
+ selectedItem: () => getIt.get<SettingsStore>().languageCode,
176
+ onItemSelected: (String code) {
177
+ getIt.get<SettingsStore>().languageCode = code;
178
+ },
179
+ images: LanguageService.list.keys.map(
180
+ (e) => Image.asset("assets/images/flags/${LanguageService.localeCountryCode[e]}.png"))
181
+ .toList(),
182
+ matchingCriteria: (String code, String searchText) {
183
+ return LanguageService.list[code].toLowerCase().contains(searchText);
184
+ },
185
),
186
SwitcherListItem(
187
title: S.current.settings_allow_biometrical_authentication,
@@ -180,12 +208,12 @@ abstract class SettingsViewModelBase with Store {
208
setAllowBiometricalAuthentication(value);
209
}
210
}),
183
- PickerListItem(
184
- title: S.current.color_theme,
185
- items: ThemeList.all,
186
- selectedItem: () => theme,
187
- onItemSelected: (ThemeBase theme) =>
188
- _settingsStore.currentTheme = theme)
211
+ ChoicesListItem(
212
+ title: S.current.color_theme,
213
+ items: ThemeList.all,
214
+ selectedItem: theme,
215
+ onItemSelected: (ThemeBase theme) => _settingsStore.currentTheme = theme,
216
+ ),
217
],
218
//[
219
//if (_yatStore.emoji.isNotEmpty) ...[
pubspec_base.yaml
+1
@@ -76,6 +76,7 @@ flutter:
76
77
assets:
78
- assets/images/
79
+ - assets/images/flags/
80
- assets/node_list.yml
81
- assets/haven_node_list.yml
82
- assets/bitcoin_electrum_server_list.yml
res/values/strings_de.arb
+3
-1
@@ -228,7 +228,7 @@
228
"settings_nodes" : "Knoten",
229
"settings_current_node" : "Aktueller Knoten",
230
"settings_wallets" : "Wallets",
231
- "settings_display_balance_as" : "Kontostand anzeigen in",
231
+ "settings_display_balance" : "Kontostand anzeigen",
232
"settings_currency" : "Währung",
233
"settings_fee_priority" : "Gebührenpriorität",
234
"settings_save_recipient_address" : "Empfängeradresse speichern",
@@ -530,6 +530,8 @@
530
"third_intro_content" : "Yats leben auch außerhalb von Cake Wallet. Jede Wallet-Adresse auf der Welt kann durch ein Yat ersetzt werden!",
531
"learn_more" : "Erfahren Sie mehr",
532
"search": "Suche",
533
+ "search_language": "Sprache suchen",
534
+ "search_currency": "Währung suchen",
535
"new_template" : "neue Vorlage",
536
"electrum_address_disclaimer": "Wir generieren jedes Mal neue Adressen, wenn Sie eine verwenden, aber vorherige Adressen funktionieren weiterhin"
537
}
res/values/strings_en.arb
+3
-1
@@ -228,7 +228,7 @@
228
"settings_nodes" : "Nodes",
229
"settings_current_node" : "Current node",
230
"settings_wallets" : "Wallets",
231
- "settings_display_balance_as" : "Display balance as",
231
+ "settings_display_balance" : "Display balance",
232
"settings_currency" : "Currency",
233
"settings_fee_priority" : "Fee priority",
234
"settings_save_recipient_address" : "Save recipient address",
@@ -530,6 +530,8 @@
530
"third_intro_content" : "Yats live outside of Cake Wallet, too. Any wallet address on earth can be replaced with a Yat!",
531
"learn_more" : "Learn More",
532
"search": "Search",
533
+ "search_language": "Search language",
534
+ "search_currency": "Search currency",
535
"new_template" : "New Template",
536
"electrum_address_disclaimer": "We generate new addresses each time you use one, but previous addresses continue to work"
537
}
res/values/strings_es.arb
+3
-1
@@ -228,7 +228,7 @@
228
"settings_nodes" : "Nodos",
229
"settings_current_node" : "Nodo actual",
230
"settings_wallets" : "Carteras",
231
- "settings_display_balance_as" : "Mostrar saldo como",
231
+ "settings_display_balance" : "Mostrar saldo",
232
"settings_currency" : "Moneda",
233
"settings_fee_priority" : "Prioridad de tasa",
234
"settings_save_recipient_address" : "Guardar dirección del destinatario",
@@ -530,6 +530,8 @@
530
"third_intro_content" : "Los Yats también viven fuera de Cake Wallet. Cualquier dirección de billetera en la tierra se puede reemplazar con un Yat!",
531
"learn_more" : "Aprende más",
532
"search": "Búsqueda",
533
+ "search_language": "Idioma de búsqueda",
534
+ "search_currency": "Moneda de búsqueda",
535
"new_template" : "Nueva plantilla",
536
"electrum_address_disclaimer": "Generamos nuevas direcciones cada vez que usa una, pero las direcciones anteriores siguen funcionando"
537
}
res/values/strings_fr.arb
+4
-2
@@ -226,7 +226,7 @@
226
"settings_nodes" : "Nœuds",
227
"settings_current_node" : "Nœud actuel",
228
"settings_wallets" : "Portefeuilles",
229
- "settings_display_balance_as" : "Afficher le solde en",
229
+ "settings_display_balance" : "Afficher le solde",
230
"settings_currency" : "Devise",
231
"settings_fee_priority" : "Priorité des frais",
232
"settings_save_recipient_address" : "Sauvegarder l'adresse du bénéficiaire",
@@ -527,7 +527,9 @@
527
"third_intro_title" : "Yat joue bien avec les autres",
528
"third_intro_content" : "Les Yats existent aussi en dehors de Cake Wallet. Toute adresse sur terre peut être remplacée par un Yat !",
529
"learn_more" : "En savoir plus",
530
-
530
+ "search": "Chercher",
531
+ "search_language": "Langue de recherche",
532
+ "search_currency": "Devise de recherche",
533
"new_template" : "Nouveau Modèle",
534
"electrum_address_disclaimer": "Nous générons de nouvelles adresses à chaque fois que vous en utilisez une, mais les adresses précédentes continuent à fonctionner"
535
}
res/values/strings_hi.arb
+3
-1
@@ -228,7 +228,7 @@
228
"settings_nodes" : "नोड्स",
229
"settings_current_node" : "वर्तमान नोड",
230
"settings_wallets" : "पर्स",
231
- "settings_display_balance_as" : "के रूप में संतुलन प्रदर्शित करें",
231
+ "settings_display_balance" : "प्रदर्शन संतुलन",
232
"settings_currency" : "मुद्रा",
233
"settings_fee_priority" : "शुल्क प्राथमिकता",
234
"settings_save_recipient_address" : "प्राप्तकर्ता का पता सहेजें",
@@ -530,6 +530,8 @@
530
"third_intro_content" : "Yats Cake Wallet के बाहर भी रहता है। धरती पर किसी भी वॉलेट पते को Yat से बदला जा सकता है!",
531
"learn_more" : "और अधिक जानें",
532
"search": "खोज",
533
+ "search_language": "भाषा खोजें",
534
+ "search_currency": "मुद्रा खोजें",
535
"new_template" : "नया टेम्पलेट",
536
"electrum_address_disclaimer": "हर बार जब आप एक का उपयोग करते हैं तो हम नए पते उत्पन्न करते हैं, लेकिन पिछले पते काम करना जारी रखते हैं"
537
}
res/values/strings_hr.arb
+3
-1
@@ -228,7 +228,7 @@
228
"settings_nodes" : "Nodovi",
229
"settings_current_node" : "Trenutni node",
230
"settings_wallets" : "Novčanik",
231
- "settings_display_balance_as" : "Prikaži stanje računa kao",
231
+ "settings_display_balance" : "Prikaži stanje računa",
232
"settings_currency" : "Valuta",
233
"settings_fee_priority" : "Prioritet naknade",
234
"settings_save_recipient_address" : "Spremi primateljevu adresu",
@@ -530,6 +530,8 @@
530
"third_intro_content" : "Yats žive i izvan Cake Wallet -a. Bilo koja adresa novčanika na svijetu može se zamijeniti Yat!",
531
"learn_more" : "Saznajte više",
532
"search": "Traži",
533
+ "search_language": "Jezik pretraživanja",
534
+ "search_currency": "Traži valutu",
535
"new_template" : "novi predložak",
536
"electrum_address_disclaimer": "Minden egyes alkalommal új címeket generálunk, de a korábbi címek továbbra is működnek"
537
}
res/values/strings_it.arb
+3
-1
@@ -228,7 +228,7 @@
228
"settings_nodes" : "Nodi",
229
"settings_current_node" : "Nodo attuale",
230
"settings_wallets" : "Portafogli",
231
- "settings_display_balance_as" : "Mostra saldo come",
231
+ "settings_display_balance" : "Mostra saldo",
232
"settings_currency" : "Moneta",
233
"settings_fee_priority" : "Priorità commissione",
234
"settings_save_recipient_address" : "Salva indirizzo di destinazione",
@@ -530,6 +530,8 @@
530
"third_intro_content" : "Anche Yats vive fuori da Cake Wallet. Qualsiasi indirizzo di portafoglio sulla terra può essere sostituito con un Yat!",
531
"learn_more" : "Impara di più",
532
"search": "Ricerca",
533
+ "search_language": "Cerca lingua",
534
+ "search_currency": "Cerca valuta",
535
"new_template" : "Nuovo modello",
536
"electrum_address_disclaimer": "Generiamo nuovi indirizzi ogni volta che ne utilizzi uno, ma gli indirizzi precedenti continuano a funzionare"
537
}
res/values/strings_ja.arb
+3
-1
@@ -228,7 +228,7 @@
228
"settings_nodes" : "ノード",
229
"settings_current_node" : "現在のノード",
230
"settings_wallets" : "財布",
231
- "settings_display_balance_as" : "残高を表示",
231
+ "settings_display_balance" : "ディスプレイバランス",
232
"settings_currency" : "通貨",
233
"settings_fee_priority" : "料金優先",
234
"settings_save_recipient_address" : "受信者のアドレスを保存",
@@ -530,6 +530,8 @@
530
"third_intro_content" : "YatsはCakeWalletの外にも住んでいます。 地球上のどのウォレットアドレスもYatに置き換えることができます!",
531
"learn_more" : "もっと詳しく知る",
532
"search": "検索",
533
+ "search_language": "検索言語",
534
+ "search_currency": "検索通貨",
535
"new_template" : "新しいテンプレート",
536
"electrum_address_disclaimer": "使用するたびに新しいアドレスが生成されますが、以前のアドレスは引き続き機能します"
537
}
res/values/strings_ko.arb
+3
-1
@@ -228,7 +228,7 @@
228
"settings_nodes" : "노드",
229
"settings_current_node" : "현재 노드",
230
"settings_wallets" : "지갑",
231
- "settings_display_balance_as" : "잔액 표시",
231
+ "settings_display_balance" : "디스플레이 잔액",
232
"settings_currency" : "통화",
233
"settings_fee_priority" : "수수료 우선",
234
"settings_save_recipient_address" : "수신자 주소 저장",
@@ -530,6 +530,8 @@
530
"third_intro_content" : "Yats는 Cake Wallet 밖에서도 살고 있습니다. 지구상의 모든 지갑 주소는 Yat!",
531
"learn_more" : "더 알아보기",
532
"search": "찾다",
533
+ "search_language": "검색 언어",
534
+ "search_currency": "통화 검색",
535
"new_template" : "새 템플릿",
536
"electrum_address_disclaimer": "사용할 때마다 새 주소가 생성되지만 이전 주소는 계속 작동합니다."
537
}
res/values/strings_nl.arb
+3
-1
@@ -228,7 +228,7 @@
228
"settings_nodes" : "knooppunten",
229
"settings_current_node" : "Huidige knooppunt",
230
"settings_wallets" : "Portemonnee",
231
- "settings_display_balance_as" : "Toon saldo als",
231
+ "settings_display_balance" : "Saldo weergeven",
232
"settings_currency" : "Valuta",
233
"settings_fee_priority" : "Tariefprioriteit",
234
"settings_save_recipient_address" : "Adres ontvanger opslaan",
@@ -530,6 +530,8 @@
530
"third_intro_content" : "Yats wonen ook buiten Cake Wallet. Elk portemonnee-adres op aarde kan worden vervangen door een Yat!",
531
"learn_more" : "Kom meer te weten",
532
"search": "Zoekopdracht",
533
+ "search_language": "Zoektaal",
534
+ "search_currency": "Zoek valuta",
535
"new_template" : "Nieuwe sjabloon",
536
"electrum_address_disclaimer": "We generate new addresses each time you use one, but previous addresses continue to work"
537
}
res/values/strings_pl.arb
+3
-1
@@ -228,7 +228,7 @@
228
"settings_nodes" : "Węzły",
229
"settings_current_node" : "Bieżący węzeł",
230
"settings_wallets" : "Portfele",
231
- "settings_display_balance_as" : "Wyświetl saldo jako",
231
+ "settings_display_balance" : "Wyświetl saldo",
232
"settings_currency" : "Waluta",
233
"settings_fee_priority" : "Priorytet opłaty",
234
"settings_save_recipient_address" : "Zapisz adres odbiorcy",
@@ -530,6 +530,8 @@
530
"third_intro_content" : "Yats mieszkają również poza Cake Wallet. Każdy adres portfela na ziemi można zastąpić Yat!",
531
"learn_more" : "Ucz się więcej",
532
"search": "Szukaj",
533
+ "search_language": "Wyszukaj język",
534
+ "search_currency": "Wyszukaj walutę",
535
"new_template" : "Nowy szablon",
536
"electrum_address_disclaimer": "Za każdym razem, gdy korzystasz z jednego z nich, generujemy nowe adresy, ale poprzednie adresy nadal działają"
537
}
res/values/strings_pt.arb
+3
-1
@@ -228,7 +228,7 @@
228
"settings_nodes" : "Nós",
229
"settings_current_node" : "Nó atual",
230
"settings_wallets" : "Carteiras",
231
- "settings_display_balance_as" : "Saldo a exibir",
231
+ "settings_display_balance" : "Exibir saldo",
232
"settings_currency" : "Moeda",
233
"settings_fee_priority" : "Prioridade da taxa",
234
"settings_save_recipient_address" : "Salvar endereço do destinatário",
@@ -530,6 +530,8 @@
530
"third_intro_content" : "Yats também mora fora da Cake Wallet. Qualquer endereço de carteira na Terra pode ser substituído por um Yat!",
531
"learn_more" : "Saber mais",
532
"search": "Procurar",
533
+ "search_language": "Idioma de pesquisa",
534
+ "search_currency": "Pesquisar moeda",
535
"new_template" : "Novo modelo",
536
"electrum_address_disclaimer": "Geramos novos endereços cada vez que você usa um, mas os endereços anteriores continuam funcionando"
537
}
res/values/strings_ru.arb
+3
-1
@@ -228,7 +228,7 @@
228
"settings_nodes" : "Ноды",
229
"settings_current_node" : "Текущая нода",
230
"settings_wallets" : "Кошельки",
231
- "settings_display_balance_as" : "Отображать баланс как",
231
+ "settings_display_balance" : "Отображать баланс",
232
"settings_currency" : "Валюта",
233
"settings_fee_priority" : "Приоритет транзакции",
234
"settings_save_recipient_address" : "Сохранять адрес получателя",
@@ -530,6 +530,8 @@
530
"third_intro_content" : "Yat находятся за пределами Cake Wallet. Любой адрес кошелька на земле можно заменить на Yat!",
531
"learn_more" : "Узнать больше",
532
"search": "Поиск",
533
+ "search_language": "Язык поиска",
534
+ "search_currency": "Валюта поиска",
535
"new_template" : "Новый шаблон",
536
"electrum_address_disclaimer": "Мы генерируем новые адреса каждый раз, когда вы их используете, но предыдущие адреса продолжают работать."
537
}
res/values/strings_uk.arb
+3
-1
@@ -227,7 +227,7 @@
227
"settings_nodes" : "Вузли",
228
"settings_current_node" : "Поточний вузол",
229
"settings_wallets" : "Гаманці",
230
- "settings_display_balance_as" : "Відображати баланс як",
230
+ "settings_display_balance" : "Відображати баланс",
231
"settings_currency" : "Валюта",
232
"settings_fee_priority" : "Пріоритет транзакції",
233
"settings_save_recipient_address" : "Зберігати адресу отримувача",
@@ -529,6 +529,8 @@
529
"third_intro_content" : "Yat знаходиться за межами Cake Wallet. Будь-яку адресу гаманця на землі можна замінити на Yat!",
530
"learn_more" : "Дізнатися більше",
531
"search": "Пошук",
532
+ "search_language": "Мова пошуку",
533
+ "search_currency": "Шукати валюту",
534
"new_template" : "Новий шаблон",
535
"electrum_address_disclaimer": "Ми створюємо нові адреси щоразу, коли ви використовуєте їх, але попередні адреси продовжують працювати"
536
}
res/values/strings_zh.arb
+3
-1
@@ -228,7 +228,7 @@
228
"settings_nodes" : "节点数",
229
"settings_current_node" : "当前节点",
230
"settings_wallets" : "钱包",
231
- "settings_display_balance_as" : "将余额显示为",
231
+ "settings_display_balance" : "显示余额为",
232
"settings_currency" : "货币",
233
"settings_fee_priority" : "交易优先级",
234
"settings_save_recipient_address" : "保存收件人地址",
@@ -528,6 +528,8 @@
528
"third_intro_content" : "Yats 也住在 Cake Wallet 之外。 地球上任何一個錢包地址都可以用一個Yat來代替!",
529
"learn_more" : "了解更多",
530
"search": "搜索",
531
+ "search_language": "搜索语言",
532
+ "search_currency": "搜索货币",
533
"new_template" : "新模板",
534
"electrum_address_disclaimer": "每次您使用一个地址时,我们都会生成新地址,但之前的地址仍然有效"
535
}