Skip to content

Commit ac36da4

Browse files
Merge pull request #296 from enrique-lozano/fix/scrollable-modals
Scrolling issues and confirmation literals
2 parents 3f3d88f + 6519083 commit ac36da4

35 files changed

+865
-395
lines changed

lib/app/accounts/account_selector.dart

Lines changed: 10 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:collection/collection.dart';
22
import 'package:drift/drift.dart' as drift;
33
import 'package:flutter/material.dart';
4+
import 'package:monekin/app/categories/selectors/draggableScrollableKeyboardAware.mixin.dart';
45
import 'package:monekin/core/database/app_db.dart';
56
import 'package:monekin/core/database/services/account/account_service.dart';
67
import 'package:monekin/core/models/account/account.dart';
@@ -42,53 +43,26 @@ class AccountSelectorModal extends StatefulWidget {
4243
State<AccountSelectorModal> createState() => _AccountSelectorModalState();
4344
}
4445

45-
class _AccountSelectorModalState extends State<AccountSelectorModal> {
46+
class _AccountSelectorModalState extends State<AccountSelectorModal>
47+
with DraggableScrollableKeyboardAware {
4648
late List<Account> selectedAccounts;
4749

4850
String searchValue = '';
4951

50-
final DraggableScrollableController controller =
51-
DraggableScrollableController();
52-
5352
@override
5453
void initState() {
5554
super.initState();
5655

5756
selectedAccounts = [...widget.selectedAccounts];
5857
}
5958

60-
@override
61-
void dispose() {
62-
controller.dispose();
63-
64-
super.dispose();
65-
}
66-
67-
_moveSheetTo(double position) {
68-
if (controller.isAttached && mounted) {
69-
controller.jumpTo(position);
70-
}
71-
}
72-
7359
@override
7460
Widget build(BuildContext context) {
7561
final t = Translations.of(context);
7662

77-
final bottomInsets = MediaQuery.of(context).viewInsets.bottom;
78-
79-
if (bottomInsets > 0) {
80-
_moveSheetTo(1);
81-
} else {
82-
_moveSheetTo(0.65);
83-
}
84-
85-
return DraggableScrollableSheet(
86-
controller: controller,
87-
expand: false,
63+
return buildDraggableSheet(
8864
minChildSize: 0.64,
89-
initialChildSize: 0.65,
90-
snap: true,
91-
snapSizes: const [0.65],
65+
defaultSize: 0.65,
9266
builder: (context, scrollController) {
9367
return ModalContainer(
9468
title: widget.allowMultiSelection
@@ -128,9 +102,8 @@ class _AccountSelectorModalState extends State<AccountSelectorModal> {
128102
border: const UnderlineInputBorder(),
129103
),
130104
onChanged: (value) {
131-
setState(() {
132-
searchValue = value;
133-
});
105+
searchValue = value;
106+
rebuild();
134107
},
135108
),
136109
if (widget.allowMultiSelection)
@@ -169,7 +142,7 @@ class _AccountSelectorModalState extends State<AccountSelectorModal> {
169142
: null,
170143
tristate: true,
171144
title: Text(
172-
t.general.select_all,
145+
t.ui_actions.select_all,
173146
style: const TextStyle(fontWeight: FontWeight.w700),
174147
),
175148
enabled: snapshot.hasData && snapshot.data!.isNotEmpty,
@@ -182,7 +155,7 @@ class _AccountSelectorModalState extends State<AccountSelectorModal> {
182155
(selAcc) => snapshot.data!.map((e) => e.id).contains(selAcc.id));
183156
}
184157

185-
setState(() {});
158+
rebuild();
186159
},
187160
);
188161
}
@@ -247,7 +220,7 @@ class _AccountSelectorModalState extends State<AccountSelectorModal> {
247220
.removeWhere((element) => element.id == account.id);
248221
}
249222

250-
setState(() {});
223+
rebuild();
251224
},
252225
);
253226
}

