Skip to content

Commit

Permalink
User lists: bring Share / View on web / Clear actions to the Modal sh…
Browse files Browse the repository at this point in the history
…eet (#4400)
  • Loading branch information
g123k authored Jul 30, 2023
1 parent 05850f3 commit 3f2b7a7
Show file tree
Hide file tree
Showing 8 changed files with 247 additions and 92 deletions.
1 change: 1 addition & 0 deletions packages/smooth_app/lib/data_models/product_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -255,5 +255,6 @@ class ProductList {
}
}

/// Can be edited or renamed
bool get isEditable => listType == ProductListType.USER;
}
4 changes: 4 additions & 0 deletions packages/smooth_app/lib/database/dao_product_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ class DaoProductList extends AbstractDao {
productList.set(list.barcodes);
}

/// Checks if a list exists in the database.
bool exist(final ProductList productList) =>
_getBox().containsKey(getKey(productList));

/// Returns the number of barcodes quickly but without product check.
Future<int> getLength(final ProductList productList) async {
final _BarcodeList? list = await _get(productList);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ class SmoothModalSheetHeader extends StatelessWidget implements SizeWidget {
title,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.titleLarge,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
),
),
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,44 +47,60 @@ class SmoothDraggableBottomSheetState

@override
Widget build(BuildContext context) {
final Color backgroundColor = widget.bottomSheetColor ??
Theme.of(context).bottomSheetTheme.backgroundColor ??
Theme.of(context).scaffoldBackgroundColor;
final double bottomPaddingHeight = MediaQuery.paddingOf(context).bottom;

return NotificationListener<DraggableScrollableNotification>(
onNotification: _scrolling,
child: SafeArea(
child: DraggableScrollableSheet(
minChildSize: 0.0,
maxChildSize: widget.maxHeightFraction,
initialChildSize: widget.initHeightFraction,
snap: true,
controller: _controller,
builder: (BuildContext context, ScrollController controller) {
return DecoratedBox(
decoration: BoxDecoration(
borderRadius: widget.borderRadius,
color: widget.bottomSheetColor ??
Theme.of(context).bottomSheetTheme.backgroundColor ??
Theme.of(context).scaffoldBackgroundColor,
),
child: Material(
type: MaterialType.transparency,
child: ClipRRect(
borderRadius: widget.borderRadius,
child: _SmoothDraggableContent(
bodyBuilder: widget.bodyBuilder,
headerBuilder: widget.headerBuilder,
headerHeight: widget.headerHeight,
currentExtent: _controller.isAttached
? _controller.size
: widget.initHeightFraction,
scrollController: controller,
cacheExtent: _calculateCacheExtent(
MediaQuery.of(context).viewInsets.bottom,
child: Column(
children: <Widget>[
Expanded(
child: SafeArea(
bottom: false,
child: DraggableScrollableSheet(
minChildSize: 0.0,
maxChildSize: widget.maxHeightFraction,
initialChildSize: widget.initHeightFraction,
snap: true,
controller: _controller,
builder: (BuildContext context, ScrollController controller) {
return DecoratedBox(
decoration: BoxDecoration(
borderRadius: widget.borderRadius,
color: backgroundColor,
),
),
),
child: Material(
type: MaterialType.transparency,
child: ClipRRect(
borderRadius: widget.borderRadius,
child: _SmoothDraggableContent(
bodyBuilder: widget.bodyBuilder,
headerBuilder: widget.headerBuilder,
headerHeight: widget.headerHeight,
currentExtent: _controller.isAttached
? _controller.size
: widget.initHeightFraction,
scrollController: controller,
cacheExtent: _calculateCacheExtent(
MediaQuery.of(context).viewInsets.bottom,
),
),
),
),
);
},
),
);
},
),
),
),
if (bottomPaddingHeight > 0)
SizedBox(
width: double.infinity,
height: bottomPaddingHeight,
child: ColoredBox(color: backgroundColor),
),
],
),
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class _FlexibleBottomSheetRoute<T> extends PopupRoute<T> {
Animation<double> secondaryAnimation,
) {
final Widget bottomSheet = MediaQuery.removePadding(
removeBottom: false,
context: context,
child: SmoothDraggableBottomSheet(
initHeightFraction: initHeight,
Expand Down
232 changes: 175 additions & 57 deletions packages/smooth_app/lib/pages/all_product_list_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:smooth_app/database/dao_product_list.dart';
import 'package:smooth_app/database/local_database.dart';
import 'package:smooth_app/generic_lib/design_constants.dart';
import 'package:smooth_app/pages/preferences/user_preferences_list_tile.dart';
import 'package:smooth_app/pages/product/common/product_list_popup_items.dart';
import 'package:smooth_app/pages/product/common/product_query_page_helper.dart';
import 'package:smooth_app/pages/product_list_user_dialog_helper.dart';

Expand Down Expand Up @@ -43,62 +44,73 @@ class AllProductListModal extends StatelessWidget {
final ProductList productList = productLists[index];
return Column(
children: <Widget>[
UserPreferencesListTile(
title: Text(
ProductQueryPageHelper.getProductListLabel(
productList,
appLocalizations,
),
),
subtitle: FutureBuilder<int>(
future: daoProductList.getLength(productList),
builder: (
final BuildContext context,
final AsyncSnapshot<int> snapshot,
) {
if (snapshot.data != null) {
return Text(
appLocalizations.user_list_length(snapshot.data!),
);
}
return EMPTY_WIDGET;
},
),
trailing: productList.isEditable
? PopupMenuButton<PopupMenuEntries>(
itemBuilder: (BuildContext context) {
return <PopupMenuEntry<PopupMenuEntries>>[
PopupMenuItem<PopupMenuEntries>(
value: PopupMenuEntries.deleteList,
child: ListTile(
leading: const Icon(Icons.delete),
title:
Text(appLocalizations.action_delete_list),
contentPadding: EdgeInsets.zero,
),
onTap: () {
WidgetsBinding.instance
.addPostFrameCallback((_) {
ProductListUserDialogHelper(daoProductList)
.showDeleteUserListDialog(
context, productList);
});
})
];
},
icon: const Icon(Icons.more_vert),
)
: null,
selected: productList.listType == currentList.listType &&
productList.parameters == currentList.parameters,
selectedColor: Theme.of(context).primaryColor.withOpacity(0.2),
contentPadding: const EdgeInsetsDirectional.only(
start: VERY_LARGE_SPACE,
end: LARGE_SPACE,
top: VERY_SMALL_SPACE,
bottom: VERY_SMALL_SPACE,
),
onTap: () => Navigator.of(context).pop(productList),
FutureBuilder<int>(
future: daoProductList.getLength(productList),
builder: (
final BuildContext context,
final AsyncSnapshot<int> snapshot,
) {
final int productsLength = snapshot.data ?? 0;

return UserPreferencesListTile(
title: Text(
ProductQueryPageHelper.getProductListLabel(
productList,
appLocalizations,
),
),
subtitle: Text(
appLocalizations.user_list_length(productsLength),
),
trailing: PopupMenuButton<PopupMenuEntries>(
itemBuilder: (BuildContext context) {
return <PopupMenuEntry<PopupMenuEntries>>[
_shareMenu(
appLocalizations,
daoProductList,
localDatabase,
context,
productList,
),
_openInWebMenu(
appLocalizations,
daoProductList,
localDatabase,
context,
productList,
),
if (productsLength > 0)
_clearListMenu(
appLocalizations,
daoProductList,
localDatabase,
context,
productList,
),
if (productList.isEditable)
_deleteListMenu(
appLocalizations,
daoProductList,
context,
productList,
),
];
},
icon: const Icon(Icons.more_vert),
),
selected: productList.listType == currentList.listType &&
productList.parameters == currentList.parameters,
selectedColor:
Theme.of(context).primaryColor.withOpacity(0.2),
contentPadding: const EdgeInsetsDirectional.only(
start: VERY_LARGE_SPACE,
end: LARGE_SPACE,
top: VERY_SMALL_SPACE,
bottom: VERY_SMALL_SPACE,
),
onTap: () => Navigator.of(context).pop(productList),
);
},
),
if (index < productLists.length - 1) const Divider(height: 1.0),
],
Expand All @@ -107,6 +119,112 @@ class AllProductListModal extends StatelessWidget {
),
);
}

PopupMenuItem<PopupMenuEntries> _shareMenu(
AppLocalizations appLocalizations,
DaoProductList daoProductList,
LocalDatabase localDatabase,
BuildContext context,
ProductList productList,
) {
final ProductListPopupShare popupShare = ProductListPopupShare();
return PopupMenuItem<PopupMenuEntries>(
value: PopupMenuEntries.shareList,
child: ListTile(
leading: const Icon(Icons.share),
title: Text(popupShare.getTitle(appLocalizations)),
contentPadding: EdgeInsets.zero,
onTap: () {
Navigator.of(context).pop();
popupShare.doSomething(
productList: productList,
localDatabase: localDatabase,
context: context,
);
},
),
);
}

PopupMenuItem<PopupMenuEntries> _openInWebMenu(
AppLocalizations appLocalizations,
DaoProductList daoProductList,
LocalDatabase localDatabase,
BuildContext context,
ProductList productList,
) {
final ProductListPopupOpenInWeb webItem = ProductListPopupOpenInWeb();
return PopupMenuItem<PopupMenuEntries>(
value: PopupMenuEntries.openListInBrowser,
child: ListTile(
leading: const Icon(Icons.public),
title: Text(webItem.getTitle(appLocalizations)),
contentPadding: EdgeInsets.zero,
onTap: () {
Navigator.of(context).pop();
webItem.doSomething(
productList: productList,
localDatabase: localDatabase,
context: context,
);
},
),
);
}

PopupMenuItem<PopupMenuEntries> _clearListMenu(
AppLocalizations appLocalizations,
DaoProductList daoProductList,
LocalDatabase localDatabase,
BuildContext context,
ProductList productList,
) {
final ProductListPopupClear clearItem = ProductListPopupClear();
return PopupMenuItem<PopupMenuEntries>(
value: PopupMenuEntries.clearList,
child: ListTile(
leading: const Icon(Icons.delete_sweep),
title: Text(clearItem.getTitle(appLocalizations)),
contentPadding: EdgeInsets.zero,
onTap: () async {
Navigator.of(context).pop();

clearItem.doSomething(
productList: productList,
localDatabase: localDatabase,
context: context,
);
},
),
);
}

PopupMenuItem<PopupMenuEntries> _deleteListMenu(
AppLocalizations appLocalizations,
DaoProductList daoProductList,
BuildContext context,
ProductList productList,
) {
return PopupMenuItem<PopupMenuEntries>(
value: PopupMenuEntries.deleteList,
child: ListTile(
leading: const Icon(Icons.delete),
title: Text(appLocalizations.action_delete_list),
contentPadding: EdgeInsets.zero,
),
onTap: () {
WidgetsBinding.instance.addPostFrameCallback((_) {
ProductListUserDialogHelper(daoProductList)
.showDeleteUserListDialog(context, productList);
});
});
}
}

enum PopupMenuEntries { deleteList }
enum PopupMenuEntries {
shareList,
openListInBrowser,
renameList,
clearList,
deleteList,
}
Loading

0 comments on commit 3f2b7a7

Please sign in to comment.