production
This commit is contained in:
@@ -816,12 +816,23 @@ class _CallButton extends StatelessWidget {
|
||||
/// the kitchen's. See [StopContact].
|
||||
final String? semanticLabel;
|
||||
|
||||
const _CallButton({required this.phone, this.size, this.semanticLabel});
|
||||
/// A disc rather than a rounded square. The sheets draw it beside a round
|
||||
/// avatar, where a square tile reads as a control belonging to something
|
||||
/// else; the cards keep the square, which matches the tiles around it.
|
||||
final bool round;
|
||||
|
||||
const _CallButton({
|
||||
required this.phone,
|
||||
this.size,
|
||||
this.semanticLabel,
|
||||
this.round = false,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _SquareIconButton(
|
||||
icon: LucideIcons.phone,
|
||||
round: round,
|
||||
size: size ?? math.max(52.0, 52.w),
|
||||
// ── Green, and the same green everywhere a phone appears ──
|
||||
//
|
||||
@@ -833,9 +844,9 @@ class _CallButton extends StatelessWidget {
|
||||
// app he already uses — it is what the glyph means before the palette
|
||||
// gets a say — and "done" is carried by a tick and a word, not by a hue
|
||||
// on a handset.
|
||||
background: ColorConstants.acceptGreen.withValues(alpha: 0.12),
|
||||
background: Narrative.emeraldWash,
|
||||
border: Colors.transparent,
|
||||
iconColor: ColorConstants.acceptGreen,
|
||||
iconColor: Narrative.emerald,
|
||||
semanticLabel: semanticLabel ?? 'Call this stop',
|
||||
onTap: () async {
|
||||
// A dialer that fails to open is silent by default: the rider is at
|
||||
@@ -859,6 +870,7 @@ class _SquareIconButton extends StatelessWidget {
|
||||
final Color iconColor;
|
||||
final String semanticLabel;
|
||||
final VoidCallback onTap;
|
||||
final bool round;
|
||||
|
||||
const _SquareIconButton({
|
||||
required this.icon,
|
||||
@@ -868,25 +880,29 @@ class _SquareIconButton extends StatelessWidget {
|
||||
required this.iconColor,
|
||||
required this.semanticLabel,
|
||||
required this.onTap,
|
||||
this.round = false,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final radius = BorderRadius.circular(
|
||||
round ? DesignConstants.radiusFull : DesignConstants.radiusXl,
|
||||
);
|
||||
return Semantics(
|
||||
button: true,
|
||||
label: semanticLabel,
|
||||
child: Material(
|
||||
color: background,
|
||||
borderRadius: BorderRadius.circular(DesignConstants.radiusXl),
|
||||
borderRadius: radius,
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
borderRadius: BorderRadius.circular(DesignConstants.radiusXl),
|
||||
borderRadius: radius,
|
||||
child: Container(
|
||||
width: size,
|
||||
height: size,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(DesignConstants.radiusXl),
|
||||
borderRadius: radius,
|
||||
border: Border.all(color: border, width: 1.5),
|
||||
),
|
||||
child: Icon(icon, color: iconColor, size: 22.sp),
|
||||
@@ -1044,71 +1060,21 @@ class _QueueHeading extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
],
|
||||
if (order != null) ...[
|
||||
const Spacer(),
|
||||
Flexible(child: _OrderProvenance(source: order!)),
|
||||
],
|
||||
// ── The provenance chip is gone ──
|
||||
//
|
||||
// `As assigned` / `Nearest first` sat at the head of the queue, in a
|
||||
// tinted pill with a glyph, telling the rider where the *ordering* of
|
||||
// his list came from. It is a fact about this app's sorting, not
|
||||
// about his work: he cannot act on it, he cannot change it, and on
|
||||
// the common day it said the same three words every time he opened
|
||||
// the tab. What he needs from that row is which trip and how far
|
||||
// through it he is, and both are already on it.
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// `Hub route` / `Nearest first` — where the queue's order came from.
|
||||
///
|
||||
/// Deliberately quiet. It is a provenance mark, not a warning: nearest-first
|
||||
/// is a reasonable order when nobody has assigned one, and the rider does not
|
||||
/// need alarming about it. What he needs is to not be told it is his route.
|
||||
class _OrderProvenance extends StatelessWidget {
|
||||
final RouteOrderSource source;
|
||||
|
||||
const _OrderProvenance({required this.source});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final assigned = source.isAdmin;
|
||||
final tint = assigned
|
||||
? ColorConstants.acceptGreen
|
||||
: ColorConstants.secondaryText;
|
||||
|
||||
return Tooltip(
|
||||
message: source.explanation,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 3.h),
|
||||
decoration: BoxDecoration(
|
||||
color: tint.withValues(alpha: assigned ? 0.10 : 0.07),
|
||||
borderRadius: BorderRadius.circular(DesignConstants.radiusFull),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
assigned ? LucideIcons.route : LucideIcons.navigation,
|
||||
size: 11.sp,
|
||||
color: tint,
|
||||
),
|
||||
SizedBox(width: 4.w),
|
||||
Flexible(
|
||||
child: Text(
|
||||
source.label,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 10.5.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
letterSpacing: 0.2,
|
||||
color: tint,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// `Bag 1 · Joe` — the pairing, as one object.
|
||||
///
|
||||
/// ── Why they are one line and not two facts ──
|
||||
|
||||
Reference in New Issue
Block a user