import "package:dio/dio.dart"; import 'package:flutter/material.dart'; import "package:flutter/services.dart"; import "package:photos/generated/l10n.dart"; import "package:photos/models/search/button_result.dart"; import 'package:photos/models/typedefs.dart'; import 'package:photos/theme/colors.dart'; import 'package:photos/ui/common/loading_widget.dart'; import 'package:photos/ui/common/progress_dialog.dart'; import 'package:photos/ui/components/action_sheet_widget.dart'; import 'package:photos/ui/components/buttons/button_widget.dart'; import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/ui/components/models/button_type.dart'; typedef DialogBuilder = DialogWidget Function(BuildContext context); ///Will return null if dismissed by tapping outside Future showErrorDialog( BuildContext context, String title, String? body, { bool isDismissable = true, }) async { return showDialogWidget( context: context, title: title, body: body, isDismissible: isDismissable, buttons: [ ButtonWidget( buttonType: ButtonType.secondary, labelText: S.of(context).ok, isInAlert: true, buttonAction: ButtonAction.first, ), ], ); } Future showErrorDialogForException({ required BuildContext context, required Exception exception, bool isDismissible = true, String apiErrorPrefix = "It looks like something went wrong.", String? message, }) async { String errorMessage = message ?? S.of(context).tempErrorContactSupportIfPersists; if (exception is DioError && exception.response != null && exception.response!.data["code"] != null) { errorMessage = "$apiErrorPrefix\n\nReason: " + exception.response!.data["code"]; } return showDialogWidget( context: context, title: S.of(context).error, icon: Icons.error_outline_outlined, body: errorMessage, isDismissible: isDismissible, buttons: const [ ButtonWidget( buttonType: ButtonType.secondary, labelText: "OK", isInAlert: true, ), ], ); } ///Will return null if dismissed by tapping outside Future showGenericErrorDialog({ required BuildContext context, bool isDismissible = true, }) async { return showDialogWidget( context: context, title: S.of(context).error, icon: Icons.error_outline_outlined, body: S.of(context).itLooksLikeSomethingWentWrongPleaseRetryAfterSome, isDismissible: isDismissible, buttons: const [ ButtonWidget( buttonType: ButtonType.secondary, labelText: "OK", isInAlert: true, ), ], ); } DialogWidget choiceDialog({ required String title, String? body, required String firstButtonLabel, String secondButtonLabel = "Cancel", ButtonType firstButtonType = ButtonType.neutral, ButtonType secondButtonType = ButtonType.secondary, ButtonAction firstButtonAction = ButtonAction.first, ButtonAction secondButtonAction = ButtonAction.cancel, FutureVoidCallback? firstButtonOnTap, FutureVoidCallback? secondButtonOnTap, bool isCritical = false, IconData? icon, }) { final buttons = [ ButtonWidget( buttonType: isCritical ? ButtonType.critical : firstButtonType, labelText: firstButtonLabel, isInAlert: true, onTap: firstButtonOnTap, buttonAction: firstButtonAction, ), ButtonWidget( buttonType: secondButtonType, labelText: secondButtonLabel, isInAlert: true, onTap: secondButtonOnTap, buttonAction: secondButtonAction, ), ]; return DialogWidget(title: title, body: body, buttons: buttons, icon: icon); } ///Will return null if dismissed by tapping outside Future showChoiceDialog( BuildContext context, { required String title, String? body, required String firstButtonLabel, String secondButtonLabel = "Cancel", ButtonType firstButtonType = ButtonType.neutral, ButtonType secondButtonType = ButtonType.secondary, ButtonAction firstButtonAction = ButtonAction.first, ButtonAction secondButtonAction = ButtonAction.cancel, FutureVoidCallback? firstButtonOnTap, FutureVoidCallback? secondButtonOnTap, bool isCritical = false, IconData? icon, bool isDismissible = true, }) async { final buttons = [ ButtonWidget( buttonType: isCritical ? ButtonType.critical : firstButtonType, labelText: firstButtonLabel, isInAlert: true, onTap: firstButtonOnTap, buttonAction: firstButtonAction, ), ButtonWidget( buttonType: secondButtonType, labelText: secondButtonLabel, isInAlert: true, onTap: secondButtonOnTap, buttonAction: secondButtonAction, ), ]; return showDialogWidget( context: context, title: title, body: body, buttons: buttons, icon: icon, isDismissible: isDismissible, ); } ///Will return null if dismissed by tapping outside Future showChoiceActionSheet( BuildContext context, { required String title, String? body, required String firstButtonLabel, String secondButtonLabel = "Cancel", ButtonType firstButtonType = ButtonType.neutral, ButtonType secondButtonType = ButtonType.secondary, ButtonAction firstButtonAction = ButtonAction.first, ButtonAction secondButtonAction = ButtonAction.cancel, FutureVoidCallback? firstButtonOnTap, FutureVoidCallback? secondButtonOnTap, bool isCritical = false, IconData? icon, bool isDismissible = true, }) async { final buttons = [ ButtonWidget( buttonType: isCritical ? ButtonType.critical : firstButtonType, labelText: firstButtonLabel, isInAlert: true, onTap: firstButtonOnTap, buttonAction: firstButtonAction, shouldStickToDarkTheme: true, ), ButtonWidget( buttonType: secondButtonType, labelText: secondButtonLabel, isInAlert: true, onTap: secondButtonOnTap, buttonAction: secondButtonAction, shouldStickToDarkTheme: true, ), ]; return showActionSheet( context: context, title: title, body: body, buttons: buttons, isDismissible: isDismissible, ); } ProgressDialog createProgressDialog( BuildContext context, String message, { isDismissible = false, }) { final dialog = ProgressDialog( context, type: ProgressDialogType.normal, isDismissible: isDismissible, barrierColor: Colors.black12, ); dialog.style( message: message, messageTextStyle: Theme.of(context).textTheme.bodySmall, backgroundColor: Theme.of(context).dialogTheme.backgroundColor, progressWidget: const EnteLoadingWidget(), borderRadius: 10, elevation: 10.0, insetAnimCurve: Curves.easeInOut, ); return dialog; } //Can return ButtonResult? from ButtonWidget or Exception? from TextInputDialog Future showTextInputDialog( BuildContext context, { required String title, String? body, required String submitButtonLabel, IconData? icon, String? label, String? message, String? hintText, required FutureVoidCallbackParamStr onSubmit, IconData? prefixIcon, String? initialValue, Alignment? alignMessage, int? maxLength, bool showOnlyLoadingState = false, TextCapitalization textCapitalization = TextCapitalization.none, bool alwaysShowSuccessState = false, bool isPasswordInput = false, TextEditingController? textEditingController, List? textInputFormatter, TextInputType? textInputType, }) { return showDialog( barrierColor: backdropFaintDark, context: context, builder: (context) { final bottomInset = MediaQuery.of(context).viewInsets.bottom; final isKeyboardUp = bottomInset > 100; return Center( child: Padding( padding: EdgeInsets.only(bottom: isKeyboardUp ? bottomInset : 0), child: TextInputDialog( title: title, message: message, label: label, body: body, icon: icon, submitButtonLabel: submitButtonLabel, onSubmit: onSubmit, hintText: hintText, prefixIcon: prefixIcon, initialValue: initialValue, alignMessage: alignMessage, maxLength: maxLength, showOnlyLoadingState: showOnlyLoadingState, textCapitalization: textCapitalization, alwaysShowSuccessState: alwaysShowSuccessState, isPasswordInput: isPasswordInput, textEditingController: textEditingController, textInputFormatter: textInputFormatter, textInputType: textInputType, ), ), ); }, ); }