chitfund/luckychit/lib/core/utils/snackbar_util.dart

284 lines
7.1 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
enum SnackbarType {
success,
error,
warning,
info,
}
class SnackbarUtil {
static ColorScheme get _scheme {
final ctx = Get.context;
if (ctx == null) {
return const ColorScheme.light();
}
return Theme.of(ctx).colorScheme;
}
/// Show a success snackbar
static void showSuccess(
String message, {
String? title,
Duration? duration,
}) {
_showSnackbar(
title: title ?? 'Success',
message: message,
type: SnackbarType.success,
duration: duration,
);
}
/// Show an error snackbar
static void showError(
String message, {
String? title,
Duration? duration,
}) {
_showSnackbar(
title: title ?? 'Error',
message: message,
type: SnackbarType.error,
duration: duration,
);
}
/// Show a warning snackbar
static void showWarning(
String message, {
String? title,
Duration? duration,
}) {
_showSnackbar(
title: title ?? 'Warning',
message: message,
type: SnackbarType.warning,
duration: duration,
);
}
/// Show an info snackbar
static void showInfo(
String message, {
String? title,
Duration? duration,
}) {
_showSnackbar(
title: title ?? 'Info',
message: message,
type: SnackbarType.info,
duration: duration,
);
}
/// Internal method to show snackbar with custom styling
static void _showSnackbar({
required String title,
required String message,
required SnackbarType type,
Duration? duration,
}) {
final config = _getSnackbarConfig(type);
Get.snackbar(
title,
message,
snackPosition: SnackPosition.TOP,
backgroundColor: config.backgroundColor,
colorText: config.textColor,
icon: Icon(
config.icon,
color: config.iconColor,
size: 28.w,
),
shouldIconPulse: true,
borderRadius: 12.r,
margin: EdgeInsets.all(16.w),
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 16.h),
duration: duration ?? const Duration(seconds: 3),
isDismissible: true,
dismissDirection: DismissDirection.horizontal,
forwardAnimationCurve: Curves.easeOutBack,
reverseAnimationCurve: Curves.easeInBack,
animationDuration: const Duration(milliseconds: 500),
boxShadows: [
BoxShadow(
color: config.backgroundColor.withOpacity(0.3),
blurRadius: 12,
offset: const Offset(0, 4),
),
],
titleText: Text(
title,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.bold,
color: config.textColor,
),
),
messageText: Text(
message,
style: TextStyle(
fontSize: 14.sp,
color: config.textColor.withOpacity(0.9),
),
),
);
}
/// Get configuration based on snackbar type
static _SnackbarConfig _getSnackbarConfig(SnackbarType type) {
final scheme = _scheme;
switch (type) {
case SnackbarType.success:
return _SnackbarConfig(
backgroundColor: scheme.primary,
textColor: scheme.onPrimary,
iconColor: scheme.onPrimary,
icon: Icons.check_circle_rounded,
);
case SnackbarType.error:
return _SnackbarConfig(
backgroundColor: scheme.error,
textColor: scheme.onError,
iconColor: scheme.onError,
icon: Icons.error_rounded,
);
case SnackbarType.warning:
return _SnackbarConfig(
backgroundColor: scheme.tertiary,
textColor: scheme.onTertiary,
iconColor: scheme.onTertiary,
icon: Icons.warning_rounded,
);
case SnackbarType.info:
return _SnackbarConfig(
backgroundColor: scheme.secondary,
textColor: scheme.onSecondary,
iconColor: scheme.onSecondary,
icon: Icons.info_rounded,
);
}
}
/// Show a loading snackbar that can be dismissed programmatically
static void showLoading(String message) {
final scheme = _scheme;
Get.snackbar(
'Loading',
message,
snackPosition: SnackPosition.BOTTOM,
backgroundColor: scheme.inverseSurface,
colorText: scheme.onInverseSurface,
icon: SizedBox(
width: 24.w,
height: 24.h,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(scheme.onInverseSurface),
),
),
shouldIconPulse: false,
borderRadius: 12.r,
margin: EdgeInsets.all(16.w),
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 16.h),
duration: const Duration(days: 1), // Long duration
isDismissible: false,
showProgressIndicator: false,
);
}
/// Dismiss the current snackbar
static void dismiss() {
if (Get.isSnackbarOpen) {
Get.closeCurrentSnackbar();
}
}
/// Show a custom snackbar with action button
static void showWithAction({
required String title,
required String message,
required String actionLabel,
required VoidCallback onAction,
SnackbarType type = SnackbarType.info,
Duration? duration,
}) {
final config = _getSnackbarConfig(type);
Get.snackbar(
title,
message,
snackPosition: SnackPosition.TOP,
backgroundColor: config.backgroundColor,
colorText: config.textColor,
icon: Icon(
config.icon,
color: config.iconColor,
size: 28.w,
),
shouldIconPulse: true,
borderRadius: 12.r,
margin: EdgeInsets.all(16.w),
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 16.h),
duration: duration ?? const Duration(seconds: 5),
isDismissible: true,
mainButton: TextButton(
onPressed: () {
Get.closeCurrentSnackbar();
onAction();
},
style: TextButton.styleFrom(
foregroundColor: Colors.white,
backgroundColor: Colors.white.withOpacity(0.2),
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.r),
),
),
child: Text(
actionLabel,
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w600,
),
),
),
titleText: Text(
title,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.bold,
color: config.textColor,
),
),
messageText: Text(
message,
style: TextStyle(
fontSize: 14.sp,
color: config.textColor.withOpacity(0.9),
),
),
);
}
}
/// Internal configuration class for snackbar styling
class _SnackbarConfig {
final Color backgroundColor;
final Color textColor;
final Color iconColor;
final IconData icon;
_SnackbarConfig({
required this.backgroundColor,
required this.textColor,
required this.iconColor,
required this.icon,
});
}