Files
sevenhill b22654b99f
Build Android (FCM) / build-android-fcm (push) Canceled after 0s
Build Android / build-android (push) Canceled after 0s
Build iOS / build-ios (push) Canceled after 0s
Build Linux / build-linux (push) Canceled after 0s
Build macOS / build-macos (push) Canceled after 0s
Build Windows / build-windows (push) Canceled after 0s
Native crypto / native-crypto (push) Canceled after 0s
Release (main) / android (oneme) (push) Canceled after 0s
Release (main) / android (qlyra) (push) Canceled after 0s
Release (main) / windows (push) Canceled after 0s
Release (main) / linux (push) Canceled after 0s
Release (main) / macos (push) Canceled after 0s
Release (main) / ios (push) Canceled after 0s
Release (main) / release (push) Canceled after 0s
Update Qlyra to 1.0.13 with messaging, media and plugin improvements
2026-09-10 17:55:55 +03:00

103 lines
2.6 KiB
Dart

import 'package:flutter/material.dart';
import '../../core/config/app_shape.dart';
/// Standard rounded top shape for modal bottom sheets.
const RoundedRectangleBorder kSheetShape = AppShape.sheetBorder;
/// Pill-shaped action button for the bottom row of a modal sheet.
class SheetButton extends StatelessWidget {
final String label;
final bool filled;
final VoidCallback? onTap;
final Color? color;
const SheetButton({
super.key,
required this.label,
required this.filled,
required this.onTap,
this.color,
});
@override
Widget build(BuildContext context) {
final cs = Theme.of(context).colorScheme;
final disabled = onTap == null;
final fill = color ?? cs.primary;
final labelColor = filled ? cs.onPrimary : (color ?? cs.onSurface);
return GestureDetector(
onTap: onTap,
child: Container(
height: 44,
alignment: Alignment.center,
decoration: BoxDecoration(
color: filled
? (disabled ? fill.withValues(alpha: 0.4) : fill)
: cs.surfaceContainerHighest,
borderRadius: BorderRadius.circular(22),
),
child: Text(
label,
style: TextStyle(
color: disabled
? labelColor.withValues(alpha: filled ? 0.85 : 0.4)
: labelColor,
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
),
);
}
}
/// Grabber row that keeps the pill centred while an action sits at the edge.
class SheetGrabberBar extends StatelessWidget {
static const double height = 34;
static const double actionInset = 8;
final Widget action;
const SheetGrabberBar({super.key, required this.action});
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
height: height,
child: Stack(
alignment: Alignment.center,
children: [
const SheetGrabber(margin: EdgeInsets.zero),
Positioned(right: actionInset, child: action),
],
),
);
}
}
/// The little drag "grabber" pill shown at the top of a bottom sheet.
class SheetGrabber extends StatelessWidget {
final EdgeInsetsGeometry margin;
const SheetGrabber({
super.key,
this.margin = const EdgeInsets.symmetric(vertical: 10),
});
@override
Widget build(BuildContext context) {
final cs = Theme.of(context).colorScheme;
return Container(
width: 40,
height: 4,
margin: margin,
decoration: BoxDecoration(
color: cs.onSurfaceVariant.withValues(alpha: 0.35),
borderRadius: BorderRadius.circular(2),
),
);
}
}