CW-376-picker-ui-issue (#919)

* feat: use common modal widget for repeated picker logic and display

* refactor: rename widget

* refactor: clear wrapper logic from picker widget and move title to hasTitle

* Minor code readability enhancements [skip ci]

---------

Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
This commit is contained in:
Rafael Saes 2023-05-10 09:19:38 -03:00 committed by GitHub
parent 759e61f67e
commit e28e2fbdde
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 310 additions and 305 deletions

View file

@ -1,13 +1,9 @@
import 'dart:ui';
import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/filter_tile.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/filter_tile.dart';
import 'package:cake_wallet/src/widgets/section_divider.dart'; import 'package:cake_wallet/src/widgets/section_divider.dart';
import 'package:cake_wallet/src/widgets/standard_checkbox.dart'; import 'package:cake_wallet/src/widgets/standard_checkbox.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:cake_wallet/src/widgets/alert_background.dart'; import 'package:cake_wallet/src/widgets/picker_wrapper_widget.dart';
import 'package:cake_wallet/src/widgets/alert_close_button.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter_mobx/flutter_mobx.dart';
//import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker; //import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker;
@ -20,26 +16,26 @@ class FilterWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
const sectionDivider = const SectionDivider(); const sectionDivider = const SectionDivider();
return AlertBackground( return PickerWrapperWidget(
child: Stack( children: [
alignment: Alignment.center,
children: <Widget>[
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding( Padding(
padding: EdgeInsets.only(left: 24, right: 24, top: 24), padding: EdgeInsets.only(left: 24, right: 24, top: 24),
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(24)), borderRadius: BorderRadius.all(Radius.circular(24)),
child: Container( child: Container(
color: Theme.of(context).textTheme!.bodyText1!.decorationColor!, color: Theme.of(context).textTheme!.bodyText1!.decorationColor!,
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding( Padding(
padding: EdgeInsets.all(24.0), padding: EdgeInsets.all(24.0),
child: Text( child: Text(
S.of(context).filter_by, S.of(context).filter_by,
style: TextStyle( style: TextStyle(
color: Theme.of(context).primaryTextTheme.overline!.color!, color: Theme.of(context)
.primaryTextTheme
.overline!
.color!,
fontSize: 16, fontSize: 16,
fontFamily: 'Lato', fontFamily: 'Lato',
decoration: TextDecoration.none, decoration: TextDecoration.none,
@ -54,17 +50,23 @@ class FilterWidget extends StatelessWidget {
itemCount: dashboardViewModel.filterItems.length, itemCount: dashboardViewModel.filterItems.length,
separatorBuilder: (context, _) => sectionDivider, separatorBuilder: (context, _) => sectionDivider,
itemBuilder: (_, index1) { itemBuilder: (_, index1) {
final title = dashboardViewModel.filterItems.keys.elementAt(index1); final title = dashboardViewModel.filterItems.keys
final section = dashboardViewModel.filterItems.values.elementAt(index1); .elementAt(index1);
final section = dashboardViewModel.filterItems.values
.elementAt(index1);
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
Padding( Padding(
padding: EdgeInsets.only(top: 20, left: 24, right: 24), padding:
EdgeInsets.only(top: 20, left: 24, right: 24),
child: Text( child: Text(
title, title,
style: TextStyle( style: TextStyle(
color: Theme.of(context).primaryTextTheme!.headline6!.color!, color: Theme.of(context)
.primaryTextTheme!
.headline6!
.color!,
fontSize: 16, fontSize: 16,
fontFamily: 'Lato', fontFamily: 'Lato',
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@ -83,9 +85,11 @@ class FilterWidget extends StatelessWidget {
value: item.value(), value: item.value(),
caption: item.caption, caption: item.caption,
gradientBackground: true, gradientBackground: true,
borderColor: Theme.of(context).dividerColor, borderColor:
Theme.of(context).dividerColor,
iconColor: Colors.white, iconColor: Colors.white,
onChanged: (value) => item.onChanged(), onChanged: (value) =>
item.onChanged(),
)); ));
return FilterTile(child: content); return FilterTile(child: content);
}, },
@ -97,12 +101,8 @@ class FilterWidget extends StatelessWidget {
]), ]),
), ),
), ),
), )
], ],
),
AlertCloseButton()
],
),
); );
} }
} }

