* Task/Ticket desktop dialogs — widened from 520 → 600dp, and tasks now uses SizedBox(width: 600) instead of ConstrainedBox(maxWidth:) which was the root cause of the "still small" issue (max-only never forced expansion)

* Pass Slip + Leave — both dialogs gained an isSheet flag; callers now branch on AppBreakpoints.tablet: bottom sheet on mobile, dialog on desktop
This commit is contained in:
2026-04-30 06:45:51 +08:00
parent 48cd3bcd60
commit 783c5eb0be
19 changed files with 1224 additions and 887 deletions
@@ -261,9 +261,23 @@ class _AnnouncementCard extends ConsumerStatefulWidget {
class _AnnouncementCardState extends ConsumerState<_AnnouncementCard> {
static const _cooldownSeconds = 60;
DateTime? _sentAt;
Timer? _cooldownTimer;
void _startCooldownTimer() {
_cooldownTimer?.cancel();
_cooldownTimer = Timer.periodic(const Duration(milliseconds: 500), (_) {
if (!mounted) {
_cooldownTimer?.cancel();
return;
}
setState(() {});
if (!_inCooldown) _cooldownTimer?.cancel();
});
}
@override
void dispose() {
_cooldownTimer?.cancel();
super.dispose();
}
@@ -289,9 +303,15 @@ class _AnnouncementCardState extends ConsumerState<_AnnouncementCard> {
await ref
.read(announcementsControllerProvider)
.resendAnnouncementNotification(widget.announcement);
if (mounted) setState(() => _sentAt = DateTime.now());
if (mounted) {
setState(() => _sentAt = DateTime.now());
_startCooldownTimer();
}
} on AnnouncementNotificationException {
if (mounted) setState(() => _sentAt = DateTime.now());
if (mounted) {
setState(() => _sentAt = DateTime.now());
_startCooldownTimer();
}
} catch (e) {
if (mounted) showErrorSnackBar(context, 'Failed to send: $e');
}
@@ -326,13 +346,6 @@ class _AnnouncementCardState extends ConsumerState<_AnnouncementCard> {
final isAnnouncementPending =
pendingNew || pendingUpdates.containsKey(widget.announcement.id);
// Rebuild UI when cooldown is active.
if (_inCooldown) {
Future.delayed(const Duration(milliseconds: 500), () {
if (mounted) setState(() {});
});
}
final hasBanner = widget.announcement.bannerEnabled;
return Padding(
@@ -456,7 +469,14 @@ class _AnnouncementCardState extends ConsumerState<_AnnouncementCard> {
),
Padding(
padding: const EdgeInsets.fromLTRB(16, 6, 16, 0),
child: Text(widget.announcement.body, style: tt.bodyMedium),
child: Text(
widget.announcement.body,
style: tt.bodyMedium,
maxLines: widget.isExpanded ? null : 8,
overflow: widget.isExpanded
? TextOverflow.clip
: TextOverflow.ellipsis,
),
),
// Visible roles chips
Padding(