78 lines
2.3 KiB
Dart
78 lines
2.3 KiB
Dart
import 'dart:ui';
|
|
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:please_pay_me/theme/tokens.dart';
|
|
import 'package:please_pay_me/ui/atoms/app_text.dart';
|
|
|
|
/// iOS has no SnackBar — the platform idiom is a floating blurred capsule
|
|
/// (AirPods / Silent-mode style). Kept dismiss-free and auto-hiding.
|
|
class AppToast extends StatelessWidget {
|
|
const AppToast({
|
|
super.key,
|
|
required this.message,
|
|
this.icon = CupertinoIcons.check_mark_circled_solid,
|
|
this.tint = AppColors.accent,
|
|
});
|
|
|
|
final String message;
|
|
final IconData? icon;
|
|
final Color tint;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return ClipRRect(
|
|
borderRadius: BorderRadius.circular(AppRadii.capsule),
|
|
child: BackdropFilter(
|
|
filter: ImageFilter.blur(sigmaX: 20, sigmaY: 20),
|
|
child: Container(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: AppSpacing.s4,
|
|
vertical: AppSpacing.s3,
|
|
),
|
|
decoration: BoxDecoration(
|
|
color: AppColors.of(context, AppColors.groupedSurface).withValues(alpha: 0.82),
|
|
borderRadius: BorderRadius.circular(AppRadii.capsule),
|
|
boxShadow: const [
|
|
BoxShadow(color: Color(0x1F000000), blurRadius: 24, offset: Offset(0, 8)),
|
|
],
|
|
),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
if (icon != null) ...[
|
|
Icon(icon, size: 20, color: AppColors.of(context, tint)),
|
|
const SizedBox(width: AppSpacing.s2),
|
|
],
|
|
Flexible(child: AppText.subhead(message, color: AppColors.label)),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> showAppToast(
|
|
BuildContext context, {
|
|
required String message,
|
|
IconData? icon = CupertinoIcons.check_mark_circled_solid,
|
|
Duration duration = const Duration(seconds: 2),
|
|
}) async {
|
|
final overlay = Overlay.of(context, rootOverlay: true);
|
|
final entry = OverlayEntry(
|
|
builder: (ctx) => Positioned(
|
|
left: AppSpacing.s5,
|
|
right: AppSpacing.s5,
|
|
bottom: MediaQuery.of(ctx).padding.bottom + AppSpacing.s7,
|
|
child: SafeArea(
|
|
top: false,
|
|
child: Center(child: AppToast(message: message, icon: icon)),
|
|
),
|
|
),
|
|
);
|
|
|
|
overlay.insert(entry);
|
|
await Future<void>.delayed(duration);
|
|
entry.remove();
|
|
}
|