Skip to content

Instantly share code, notes, and snippets.

@RobertApikyan
Created November 13, 2023 13:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RobertApikyan/40a7222d4b0b992fe2b7c302daf3adc3 to your computer and use it in GitHub Desktop.
Save RobertApikyan/40a7222d4b0b992fe2b7c302daf3adc3 to your computer and use it in GitHub Desktop.
import 'dart:io';
import 'package:flutter/cupertino.dart' as iOS;
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:instabug_flutter/instabug_flutter.dart';
import 'package:qundo/app/app.dart';
import 'package:qundo/app/app_colors.dart';
import 'package:qundo/app/app_event_reporter.dart';
import 'package:qundo/app/app_font_sizes.dart';
import 'package:qundo/app/app_text_styles.dart';
import 'package:qundo/components/phone_rotate_animation.dart';
import 'package:qundo/utilities/extension.dart';
import 'package:qundo/view_models/partner_theme_bundle.dart';
import 'progress_bar.dart';
/// This class uses to display different kind of dialogs, circular and linear
/// progress dialogs, and popup message dialogs.
class AppDialogs {
/// Displays Circular progress dialog with specified [message].
/// Dialog is displaying in portrait mode by default
static Future<dynamic> showCircularProgressDialog(BuildContext context,
{String? message, ValueListenable<String>? messageListenable}) =>
showGeneralDialog(
context: context,
barrierDismissible: false,
barrierColor: AppColors.black.withAlpha(172),
pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) =>
SizedBox(
height: 240,
width: 240,
child: CircularProgressBar(
message: message,
messageListenable: messageListenable,
),
),
transitionBuilder: (context, anim1, anim2, child) => Opacity(
opacity: anim1.value,
child: child,
),
transitionDuration: const Duration(milliseconds: 300));
/// Displays Linear progress dialog with specified [message] and [progress].
/// Dialog is displaying in portrait mode by default
static Future<dynamic> showLinearProgressDialog(BuildContext context,
{String? message, ValueListenable<double>? progress}) =>
showGeneralDialog(
context: context,
barrierDismissible: false,
pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) =>
SizedBox(
height: 240,
width: 240,
child: LinearProgressBar(message: message, progress: progress),
),
transitionBuilder: (context, anim1, anim2, child) => Opacity(
opacity: anim1.value,
child: child,
),
transitionDuration: const Duration(milliseconds: 300));
static Future<dynamic> showOrientationChangeDialog(BuildContext context,
{PhoneRotateAnimationDirection direction =
PhoneRotateAnimationDirection.left,
String? message}) =>
showGeneralDialog(
context: context,
barrierDismissible: false,
pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) =>
PhoneRotateAnimation(
direction: direction,
message: message,
),
transitionBuilder: (context, anim1, anim2, child) => Opacity(
opacity: anim1.value,
child: child,
),
transitionDuration: const Duration(milliseconds: 300));
static Future<dynamic> showAppErrorDialog(BuildContext context,
{String? message,
String? title,
String? positiveText,
String? negativeText,
String? neutralText,
Color? positiveTextColor,
Color? negativeTextColor,
Color? neutralTextColor,
bool selectableText = false,
bool dismissOnBackPress = true,
VoidCallback? onPressPositive,
VoidCallback? onPressNegative,
VoidCallback? onPressNeutral}) {
return showAppDialog(context,
message: message,
title: title,
positiveText: positiveText,
negativeText: negativeText ?? (App.environment.isInsBugEnabled ? localizations.report : null),
neutralText: neutralText,
positiveTextColor: positiveTextColor,
negativeTextColor: negativeTextColor,
neutralTextColor: neutralTextColor,
selectableText: selectableText,
dismissOnBackPress: dismissOnBackPress,
onPressPositive: onPressPositive,
onPressNegative: onPressNegative ?? (App.environment.isInsBugEnabled ? () => Instabug.show() : null),
onPressNeutral: onPressNeutral);
}
/// Displays platform specific (if iOS -> Cupertino style, if Android -> Material style)
/// popup message dialog with specified parameters.
/// Dialog is displaying in portrait mode by default
static Future<dynamic> showAppDialog(BuildContext context,
{String? message,
String? title,
String? positiveText,
String? negativeText,
String? neutralText,
Color? positiveTextColor,
Color? negativeTextColor,
Color? neutralTextColor,
bool selectableText = false,
bool dismissOnBackPress = true,
VoidCallback? onPressPositive,
VoidCallback? onPressNegative,
VoidCallback? onPressNeutral}) {
AppEventReporter.instance.dialogShownReport(message: message?.shortened());
if (Platform.isIOS) {
return _showCupertinoAppDialog(context,
message: message,
title: title,
positiveText: positiveText,
negativeText: negativeText,
neutralText: neutralText,
positiveTextColor: positiveTextColor,
negativeTextColor: negativeTextColor,
neutralTextColor: neutralTextColor,
selectableText: selectableText,
dismissOnBackPress: dismissOnBackPress,
onPressPositive: onPressPositive,
onPressNegative: onPressNegative,
onPressNeutral: onPressNeutral);
}
return _showMaterialAppDialog(context,
title: title,
message: message,
positiveText: positiveText,
negativeText: negativeText,
neutralText: neutralText,
positiveTextColor: positiveTextColor,
negativeTextColor: negativeTextColor,
neutralTextColor: neutralTextColor,
selectableText: selectableText,
dismissOnBackPress: dismissOnBackPress,
onPressPositive: onPressPositive,
onPressNegative: onPressNegative,
onPressNeutral: onPressNeutral);
}
/// Displays Material style popup message dialog with specified parameters (see [showAppDialog])
static Future<dynamic> _showMaterialAppDialog(BuildContext context,
{String? message,
String? title,
String? positiveText,
String? negativeText,
String? neutralText,
Color? positiveTextColor,
Color? negativeTextColor,
Color? neutralTextColor,
bool selectableText = false,
bool dismissOnBackPress = true,
VoidCallback? onPressPositive,
VoidCallback? onPressNegative,
VoidCallback? onPressNeutral}) async {
var actions = <Widget>[];
addActionButton(
TapIds tapIds,
String? text,
Color? textColor,
VoidCallback? onPress,
) {
if (text != null) {
actions.add(TextButton(
style: ButtonStyle(
overlayColor:
MaterialStateProperty.all(ThemeBundle.getColors().splashColor),
),
onPressed: () {
AppEventReporter.instance.tapReport(tapId: tapIds,metaInfo: {'message':message?.shortened() ?? 'N/A', 'buttonText':text});
Navigator.pop(context);
if (onPress != null) {
onPress();
}
},
child: Text(
text.toUpperCase(),
style: TextStyle(
color: textColor ?? ThemeBundle.getColors().primaryColor,
fontSize: AppFontSizes.ultraBig,
fontWeight: FontWeight.w500),
),
));
}
}
addActionButton(TapIds.dialog_neutral,neutralText, neutralTextColor, onPressNeutral);
addActionButton(TapIds.dialog_negative,negativeText, negativeTextColor, onPressNegative);
addActionButton(TapIds.dialog_positive,positiveText, positiveTextColor, onPressPositive);
Widget messageWidget = selectableText
? SelectableText(message ?? '', style: regularTextStyle)
: Text(message ?? '', style: regularTextStyle);
final emptyTitle = title == null || title.isEmpty;
return await showGeneralDialog(
context: context,
barrierDismissible: false,
pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) =>
WillPopScope(
onWillPop: () async => dismissOnBackPress,
child: AlertDialog(
content: messageWidget,
title: emptyTitle
? null
: Text(
title,
style: bigTextStyle,
),
actions: actions,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(11)),
),
),
transitionBuilder: (context, anim1, anim2, child) => Opacity(
opacity: anim1.value,
child: child,
),
transitionDuration: const Duration(milliseconds: 300));
}
/// Displays Cupertino style popup message dialog with specified parameters (see [showAppDialog])
static Future<dynamic> _showCupertinoAppDialog(BuildContext context,
{String? message,
String? title,
String? positiveText,
String? negativeText,
String? neutralText,
Color? positiveTextColor,
Color? negativeTextColor,
Color? neutralTextColor,
bool selectableText = false,
bool dismissOnBackPress = true,
VoidCallback? onPressPositive,
VoidCallback? onPressNegative,
VoidCallback? onPressNeutral}) async {
var actions = <Widget>[];
addActionButton(
TapIds tapIds,
String? text,
Color? textColor,
VoidCallback? onPress,
) {
if (text != null) {
actions.add(iOS.CupertinoButton(
pressedOpacity: 1,
onPressed: () {
AppEventReporter.instance.tapReport(tapId: tapIds,metaInfo: {'message':message?.shortened() ?? 'N/A'});
Navigator.pop(context);
if (onPress != null) {
onPress();
}
},
child: Text(
text,
style: TextStyle(
color: textColor ?? ThemeBundle.getColors().primaryColor,
fontSize: AppFontSizes.extraBig,
fontFamily: ThemeBundle.getFontBundle().familyName,
fontWeight: iOS.FontWeight.w600),
),
));
}
}
addActionButton(TapIds.dialog_neutral,neutralText, neutralTextColor, onPressNeutral);
addActionButton(TapIds.dialog_negative,negativeText, negativeTextColor, onPressNegative);
addActionButton(TapIds.dialog_positive,positiveText, positiveTextColor, onPressPositive);
Widget messageWidget = selectableText
? SelectableText(message ?? '',
style: TextStyle(
color: AppColors.black,
fontWeight: FontWeight.w400,
fontSize: AppFontSizes.big,
fontFamily: ThemeBundle.getFontBundle().familyName))
: Text(message ?? '',
style: TextStyle(
color: AppColors.black,
fontWeight: FontWeight.w400,
fontSize: AppFontSizes.big,
fontFamily: ThemeBundle.getFontBundle().familyName));
final emptyTitle = title == null || title.isEmpty;
return await showGeneralDialog(
context: context,
barrierDismissible: false,
pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) =>
iOS.WillPopScope(
onWillPop: () async => dismissOnBackPress,
child: CupertinoAlertDialog(
content: messageWidget,
title: emptyTitle
? null
: iOS.Text(
title,
style: TextStyle(
color: AppColors.black,
fontWeight: iOS.FontWeight.w700,
fontFamily: ThemeBundle.getFontBundle().familyName),
),
actions: actions,
),
),
transitionBuilder: (context, anim1, anim2, child) => Opacity(
opacity: anim1.value,
child: child,
),
transitionDuration: const Duration(milliseconds: 300));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment