Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Product not found dialog - a fully responsive implementation #4315

Merged
merged 1 commit into from
Aug 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,12 @@ class SmoothAlertDialog extends StatelessWidget {
this.actionsAxis,
this.actionsOrder,
this.close = false,
this.margin,
this.contentPadding,
});
}) : assert(
body is! LayoutBuilder,
"LayoutBuilder isn't supported with Dialogs",
);

final String? title;
final bool close;
Expand All @@ -41,8 +45,15 @@ class SmoothAlertDialog extends StatelessWidget {
final SmoothActionButton? negativeAction;
final Axis? actionsAxis;
final SmoothButtonsBarOrder? actionsOrder;
final EdgeInsets? margin;
final EdgeInsetsDirectional? contentPadding;

/// Default value [_defaultInsetPadding] in dialog.dart
static const EdgeInsets defaultMargin = EdgeInsets.symmetric(
horizontal: 40.0,
vertical: 24.0,
);

static const EdgeInsetsDirectional _smallContentPadding =
EdgeInsetsDirectional.only(
start: SMALL_SPACE,
Expand All @@ -62,12 +73,13 @@ class SmoothAlertDialog extends StatelessWidget {
@override
Widget build(BuildContext context) {
final Widget content = _buildContent(context);
final EdgeInsetsDirectional padding = contentPadding ??
(context.isSmallDevice() ? _smallContentPadding : _contentPadding);
final EdgeInsetsDirectional padding =
contentPadding ?? defaultContentPadding(context);

return AlertDialog(
scrollable: false,
elevation: 4.0,
insetPadding: margin ?? defaultMargin,
contentPadding: EdgeInsets.zero,
shape: const RoundedRectangleBorder(borderRadius: ROUNDED_BORDER_RADIUS),
content: ClipRRect(
Expand All @@ -93,7 +105,7 @@ class SmoothAlertDialog extends StatelessWidget {
return Padding(
padding: EdgeInsetsDirectional.only(
top: padding.bottom,
start: SMALL_SPACE,
start: actionsAxis == Axis.horizontal ? SMALL_SPACE : 0.0,
end: positiveAction != null && negativeAction != null
? 0.0
: SMALL_SPACE,
Expand All @@ -119,6 +131,10 @@ class SmoothAlertDialog extends StatelessWidget {
],
),
);

static EdgeInsetsDirectional defaultContentPadding(BuildContext context) {
return (context.isSmallDevice() ? _smallContentPadding : _contentPadding);
}
}

class _SmoothDialogTitle extends StatelessWidget {
Expand Down
21 changes: 21 additions & 0 deletions packages/smooth_app/lib/generic_lib/widgets/smooth_responsive.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ extension MediaQueryResponsiveExtensions on MediaQueryData {
bool isLargeDevice() {
return size.width > _MAX_TABLET_WIDTH;
}

DeviceType get _deviceType {
if (size.width <= _MAX_SMALL_DEVICE_WIDTH) {
return DeviceType.small;
} else if (size.width <= _MAX_SMARTPHONE_WIDTH) {
return DeviceType.smartphone;
} else if (size.width <= _MAX_TABLET_WIDTH) {
return DeviceType.tablet;
} else {
return DeviceType.large;
}
}
}

extension BuildContextResponsiveExtensions on BuildContext {
Expand All @@ -58,6 +70,8 @@ extension BuildContextResponsiveExtensions on BuildContext {
bool isLargeDevice() {
return SmoothResponsive.isLargeDevice(this);
}

DeviceType get deviceType => MediaQuery.of(this)._deviceType;
}

/// Custom Widget to provide a responsive behavior.
Expand Down Expand Up @@ -89,3 +103,10 @@ class SmoothResponsiveBuilder extends StatelessWidget {
}
}
}

enum DeviceType {
small,
smartphone,
tablet,
large,
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'dart:math' as math;

import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_svg/flutter_svg.dart';
Expand All @@ -10,6 +11,7 @@ import 'package:smooth_app/database/local_database.dart';
import 'package:smooth_app/generic_lib/design_constants.dart';
import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart';
import 'package:smooth_app/generic_lib/loading_dialog.dart';
import 'package:smooth_app/generic_lib/widgets/smooth_responsive.dart';
import 'package:smooth_app/helpers/app_helper.dart';
import 'package:smooth_app/pages/navigator/app_navigator.dart';
import 'package:smooth_app/query/barcode_product_query.dart';
Expand Down Expand Up @@ -53,83 +55,80 @@ class ProductDialogHelper {
FetchedProduct.error(FetchedProductStatus.userCancelled);

void _openProductNotFoundDialog() => showDialog<Widget>(
context: context,
builder: (BuildContext context) => SmoothAlertDialog(
body: LayoutBuilder(
builder: (
final BuildContext context,
final BoxConstraints constraints,
) {
final MediaQueryData mediaQueryData = MediaQuery.of(context);
final AppLocalizations appLocalizations =
AppLocalizations.of(context);
const double svgPadding = SMALL_SPACE;
final double svgWidth = (constraints.maxWidth - svgPadding) / 2;
return SizedBox(
height: mediaQueryData.size.height * .5,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 25,
child: SvgPicture.asset(
'assets/onboarding/birthday-cake.svg',
package: AppHelper.APP_PACKAGE,
),
),
const SizedBox(height: SMALL_SPACE),
Expanded(
flex: 25,
child: AutoSizeText(
appLocalizations.new_product_dialog_title,
style: Theme.of(context).textTheme.displayMedium,
textAlign: TextAlign.center,
maxLines: 2,
),
),
const SizedBox(height: SMALL_SPACE),
Expanded(
flex: 10,
child: Text(
appLocalizations.barcode_barcode(barcode),
textAlign: TextAlign.center,
),
),
const SizedBox(height: SMALL_SPACE),
Expanded(
flex: 15,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SvgCache(
unknownSvgNutriscore,
width: svgWidth,
),
const SizedBox(width: svgPadding),
SvgCache(
unknownSvgEcoscore,
width: svgWidth,
),
],
),
context: context,
builder: (BuildContext context) {
final double availableWidth = MediaQuery.of(context).size.width -
SmoothAlertDialog.defaultMargin.horizontal -
SmoothAlertDialog.defaultContentPadding(context).horizontal;

/// The nutriscore logo is 240*130
final double svgHeight = math.min(
(availableWidth * 0.4) / 240.0 * 130.0,
175.0,
);

final double heightMultiplier = switch (context.deviceType) {
DeviceType.small => 1,
DeviceType.smartphone => 2,
DeviceType.tablet => 2.5,
DeviceType.large => 4,
};

final AppLocalizations appLocalizations = AppLocalizations.of(context);
return SmoothAlertDialog(
body: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SvgPicture.asset(
'assets/onboarding/birthday-cake.svg',
package: AppHelper.APP_PACKAGE,
),
SizedBox(height: SMALL_SPACE * heightMultiplier),
Text(
appLocalizations.new_product_dialog_title,
style: Theme.of(context).textTheme.displayMedium,
textAlign: TextAlign.center,
maxLines: 2,
),
SizedBox(height: SMALL_SPACE * heightMultiplier),
Text(
appLocalizations.barcode_barcode(barcode),
textAlign: TextAlign.center,
),
SizedBox(height: MEDIUM_SPACE * heightMultiplier),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 4,
child: SvgCache(
unknownSvgNutriscore,
height: svgHeight,
),
const SizedBox(height: SMALL_SPACE),
Expanded(
flex: 25,
child: AutoSizeText(
appLocalizations.new_product_dialog_description,
textAlign: TextAlign.center,
maxLines: 3,
),
),
const Spacer(),
Expanded(
flex: 4,
child: SvgCache(
unknownSvgEcoscore,
height: svgHeight,
),
],
),
);
},
),
],
),
SizedBox(height: SMALL_SPACE * heightMultiplier),
Text(
appLocalizations.new_product_dialog_description,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
maxLines: 3,
),
],
),
actionsAxis: Axis.vertical,
positiveAction: SmoothActionButton(
text: AppLocalizations.of(context).contribute,
onPressed: () => AppNavigator.of(context).push(
Expand All @@ -140,8 +139,8 @@ class ProductDialogHelper {
text: AppLocalizations.of(context).close,
onPressed: () => Navigator.pop(context),
),
),
);
);
});

static Widget getErrorMessage(final String message) => Row(
children: <Widget>[
Expand Down