Skip to content

Commit

Permalink
CW-512 wallet sort (#1195)
Browse files Browse the repository at this point in the history
* add shared preferences key and make list re-orderable

* macos sonoma build fix

* everything (almost) works

* add translations

* more translations

* everything works

* fixes

* translation merge file fix

* fix for mobile platforms

* fix filter icon being invisible on bright theme

* first pass of adding ascending/descending to filter widget

* small fix

* update ascending switch

* fixes

* fix

* reverse creation sort

* review fixes part 1

* refactor into function rather than tuple + color changes

* more fixes

* remove unrelated file

* updated wording

* cleaner callback

* undo sonoma fix

---------

Co-authored-by: fossephate <[email protected]>
Co-authored-by: Omar Hatem <[email protected]>
  • Loading branch information
3 people authored Dec 13, 2023
1 parent 049e4de commit 2ff81df
Show file tree
Hide file tree
Showing 37 changed files with 624 additions and 36 deletions.
34 changes: 34 additions & 0 deletions lib/entities/list_order_mode.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cw_core/enumerable_item.dart';

class ListOrderMode extends EnumerableItem<int> with Serializable<int> {
const ListOrderMode({required String title, required int raw}) : super(title: title, raw: raw);

static const all = [ListOrderMode.ascending, ListOrderMode.descending];

static const ascending = ListOrderMode(raw: 0, title: 'Ascending');
static const descending = ListOrderMode(raw: 1, title: 'Descending');

static ListOrderMode deserialize({required int raw}) {
switch (raw) {
case 0:
return ascending;
case 1:
return descending;
default:
throw Exception('Unexpected token: $raw for ListOrderMode deserialize');
}
}

@override
String toString() {
switch (this) {
case ListOrderMode.ascending:
return S.current.ascending;
case ListOrderMode.descending:
return S.current.descending;
default:
return '';
}
}
}
2 changes: 2 additions & 0 deletions lib/entities/preferences_key.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class PreferencesKey {
static const disableBuyKey = 'disable_buy';
static const disableSellKey = 'disable_sell';
static const defaultBuyProvider = 'default_buy_provider';
static const walletListOrder = 'wallet_list_order';
static const walletListAscending = 'wallet_list_ascending';
static const currentFiatApiModeKey = 'current_fiat_api_mode';
static const allowBiometricalAuthenticationKey = 'allow_biometrical_authentication';
static const useTOTP2FA = 'use_totp_2fa';
Expand Down
22 changes: 22 additions & 0 deletions lib/entities/wallet_list_order_types.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import 'package:cake_wallet/generated/i18n.dart';

enum WalletListOrderType {
CreationDate,
Alphabetical,
GroupByType,
Custom;

@override
String toString() {
switch (this) {
case WalletListOrderType.CreationDate:
return S.current.creation_date;
case WalletListOrderType.Alphabetical:
return S.current.alphabetical;
case WalletListOrderType.GroupByType:
return S.current.group_by_type;
case WalletListOrderType.Custom:
return S.current.custom_drag;
}
}
}
158 changes: 158 additions & 0 deletions lib/src/screens/dashboard/widgets/filter_list_widget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import 'package:cake_wallet/entities/list_order_mode.dart';
import 'package:cake_wallet/entities/wallet_list_order_types.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/src/widgets/section_divider.dart';
import 'package:cake_wallet/themes/extensions/menu_theme.dart';
import 'package:cake_wallet/view_model/settings/choices_list_item.dart';
import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/src/widgets/picker_wrapper_widget.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';

class FilterListWidget extends StatefulWidget {
FilterListWidget({
required this.initalType,
required this.initalAscending,
required this.onClose,
});

final WalletListOrderType? initalType;
final bool initalAscending;
final Function(bool, WalletListOrderType) onClose;

@override
FilterListWidgetState createState() => FilterListWidgetState();
}

class FilterListWidgetState extends State<FilterListWidget> {
late bool ascending;
late WalletListOrderType? type;

@override
void initState() {
super.initState();
ascending = widget.initalAscending;
type = widget.initalType;
}

void setSelectedOrderType(WalletListOrderType? orderType) {
setState(() {
type = orderType;
});
}

@override
Widget build(BuildContext context) {
const sectionDivider = const HorizontalSectionDivider();
return PickerWrapperWidget(
onClose: () {
widget.onClose(ascending, type!);
Navigator.of(context).pop();
},
children: [
Padding(
padding: EdgeInsets.only(left: 24, right: 24, top: 24),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(24)),
child: Container(
color: Theme.of(context).extension<CakeMenuTheme>()!.backgroundColor,
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Padding(
padding: EdgeInsets.all(24.0),
child: Text(
S.of(context).order_by,
style: TextStyle(
color:
Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor,
fontSize: 16,
fontFamily: 'Lato',
decoration: TextDecoration.none,
),
),
),
if (type != WalletListOrderType.Custom) ...[
sectionDivider,
SettingsChoicesCell(
ChoicesListItem<ListOrderMode>(
title: "",
items: ListOrderMode.all,
selectedItem: ascending ? ListOrderMode.ascending : ListOrderMode.descending,
onItemSelected: (ListOrderMode listOrderMode) {
setState(() {
ascending = listOrderMode == ListOrderMode.ascending;
});
},
),
),
],
sectionDivider,
RadioListTile(
value: WalletListOrderType.CreationDate,
groupValue: type,
title: Text(
WalletListOrderType.CreationDate.toString(),
style: TextStyle(
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
fontSize: 16,
fontFamily: 'Lato',
fontWeight: FontWeight.bold,
decoration: TextDecoration.none),
),
onChanged: setSelectedOrderType,
activeColor: Theme.of(context).primaryColor,
),
RadioListTile(
value: WalletListOrderType.Alphabetical,
groupValue: type,
title: Text(
WalletListOrderType.Alphabetical.toString(),
style: TextStyle(
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
fontSize: 16,
fontFamily: 'Lato',
fontWeight: FontWeight.bold,
decoration: TextDecoration.none),
),
onChanged: setSelectedOrderType,
activeColor: Theme.of(context).primaryColor,
),
RadioListTile(
value: WalletListOrderType.GroupByType,
groupValue: type,
title: Text(
WalletListOrderType.GroupByType.toString(),
style: TextStyle(
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
fontSize: 16,
fontFamily: 'Lato',
fontWeight: FontWeight.bold,
decoration: TextDecoration.none),
),
onChanged: setSelectedOrderType,
activeColor: Theme.of(context).primaryColor,
),
RadioListTile(
value: WalletListOrderType.Custom,
groupValue: type,
title: Text(
WalletListOrderType.Custom.toString(),
style: TextStyle(
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
fontSize: 16,
fontFamily: 'Lato',
fontWeight: FontWeight.bold,
decoration: TextDecoration.none),
),
onChanged: setSelectedOrderType,
activeColor: Theme.of(context).primaryColor,
),
]),
),
),
)
],
);
}
}
30 changes: 15 additions & 15 deletions lib/src/screens/settings/widgets/settings_choices_cell.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,21 @@ class SettingsChoicesCell extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
choicesListItem.title,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.normal,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
if (choicesListItem.title.isNotEmpty) ...[
Row(
children: [
Text(
choicesListItem.title,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.normal,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
),
),
),
],
),
const SizedBox(height: 24),
],
),
const SizedBox(height: 24),
],
Center(
child: Container(
decoration: BoxDecoration(
Expand All @@ -49,9 +51,7 @@ class SettingsChoicesCell extends StatelessWidget {
padding: EdgeInsets.symmetric(vertical: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: isSelected
? Theme.of(context).primaryColor
: null,
color: isSelected ? Theme.of(context).primaryColor : null,
),
child: Center(
child: Text(
Expand Down
39 changes: 39 additions & 0 deletions lib/src/screens/wallet_list/filtered_list.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:mobx/mobx.dart';

class FilteredList extends StatefulWidget {
FilteredList({
required this.list,
required this.itemBuilder,
required this.updateFunction,
});

final ObservableList<dynamic> list;
final Widget Function(BuildContext, int) itemBuilder;
final Function updateFunction;

@override
FilteredListState createState() => FilteredListState();
}

class FilteredListState extends State<FilteredList> {
@override
Widget build(BuildContext context) {
return Observer(
builder: (_) => ReorderableListView.builder(
physics: const BouncingScrollPhysics(),
itemBuilder: widget.itemBuilder,
itemCount: widget.list.length,
onReorder: (int oldIndex, int newIndex) {
if (oldIndex < newIndex) {
newIndex -= 1;
}
final dynamic item = widget.list.removeAt(oldIndex);
widget.list.insert(newIndex, item);
widget.updateFunction();
},
),
);
}
}
Loading

0 comments on commit 2ff81df

Please sign in to comment.