From 8427824951a9389e37987f49e3cb3227f64e2dc9 Mon Sep 17 00:00:00 2001 From: Thiru-tenext Date: Mon, 28 Sep 2026 12:54:03 +0530 Subject: [PATCH] A launch that opens in brand, and a sheet that stops resizing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ── The splash, in three beats ── Crimson edge to edge with the truck running across it in white; the invert; then the mark. The red starts before Flutter does. Four surfaces painted white before any Dart runs — launch_background at both API levels, windowSplashScreenBackground on Android 12+ in light and dark, and the iOS launch storyboard — and leaving any one of them white makes the launch a white flash followed by a red one. That flash is the only part of a launch a customer consciously notices. The invert is one gesture rather than a fade. A white truck on a background turning white is an invisible truck, so the ground lightens as the truck darkens, off one controller, and the screen turns itself inside out with the truck still on it. Fading it would have left the screen empty for the moment before the mark. The truck's colour is no longer its own: it is painted through srcIn, so the file's palette is discarded and only alpha survives. A replacement Lottie now needs no preparation, and tool/lottie_brand.py is off this path. `splash.json` is a seamless 3.9s loop — frame 0 is frame 60, the truck never arrives or departs — so there is no completion to hand over on. _truckBeat is a decision about how long a launch may hold somebody, not a property of the file. The comment claiming six seconds was wrong on both counts. ── Three things the splash was getting wrong quietly ── It showed the wrong logo: doormile-icon.png, the previous mark, to a customer who had just tapped the new one. tool/icons.py now cuts doormile-mark.png from the same master alpha as the launcher icon, so they cannot drift again. The fallback loader was invisible on red. _RoadLoader painted in DmColors.brand on what used to be a white screen; on crimson that is crimson on crimson, and it drew nothing at all on exactly the devices that had fallen back to it. The mark appeared and left in the same frame — _minimum was the sum of the beats exactly, so the clock ran out as the entrance finished. Hence _markHold. ── The truck was not in the middle ── Not a layout bug: both beats sit in a Center and always did. The artwork is drawn low and to the right inside its own 500x500 composition, so a centred widget rendered an off-centre picture — 30pt right, 36pt down. splash_centring_test.dart renders a frame at phone size and density, finds the ink and fails if either beat drifts. It is the only form of test that could have caught this, and the one that will catch it again when the Lottie is replaced, which is when the correction goes stale. Two things it taught: one enormous pump does not let the splash's async start-up chain advance, and capturing at pixelRatio 1 rasterizes the speed lines too faintly to detect, which truncates the bounding box and moves the measured centre by 12pt. ── The destination sheet stops resizing ── Tapping ONE TOUCH opened a tall sheet that snapped shorter a few frames later. DmAsyncList renders four skeleton rows while it loads — 302pt — and the states that replace them are nearer 200; the sheet was Flexible, so it was as tall as whichever state its content happened to be in, and the modal is still animating up while that swap happens. The list now lives in a box of one height. That also removes a second resize: the sheet grew from 48% of the screen to 74% when a state was picked. Both steps now measure 64% and it never changes size again. And DmAsyncList takes initialItems, fed by AppState.cachedCities: FutureBuilder reports `waiting` on its first build even for an already-complete future, so a warm cache still flashed a skeleton over data it already had. Three skeleton rows here rather than four — sheet_stability_test caught that 302pt overflows the smallest box the clamp can produce. --- .../res/drawable-v21/launch_background.xml | 12 +- .../main/res/drawable/launch_background.xml | 12 +- .../src/main/res/values-night-v31/styles.xml | 6 +- .../app/src/main/res/values-v31/styles.xml | 2 +- android/app/src/main/res/values/colors.xml | 7 + assets/images/doormile-mark.png | Bin 0 -> 73003 bytes design/screens/00-splash-animation.png | Bin 27521 -> 0 bytes design/screens/00-splash-truck.png | Bin 0 -> 38124 bytes design/screens/00b-splash-invert.png | Bin 0 -> 38115 bytes design/screens/00b-splash-mark.png | Bin 55314 -> 0 bytes design/screens/00c-splash-mark.png | Bin 0 -> 71188 bytes design/screens/06-orders-active.png | Bin 253535 -> 252217 bytes design/screens/07-orders-completed.png | Bin 121963 -> 122102 bytes design/screens/11-destination-states.png | Bin 190912 -> 167980 bytes design/screens/12-destination-districts.png | Bin 201764 -> 190640 bytes design/screens/16-pickup-booked.png | Bin 206593 -> 208154 bytes design/screens/17-receipt.png | Bin 189033 -> 189093 bytes design/screens/README.md | 5 +- ios/Runner/Base.lproj/LaunchScreen.storyboard | 7 +- lib/state/app_state.dart | 21 ++ lib/ui/screens/sheets/destination_sheet.dart | 29 +- lib/ui/screens/splash_screen.dart | 343 +++++++++++++----- lib/ui/tokens.dart | 19 + lib/ui/widgets/states.dart | 24 +- pubspec.yaml | 2 +- test/design_snapshot_test.dart | 47 ++- test/sheet_stability_test.dart | 140 +++++++ test/snapshots/00-splash-animation.png | Bin 27521 -> 0 bytes test/snapshots/00-splash-truck.png | Bin 0 -> 38124 bytes test/snapshots/00b-splash-invert.png | Bin 0 -> 38115 bytes test/snapshots/00b-splash-mark.png | Bin 55314 -> 0 bytes test/snapshots/00c-splash-mark.png | Bin 0 -> 71188 bytes test/snapshots/04-orders.png | Bin 253535 -> 252217 bytes test/snapshots/04b-orders-completed.png | Bin 121963 -> 122102 bytes test/snapshots/07-destination-states.png | Bin 190912 -> 167980 bytes test/snapshots/07b-destination-districts.png | Bin 201764 -> 190640 bytes test/snapshots/11-booked.png | Bin 206593 -> 208154 bytes test/snapshots/12-receipt.png | Bin 189033 -> 189093 bytes test/splash_centring_test.dart | 174 +++++++++ tool/icons.py | 49 +++ tool/screens.sh | 5 +- 41 files changed, 772 insertions(+), 132 deletions(-) create mode 100644 assets/images/doormile-mark.png delete mode 100644 design/screens/00-splash-animation.png create mode 100644 design/screens/00-splash-truck.png create mode 100644 design/screens/00b-splash-invert.png delete mode 100644 design/screens/00b-splash-mark.png create mode 100644 design/screens/00c-splash-mark.png create mode 100644 test/sheet_stability_test.dart delete mode 100644 test/snapshots/00-splash-animation.png create mode 100644 test/snapshots/00-splash-truck.png create mode 100644 test/snapshots/00b-splash-invert.png delete mode 100644 test/snapshots/00b-splash-mark.png create mode 100644 test/snapshots/00c-splash-mark.png create mode 100644 test/splash_centring_test.dart diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml index 7ef0971..9c6bbb1 100644 --- a/android/app/src/main/res/drawable-v21/launch_background.xml +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -1,11 +1,11 @@ + Deliberately empty, and deliberately crimson. Empty because it used to + centre a mark, which meant the customer saw a logo, then Flutter's splash, + then the logo again. Crimson because the Flutter splash now opens on + crimson: paint this white and the launch is a white flash followed by a + red one, which is the seam this file exists to remove. --> - + diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml index 7ef0971..9c6bbb1 100644 --- a/android/app/src/main/res/drawable/launch_background.xml +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -1,11 +1,11 @@ + Deliberately empty, and deliberately crimson. Empty because it used to + centre a mark, which meant the customer saw a logo, then Flutter's splash, + then the logo again. Crimson because the Flutter splash now opens on + crimson: paint this white and the launch is a white flash followed by a + red one, which is the seam this file exists to remove. --> - + diff --git a/android/app/src/main/res/values-night-v31/styles.xml b/android/app/src/main/res/values-night-v31/styles.xml index 6761aa8..48706de 100644 --- a/android/app/src/main/res/values-night-v31/styles.xml +++ b/android/app/src/main/res/values-night-v31/styles.xml @@ -3,13 +3,13 @@