device infos

This commit is contained in:
2026-08-28 15:07:30 +05:30
parent 5723d373b2
commit 69f4f3e909
84 changed files with 4337 additions and 2339 deletions

View File

@@ -36,23 +36,23 @@ class PickupCard extends StatelessWidget {
final bool enabled;
final bool isSkipped;
/// The bag this order travels in, as recorded at the counter. Empty on a
/// parcel route, where there is no load to match against. See [BagManifest].
final String bag;
/// The label this order travels in, as recorded at the counter. Empty on a
/// parcel route, where there is no load to match against. See [OrderManifest].
final String label;
/// Orders the rider is carrying.
///
/// Needed because "picked up" is not a *status* on this screen — the accepted
/// store normalises these rows to `accepted`, and what actually records the
/// hand-over is the collected set. Without it, [MilkRun.workingKind] reads a
/// bag already in the rider's box as still needing collection, and the button
/// label already in the rider's box as still needing collection, and the button
/// says **Start Pickup** for a delivery.
final Set<String> collectedIds;
/// Orders whose delivery leg the rider has actually started.
///
/// Distinct from [collectedIds] on purpose, and the distinction is the whole
/// point of the chip: a bag in his box is **PICKED**, a round he has set off
/// point of the chip: a label in his box is **PICKED**, a round he has set off
/// on is **ACTIVE**. The backend cannot answer this — `pickup-complete`
/// stamps a hyperlocal consignment `Out_for_Delivery` at the counter — so the
/// rung is resolved through [MilkRun.stageOf] against this set rather than
@@ -67,7 +67,7 @@ class PickupCard extends StatelessWidget {
this.riderSpeedMps,
this.enabled = true,
this.isSkipped = false,
this.bag = '',
this.label = '',
this.collectedIds = const {},
this.outForDeliveryIds = const {},
});
@@ -97,7 +97,7 @@ class PickupCard extends StatelessWidget {
//
// The booking adapter stamps `type: pickup` on every row it builds, so a
// milk-run order the rider has already collected still described itself as
// a pickup — and this card offered **Start Pickup** for a bag sitting in
// a pickup — and this card offered **Start Pickup** for a label sitting in
// his box. See [MilkRun.workingKind].
final StopKind kind = MilkRun.workingKind(item, collectedIds: collectedIds);
@@ -201,7 +201,7 @@ class PickupCard extends StatelessWidget {
// ── Identity left, state and journey right ──
//
// The distance and ETA had a full-width row of their own under
// the bag — a fifth storey on a card the rider reads at a red
// the label — a fifth storey on a card the rider reads at a red
// light. Home's group node and this queue's own UP NEXT tile
// already carry the journey as a narrow right-hand column at
// the headline's shoulder; the live card was the one surface
@@ -272,7 +272,7 @@ class PickupCard extends StatelessWidget {
// ── The pairing, as one object ──
//
// `Bag 1 · Joe`, not a bag chip in one place and a
// `Bag 1 · Joe`, not a label chip in one place and a
// name in another. The join between them is the
// entire operational risk on a meal run, and making
// the rider do it himself at a gate is where the
@@ -280,10 +280,10 @@ class PickupCard extends StatelessWidget {
// the headline above, so the pair is spatial here;
// the written form earns its place further down the
// queue — see [_LaterRow] — and on the manifest.)
if (bag.isNotEmpty) ...[
if (label.isNotEmpty) ...[
SizedBox(height: 14.h),
_BagPair(
bag: bag,
_LabelPair(
label: label,
customer: '',
muted: !enabled,
size: 15.5,
@@ -371,7 +371,7 @@ class PickupCard extends StatelessWidget {
//
// Once the food is in the box the pickup is history — but it is
// still what establishes custody, and on a run with two kitchens
// it is how he knows which shelf this bag came off. So it stays,
// it is how he knows which shelf this label came off. So it stays,
// one line, under a hairline, at half the weight of the name
// above.
if (dropLeads && pickupName.isNotEmpty) ...[
@@ -534,7 +534,7 @@ class PickupCard extends StatelessWidget {
// because this method opens the map screen directly rather than through
// `startPickup`, and a stop that reached it in the pickup phase would put
// the rider through a map, an I'VE ARRIVED and a confirmation sheet for a
// bag he is supposed to collect at the counter with the rest of them. See
// label he is supposed to collect at the counter with the rest of them. See
// [MilkRun.worksOnOwnScreen].
if (!MilkRun.worksOnOwnScreen(item, collectedIds: collectedIds)) {
AppFeedback.info(
@@ -919,7 +919,7 @@ class _SquareIconButton extends StatelessWidget {
/// ```
/// NOW one task card, full weight, one big action
/// UP NEXT who and where, quietly — no action
/// LATER one line each: bag, name, distance
/// LATER one line each: label, name, distance
/// SKIPPED the reason, and the way back in
/// ```
///
@@ -963,8 +963,8 @@ class _QueueRow {
final QueueDensity density;
final int displayStep;
/// The bag this order travels in, as recorded at the counter.
final String bag;
/// The label this order travels in, as recorded at the counter.
final String label;
/// Why a skipped stop was skipped. Read from the skip cache rather than the
/// stop, because the stop is refetched from the API every three seconds and
@@ -975,14 +975,14 @@ class _QueueRow {
: stop = null,
density = QueueDensity.later,
displayStep = 0,
bag = '',
label = '',
reason = '';
const _QueueRow.stop({
required this.stop,
required this.density,
required this.displayStep,
required this.bag,
required this.label,
this.reason = '',
}) : heading = null,
count = 0;
@@ -1079,33 +1079,38 @@ class _QueueHeading extends StatelessWidget {
///
/// ── Why they are one line and not two facts ──
///
/// The rider is holding a bag and looking for a door. Printing the bag in one
/// The rider is holding a label and looking for a door. Printing the label in one
/// place and the customer in another makes him do the join himself, on a phone,
/// at a gate — and that join is the entire operational risk on a meal run: five
/// near-identical lunch bags, one confident rider, the wrong door.
///
/// So they are written the way he thinks them.
class _BagPair extends StatelessWidget {
final String bag;
class _LabelPair extends StatelessWidget {
final String label;
final String customer;
final bool muted;
/// Bigger on the live card, quieter down the queue.
final double size;
const _BagPair({
required this.bag,
const _LabelPair({
required this.label,
required this.customer,
this.muted = false,
this.size = 15,
});
String get _bagText =>
bag.toLowerCase().startsWith('bag ') ? bag : 'Bag $bag';
/// ── The word is gone; the code is not ──
///
/// This prefixed everything with `Bag `, so a counter's own code rendered as
/// `Bag DG-1042` and an app-derived number rendered as `Bag 3` — a reference
/// to an object nobody had labelled. What a counter prints is shown exactly
/// as it was sent, and nothing is shown where nothing was sent.
String get _labelText => label;
@override
Widget build(BuildContext context) {
if (bag.isEmpty) return const SizedBox.shrink();
if (label.isEmpty) return const SizedBox.shrink();
return Row(
mainAxisSize: MainAxisSize.min,
@@ -1119,7 +1124,7 @@ class _BagPair extends StatelessWidget {
borderRadius: BorderRadius.circular(DesignConstants.radiusLg),
),
child: Text(
_bagText,
_labelText,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
@@ -1223,14 +1228,14 @@ class _TaskChip extends StatelessWidget {
/// notes, no money. Preparing is a glance; acting is the card above.
class _NextCard extends StatelessWidget {
final Map<String, dynamic> item;
final String bag;
final String label;
final double? distanceMeters;
final double? riderSpeedMps;
final VoidCallback onOpen;
const _NextCard({
required this.item,
required this.bag,
required this.label,
required this.distanceMeters,
required this.riderSpeedMps,
required this.onOpen,
@@ -1293,9 +1298,9 @@ class _NextCard extends StatelessWidget {
),
),
],
if (bag.isNotEmpty) ...[
if (label.isNotEmpty) ...[
SizedBox(height: 10.h),
_BagPair(bag: bag, customer: '', muted: true, size: 14),
_LabelPair(label: label, customer: '', muted: true, size: 14),
],
],
),
@@ -1312,13 +1317,13 @@ class _NextCard extends StatelessWidget {
/// take in at once.
class _LaterRow extends StatelessWidget {
final Map<String, dynamic> item;
final String bag;
final String label;
final double? distanceMeters;
final VoidCallback onOpen;
const _LaterRow({
required this.item,
required this.bag,
required this.label,
required this.distanceMeters,
required this.onOpen,
});
@@ -1333,8 +1338,8 @@ class _LaterRow extends StatelessWidget {
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 12.h),
child: Row(
children: [
if (bag.isNotEmpty) ...[
_BagPair(bag: bag, customer: '', muted: true, size: 13),
if (label.isNotEmpty) ...[
_LabelPair(label: label, customer: '', muted: true, size: 13),
SizedBox(width: 12.w),
],
Expanded(
@@ -1375,14 +1380,14 @@ class _LaterRow extends StatelessWidget {
/// and nothing else.
class _SkippedRow extends StatelessWidget {
final Map<String, dynamic> item;
final String bag;
final String label;
final String reason;
final VoidCallback onResume;
final VoidCallback onOpen;
const _SkippedRow({
required this.item,
required this.bag,
required this.label,
required this.reason,
required this.onResume,
required this.onOpen,
@@ -1441,8 +1446,8 @@ class _SkippedRow extends StatelessWidget {
SizedBox(height: 12.h),
Row(
children: [
if (bag.isNotEmpty) ...[
_BagPair(bag: bag, customer: '', muted: true, size: 13.5),
if (label.isNotEmpty) ...[
_LabelPair(label: label, customer: '', muted: true, size: 13.5),
SizedBox(width: 12.w),
],
Expanded(