lib/app/accounts/details/account_details.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ class _AccountDetailsPageState extends State<AccountDetailsPage> {
109109
CardWithHeader(
110110
title: 'Info',
111111
footer: CardFooterWithSingleButton(
112-
text: t.general.edit,
112+
text: t.ui_actions.edit,
113113
onButtonClick: () => RouteUtils.pushRoute(
114114
context, AccountFormPage(account: account)),
115115
),
@@ -378,7 +378,7 @@ class _ArchiveWarnDialogState extends State<ArchiveWarnDialog> {
378378
return ModalContainer(
379379
title: t.account.close.title,
380380
footer: BottomSheetFooter(
381-
submitText: t.general.continue_text,
381+
submitText: t.ui_actions.continue_text,
382382
submitIcon: Icons.check,
383383
onSaved: !hasNoTransactions || widget.currentBalance != 0
384384
? null

lib/app/accounts/details/account_details_actions.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ abstract class AccountDetailsActions {
2222

2323
return [
2424
ListTileActionItem(
25-
label: t.general.edit,
25+
label: t.ui_actions.edit,
2626
icon: Icons.edit,
2727
onClick: () =>
2828
RouteUtils.pushRoute(context, AccountFormPage(account: account)),
@@ -84,7 +84,7 @@ abstract class AccountDetailsActions {
8484
account: account, currentBalance: currentBalance);
8585
}),
8686
ListTileActionItem(
87-
label: t.general.delete,
87+
label: t.ui_actions.delete,
8888
icon: Icons.delete,
8989
role: ListTileActionRole.delete,
9090
onClick: () {
@@ -105,7 +105,7 @@ abstract class AccountDetailsActions {
105105
contentParagraphs: [
106106
Text(t.account.reopen_descr),
107107
],
108-
confirmationText: t.general.confirm,
108+
confirmationText: t.ui_actions.confirm,
109109
).then((isConfirmed) {
110110
AccountService.instance
111111
.updateAccount(
@@ -148,7 +148,7 @@ abstract class AccountDetailsActions {
148148
context,
149149
dialogTitle: t.account.delete.warning_header,
150150
contentParagraphs: [Text(t.account.delete.warning_text)],
151-
confirmationText: t.general.continue_text,
151+
confirmationText: t.ui_actions.continue_text,
152152
showCancelButton: true,
153153
icon: Icons.delete,
154154
).then((isConfirmed) {

lib/app/budgets/budget_details_page.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,15 @@ class _BudgetDetailsPageState extends State<BudgetDetailsPage> {
106106
},
107107
),
108108
ListTileActionItem(
109-
label: t.general.delete,
109+
label: t.ui_actions.delete,
110110
icon: Icons.delete,
111111
role: ListTileActionRole.delete,
112112
onClick: () {
113113
confirmDialog(
114114
context,
115115
dialogTitle: t.budgets.delete,
116116
contentParagraphs: [Text(t.budgets.delete_warning)],
117-
confirmationText: t.general.confirm,
117+
confirmationText: t.ui_actions.confirm,
118118
icon: Icons.delete,
119119
).then((confirmed) {
120120
if (confirmed != true) return;

lib/app/categories/form/category_form.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ class _CategoryFormPageState extends State<CategoryFormPage> {
141141
}
142142
},
143143
icon: const Icon(Icons.check),
144-
label: Text(t.general.save_changes),
144+
label: Text(t.ui_actions.save_changes),
145145
),
146146
)
147147
],
@@ -178,7 +178,7 @@ class _CategoryFormPageState extends State<CategoryFormPage> {
178178
contentPadding: EdgeInsets.zero,
179179
leading: const Icon(Icons.delete),
180180
minLeadingWidth: 26,
181-
title: Text(t.general.delete),
181+
title: Text(t.ui_actions.delete),
182182
))
183183
];
184184
},
@@ -337,7 +337,7 @@ class _CategoryFormPageState extends State<CategoryFormPage> {
337337
contentPadding: EdgeInsets.zero,
338338
leading: const Icon(Icons.edit),
339339
minLeadingWidth: 26,
340-
title: Text(t.general.edit),
340+
title: Text(t.ui_actions.edit),
341341
)),
342342
const PopupMenuDivider(),
343343
PopupMenuItem(
@@ -346,7 +346,7 @@ class _CategoryFormPageState extends State<CategoryFormPage> {
346346
contentPadding: EdgeInsets.zero,
347347
leading: const Icon(Icons.delete),
348348
minLeadingWidth: 26,
349-
title: Text(t.general.delete),
349+
title: Text(t.ui_actions.delete),
350350
))
351351
];
352352
},

lib/app/categories/selectors/category_multi_selector.dart

Lines changed: 13 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:collection/collection.dart';
22
import 'package:drift/drift.dart' as drift;
33
import 'package:flutter/material.dart';
4+
import 'package:monekin/app/categories/selectors/draggableScrollableKeyboardAware.mixin.dart';
45
import 'package:monekin/core/database/services/category/category_service.dart';
56
import 'package:monekin/core/extensions/string.extension.dart';
67
import 'package:monekin/core/models/category/category.dart';
@@ -35,57 +36,29 @@ class CategoryMultiSelectorModal extends StatefulWidget {
3536
_CategoryMultiSelectorModalState();
3637
}
3738

38-
class _CategoryMultiSelectorModalState
39-
extends State<CategoryMultiSelectorModal> {
39+
class _CategoryMultiSelectorModalState extends State<CategoryMultiSelectorModal>
40+
with DraggableScrollableKeyboardAware {
4041
late List<Category> selectedCategories;
4142

4243
String searchValue = '';
4344

4445
/// IDs of the category tiles that are expanded
4546
Set<String> expandedCategoriesTiles = {};
4647

47-
final DraggableScrollableController controller =
48-
DraggableScrollableController();
49-
5048
@override
5149
void initState() {
5250
super.initState();
5351

5452
selectedCategories = [...widget.selectedCategories];
5553
}
5654

57-
@override
58-
void dispose() {
59-
controller.dispose();
60-
61-
super.dispose();
62-
}
63-
64-
_moveSheetTo(double position) {
65-
if (controller.isAttached && mounted) {
66-
controller.jumpTo(position);
67-
}
68-
}
69-
7055
@override
7156
Widget build(BuildContext context) {
7257
final t = Translations.of(context);
7358

74-
final bottomInsets = MediaQuery.of(context).viewInsets.bottom;
75-
76-
if (bottomInsets > 0) {
77-
_moveSheetTo(1);
78-
} else {
79-
_moveSheetTo(0.65);
80-
}
81-
82-
return DraggableScrollableSheet(
83-
controller: controller,
84-
expand: false,
59+
return buildDraggableSheet(
60+
defaultSize: 0.65,
8561
minChildSize: 0.64,
86-
initialChildSize: 0.65,
87-
snap: true,
88-
snapSizes: const [0.65],
8962
builder: (context, sc) {
9063
return ModalContainer(
9164
title: t.categories.select.title,
@@ -119,9 +92,9 @@ class _CategoryMultiSelectorModalState
11992
border: const UnderlineInputBorder(),
12093
),
12194
onChanged: (value) {
122-
setState(() {
123-
searchValue = value;
124-
});
95+
searchValue = value;
96+
97+
rebuild();
12598
},
12699
),
127100
buildSelectAllButton(snapshot),
@@ -187,7 +160,7 @@ class _CategoryMultiSelectorModalState
187160
.removeWhere((e) => e == category.id);
188161
}
189162

190-
setState(() {});
163+
rebuild();
191164
},
192165
leading:
193166
IconDisplayer.fromCategory(context, category: category),
@@ -209,7 +182,7 @@ class _CategoryMultiSelectorModalState
209182
.contains(e.id));
210183
}
211184

212-
setState(() {});
185+
rebuild();
213186
},
214187
),
215188
title: Row(
@@ -278,7 +251,7 @@ class _CategoryMultiSelectorModalState
278251
selectedCategories.removeWhere((e) => e.id == category.id);
279252
}
280253

281-
setState(() {});
254+
rebuild();
282255
},
283256
),
284257
);
@@ -302,7 +275,7 @@ class _CategoryMultiSelectorModalState
302275
: null,
303276
tristate: true,
304277
title: Text(
305-
t.general.select_all,
278+
t.ui_actions.select_all,
306279
style: const TextStyle(fontWeight: FontWeight.w700),
307280
),
308281
enabled: snapshot.hasData && snapshot.data!.isNotEmpty,
@@ -315,7 +288,7 @@ class _CategoryMultiSelectorModalState
315288
(selAcc) => snapshot.data!.map((e) => e.id).contains(selAcc.id));
316289
}
317290

318-
setState(() {});
291+
rebuild();
319292
},
320293
);
321294
}

0 commit comments

Comments
 (0)