View file

@ -1,8 +1,7 @@
import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:cake_wallet/src/widgets/alert_background.dart'; import 'package:cake_wallet/src/widgets/picker_wrapper_widget.dart';
import 'package:cake_wallet/src/widgets/alert_close_button.dart';
class CheckBoxPicker extends StatefulWidget { class CheckBoxPicker extends StatefulWidget {
CheckBoxPicker({ CheckBoxPicker({
@ -32,16 +31,8 @@ class CheckBoxPickerState extends State<CheckBoxPicker> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AlertBackground( return PickerWrapperWidget(
child: Column(
children: [ children: [
Expanded(
child: Stack(
alignment: Alignment.center,
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
if (widget.title.isNotEmpty) if (widget.title.isNotEmpty)
Container( Container(
padding: EdgeInsets.symmetric(horizontal: 24), padding: EdgeInsets.symmetric(horizontal: 24),
@ -91,14 +82,6 @@ class CheckBoxPickerState extends State<CheckBoxPicker> {
), ),
), ),
], ],
),
SizedBox(height: ResponsiveLayoutUtil.kPopupSpaceHeight),
AlertCloseButton(),
],
),
),
],
),
); );
} }
@ -111,7 +94,10 @@ class CheckBoxPickerState extends State<CheckBoxPicker> {
shrinkWrap: true, shrinkWrap: true,
separatorBuilder: (context, index) => widget.isSeparated separatorBuilder: (context, index) => widget.isSeparated
? Divider( ? Divider(
color: Theme.of(context).accentTextTheme.headline6!.backgroundColor!, color: Theme.of(context)
.accentTextTheme
.headline6!
.backgroundColor!,
height: 1, height: 1,
) )
: const SizedBox(), : const SizedBox(),

View file

@ -2,9 +2,8 @@
import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:cake_wallet/src/widgets/alert_background.dart';
import 'package:cake_wallet/src/widgets/alert_close_button.dart';
import 'package:cw_core/currency.dart'; import 'package:cw_core/currency.dart';
import 'package:cake_wallet/src/widgets/picker_wrapper_widget.dart';
class Picker<Item> extends StatefulWidget { class Picker<Item> extends StatefulWidget {
Picker({ Picker({
@ -114,37 +113,16 @@ class _PickerState<Item> extends State<Picker<Item>> {
final mq = MediaQuery.of(context); final mq = MediaQuery.of(context);
final bottom = mq.viewInsets.bottom; final bottom = mq.viewInsets.bottom;
final height = mq.size.height - bottom; final height = mq.size.height - bottom;
final screenCenter = height / 2;
double closeButtonBottom = 60;
double containerHeight = height * 0.65; double containerHeight = height * 0.65;
if (bottom > 0) { if (bottom > 0) {
// increase a bit or it gets too squished in the top // increase a bit or it gets too squished in the top
containerHeight = height * 0.75; containerHeight = height * 0.75;
final containerCenter = containerHeight / 2;
final containerBottom = screenCenter - containerCenter;
final hasTitle = widget.title == null || widget.title!.isEmpty;
// position the close button right below the search container
closeButtonBottom = closeButtonBottom -
containerBottom +
(hasTitle ? padding : padding / 1.5);
} }
return AlertBackground( return PickerWrapperWidget(
child: Column( hasTitle: widget.title?.isNotEmpty ?? false,
children: [ children: [
Expanded(
flex: 1,
child: Stack(
alignment: Alignment.center,
children: <Widget>[
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
if (widget.title?.isNotEmpty ?? false) if (widget.title?.isNotEmpty ?? false)
Container( Container(
padding: EdgeInsets.symmetric(horizontal: padding), padding: EdgeInsets.symmetric(horizontal: padding),
@ -165,10 +143,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(30)), borderRadius: BorderRadius.all(Radius.circular(30)),
child: Container( child: Container(
color: Theme.of(context) color: Theme.of(context).accentTextTheme.headline6!.color!,
.accentTextTheme
.headline6!
.color!,
child: ConstrainedBox( child: ConstrainedBox(
constraints: BoxConstraints( constraints: BoxConstraints(
maxHeight: containerHeight, maxHeight: containerHeight,
@ -189,26 +164,23 @@ class _PickerState<Item> extends State<Picker<Item>> {
.color!), .color!),
decoration: InputDecoration( decoration: InputDecoration(
hintText: widget.hintText, hintText: widget.hintText,
prefixIcon: Image.asset( prefixIcon:
"assets/images/search_icon.png"), Image.asset("assets/images/search_icon.png"),
filled: true, filled: true,
fillColor: Theme.of(context) fillColor: Theme.of(context)
.accentTextTheme .accentTextTheme
.headline3! .headline3!
.color!, .color!,
alignLabelWithHint: false, alignLabelWithHint: false,
contentPadding: contentPadding: const EdgeInsets.symmetric(
const EdgeInsets.symmetric(
vertical: 4, horizontal: 16), vertical: 4, horizontal: 16),
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderRadius: borderRadius: BorderRadius.circular(14),
BorderRadius.circular(14),
borderSide: const BorderSide( borderSide: const BorderSide(
color: Colors.transparent, color: Colors.transparent,
)), )),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: borderRadius: BorderRadius.circular(14),
BorderRadius.circular(14),
borderSide: const BorderSide( borderSide: const BorderSide(
color: Colors.transparent, color: Colors.transparent,
)), )),
@ -246,8 +218,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
fontFamily: 'Lato', fontFamily: 'Lato',
decoration: decoration: TextDecoration.none,
TextDecoration.none,
color: Theme.of(context) color: Theme.of(context)
.primaryTextTheme .primaryTextTheme
.headline6! .headline6!
@ -266,19 +237,6 @@ class _PickerState<Item> extends State<Picker<Item>> {
), ),
) )
], ],
),
SizedBox(height: ResponsiveLayoutUtil.kPopupSpaceHeight),
AlertCloseButton(bottom: closeButtonBottom),
],
),
),
// gives the extra spacing using MediaQuery.viewInsets.bottom
// to simulate a keyboard area
SizedBox(
height: bottom,
)
],
),
); );
} }

View file

@ -0,0 +1,61 @@
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/src/widgets/alert_background.dart';
import 'package:cake_wallet/src/widgets/alert_close_button.dart';
class PickerWrapperWidget extends StatelessWidget {
PickerWrapperWidget({required this.children, this.hasTitle = false});
final List<Widget> children;
final bool hasTitle;
@override
Widget build(BuildContext context) {
final double padding = 24;
final mq = MediaQuery.of(context);
final bottom = mq.viewInsets.bottom;
final height = mq.size.height - bottom;
final screenCenter = height / 2;
double closeButtonBottom = 60;
double containerHeight = height * 0.65;
if (bottom > 0) {
// increase a bit or it gets too squished in the top
containerHeight = height * 0.75;
final containerCenter = containerHeight / 2;
final containerBottom = screenCenter - containerCenter;
// position the close button right below the search container
closeButtonBottom = closeButtonBottom -
containerBottom + (!hasTitle ? padding : padding / 1.5);
}
return AlertBackground(
child: Column(
children: [
Expanded(
flex: 1,
child: Stack(
alignment: Alignment.center,
children: <Widget>[
Column(
mainAxisSize: MainAxisSize.min,
children: children,
),
SizedBox(height: ResponsiveLayoutUtil.kPopupSpaceHeight),
AlertCloseButton(bottom: closeButtonBottom),
],
),
),
// gives the extra spacing using MediaQuery.viewInsets.bottom
// to simulate a keyboard area
SizedBox(
height: bottom,
)
],
),
);
}
}