Added programmer role and fixed snackbar not showing

This commit is contained in:
2026-03-16 07:23:20 +08:00
parent 9f7791e56f
commit 81853c4367
23 changed files with 362 additions and 65 deletions
+146 -31
View File
@@ -1,5 +1,11 @@
import 'package:flutter/material.dart';
import 'package:awesome_snackbar_content/awesome_snackbar_content.dart';
import 'package:flutter/foundation.dart';
/// A global messenger key used to show snackbars from contexts without a
/// Scaffold (e.g. dialogs, background callbacks, or tests).
final GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey =
GlobalKey<ScaffoldMessengerState>();
/// Helper wrappers around `awesome_snackbar_content` so that callers
/// can show snackbars with a consistent look and only specify a message and
@@ -28,6 +34,7 @@ void showAwesomeSnackBar(
required String title,
required String message,
required SnackType snackType,
bool retry = true,
}) {
// Add margin and padding so even very short messages feel substantial.
final snackBar = SnackBar(
@@ -47,39 +54,147 @@ void showAwesomeSnackBar(
),
);
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(snackBar);
// Prefer a local ScaffoldMessenger when available, but prefer the global
// `scaffoldMessengerKey` if it's already ready. This increases reliability
// when callers are inside dialogs or other overlays.
final globalMessenger = scaffoldMessengerKey.currentState;
final localMessenger = ScaffoldMessenger.maybeOf(context);
final messenger = localMessenger ?? globalMessenger;
if (messenger == null) {
if (kDebugMode) {
debugPrint(
'showAwesomeSnackBar: no messenger available; scheduling fallback',
);
}
// If the scaffold messenger is not available yet, schedule a post-frame
// callback that uses the global messenger (if it becomes available).
if (retry) {
WidgetsBinding.instance.addPostFrameCallback((_) {
final gm = scaffoldMessengerKey.currentState;
if (gm != null) {
try {
gm
..hideCurrentSnackBar()
..showSnackBar(snackBar);
if (kDebugMode) {
debugPrint(
'showAwesomeSnackBar: shown via global messenger (post-frame)',
);
}
} catch (e) {
if (kDebugMode) {
debugPrint('showAwesomeSnackBar: post-frame show failed: $e');
}
}
} else if (kDebugMode) {
debugPrint(
'showAwesomeSnackBar: global messenger still null after frame',
);
}
});
}
return;
}
try {
messenger
..hideCurrentSnackBar()
..showSnackBar(snackBar);
if (kDebugMode) {
debugPrint(
'showAwesomeSnackBar: shown via ${identical(messenger, globalMessenger) ? 'global' : 'local'} messenger',
);
}
} catch (e) {
if (kDebugMode) debugPrint('showAwesomeSnackBar: show failed: $e');
}
}
void showSuccessSnackBar(BuildContext context, String message) =>
showAwesomeSnackBar(
context,
title: 'Success',
message: message,
snackType: SnackType.success,
);
void showSuccessSnackBar(BuildContext context, String message) {
showSuccessSnackBarGlobal(message);
}
void showErrorSnackBar(BuildContext context, String message) =>
showAwesomeSnackBar(
context,
title: 'Error',
message: message,
snackType: SnackType.error,
);
void showErrorSnackBar(BuildContext context, String message) {
showErrorSnackBarGlobal(message);
}
void showInfoSnackBar(BuildContext context, String message) =>
showAwesomeSnackBar(
context,
title: 'Info',
message: message,
snackType: SnackType.info,
);
void showInfoSnackBar(BuildContext context, String message) {
showInfoSnackBarGlobal(message);
}
void showWarningSnackBar(BuildContext context, String message) =>
showAwesomeSnackBar(
context,
title: 'Warning',
message: message,
snackType: SnackType.warning,
);
void showWarningSnackBar(BuildContext context, String message) {
showWarningSnackBarGlobal(message);
}
/// Global helpers that use the app-level `scaffoldMessengerKey` directly.
/// Use these from places where a valid `BuildContext` with a Scaffold may
/// not be available (e.g. dialog builders or background callbacks).
void showAwesomeSnackBarGlobal({
required String title,
required String message,
required SnackType snackType,
}) {
final gm = scaffoldMessengerKey.currentState;
if (gm == null) {
if (kDebugMode) {
debugPrint('showAwesomeSnackBarGlobal: global messenger null');
}
return;
}
final snackBar = SnackBar(
elevation: 0,
behavior: SnackBarBehavior.floating,
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
padding: EdgeInsets.zero,
backgroundColor: Colors.transparent,
content: Container(
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8),
child: AwesomeSnackbarContent(
title: title,
message: message,
contentType: _mapSnackType(snackType),
),
),
);
try {
gm
..hideCurrentSnackBar()
..showSnackBar(snackBar);
if (kDebugMode) {
debugPrint('showAwesomeSnackBarGlobal: shown');
}
} catch (e) {
if (kDebugMode) {
debugPrint('showAwesomeSnackBarGlobal: show failed: $e');
}
}
}
void showSuccessSnackBarGlobal(String message) => showAwesomeSnackBarGlobal(
title: 'Success',
message: message,
snackType: SnackType.success,
);
void showErrorSnackBarGlobal(String message) => showAwesomeSnackBarGlobal(
title: 'Error',
message: message,
snackType: SnackType.error,
);
void showInfoSnackBarGlobal(String message) => showAwesomeSnackBarGlobal(
title: 'Info',
message: message,
snackType: SnackType.info,
);
void showWarningSnackBarGlobal(String message) => showAwesomeSnackBarGlobal(
title: 'Warning',
message: message,
snackType: SnackType.warning,
);