fix: eliminate transient dashboard viewport overflow

This commit is contained in:
Developer 2026-09-05 07:21:02 -04:00
parent 472b1ac994
commit a7cce30e3d
2 changed files with 207 additions and 173 deletions

View File

@ -53,6 +53,10 @@ class ResponsiveDashboardLayout extends ConsumerWidget {
DashboardLayout mode,
RideSession session,
) {
return LayoutBuilder(
builder: (context, constraints) {
final isShortPortrait = constraints.maxHeight < 620;
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
@ -94,11 +98,19 @@ class ResponsiveDashboardLayout extends ConsumerWidget {
// Body based on mode
if (mode == DashboardLayout.minimal) ...[
const Spacer(flex: 2),
const SpeedReadout(size: SpeedReadoutSize.hero),
const Spacer(flex: 2),
if (!isShortPortrait) const Spacer(flex: 2) else const Spacer(flex: 1),
const Flexible(
flex: 6,
child: Center(
child: SpeedReadout(size: SpeedReadoutSize.hero),
),
),
if (!isShortPortrait) const Spacer(flex: 2) else const Spacer(flex: 1),
Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
padding: EdgeInsets.symmetric(
horizontal: 16,
vertical: isShortPortrait ? 4 : 10,
),
decoration: _boxDecoration(context),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
@ -109,6 +121,7 @@ class ResponsiveDashboardLayout extends ConsumerWidget {
label: 'TRIP',
value: session.tripDistanceMiles.toStringAsFixed(2),
unit: 'MI',
compact: isShortPortrait,
),
),
),
@ -117,25 +130,29 @@ class ResponsiveDashboardLayout extends ConsumerWidget {
child: MetricTile(
label: 'STATUS',
value: session.state.name.toUpperCase(),
compact: isShortPortrait,
),
),
),
],
),
),
const SizedBox(height: 16),
const RideActionButton(),
SizedBox(height: isShortPortrait ? 6 : 16),
RideActionButton(compact: isShortPortrait),
] else if (mode == DashboardLayout.touring) ...[
const SizedBox(height: 6),
const SpeedReadout(size: SpeedReadoutSize.compact),
const SizedBox(height: 8),
SizedBox(height: isShortPortrait ? 2 : 6),
SpeedReadout(size: isShortPortrait ? SpeedReadoutSize.compact : SpeedReadoutSize.compact),
SizedBox(height: isShortPortrait ? 4 : 8),
const Expanded(
flex: 5,
child: DashboardMapPanel(),
),
const SizedBox(height: 10),
SizedBox(height: isShortPortrait ? 4 : 10),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
padding: EdgeInsets.symmetric(
horizontal: 8,
vertical: isShortPortrait ? 4 : 6,
),
decoration: _boxDecoration(context),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
@ -182,23 +199,31 @@ class ResponsiveDashboardLayout extends ConsumerWidget {
],
),
),
const SizedBox(height: 10),
const RideActionButton(),
SizedBox(height: isShortPortrait ? 4 : 10),
RideActionButton(compact: isShortPortrait),
] else ...[
// Sport Cockpit Mode
const Spacer(flex: 1),
const SpeedReadout(size: SpeedReadoutSize.hero),
const Spacer(flex: 1),
const Row(
if (!isShortPortrait) const Spacer(flex: 1),
Flexible(
flex: isShortPortrait ? 3 : 4,
child: const Center(
child: SpeedReadout(size: SpeedReadoutSize.hero),
),
),
if (!isShortPortrait) const Spacer(flex: 1),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(child: GForceIndicator()),
Expanded(child: LeanAngleIndicator()),
Expanded(child: GForceIndicator(compact: isShortPortrait)),
Expanded(child: LeanAngleIndicator(compact: isShortPortrait)),
],
),
const SizedBox(height: 14),
SizedBox(height: isShortPortrait ? 4 : 14),
Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: isShortPortrait ? 4 : 8,
),
decoration: _boxDecoration(context),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
@ -210,6 +235,7 @@ class ResponsiveDashboardLayout extends ConsumerWidget {
value: session.tripDistanceMiles.toStringAsFixed(2),
unit: 'MI',
icon: Icons.pin_drop_outlined,
compact: isShortPortrait,
),
),
),
@ -220,6 +246,7 @@ class ResponsiveDashboardLayout extends ConsumerWidget {
value: session.topSpeedMph.toStringAsFixed(0),
unit: 'MPH',
icon: Icons.speed_outlined,
compact: isShortPortrait,
),
),
),
@ -230,17 +257,20 @@ class ResponsiveDashboardLayout extends ConsumerWidget {
value: session.averageSpeedMph.toStringAsFixed(1),
unit: 'MPH',
icon: Icons.av_timer_outlined,
compact: isShortPortrait,
),
),
),
],
),
),
const SizedBox(height: 14),
const RideActionButton(),
SizedBox(height: isShortPortrait ? 4 : 14),
RideActionButton(compact: isShortPortrait),
],
],
);
},
);
}
// --------------------------------------------------------------------------

View File

@ -76,6 +76,10 @@ void main() {
group('Canonical Dashboard Viewport Matrix Tests', () {
final viewports = <String, Size>{
'320x640 (Small Compact Phone)': const Size(320, 640),
'320x520 (Constrained Small Phone)': const Size(320, 520),
'360x460 (Transient IME/Sheet Inset)': const Size(360, 460),
'412x460 (Pixel 8a Inset Viewport)': const Size(412, 460),
'390x480 (Constrained Portrait Phone)': const Size(390, 480),
'400x800 (Standard Phone Portrait)': const Size(400, 800),
'412x915 (Pixel-class Portrait)': const Size(412, 915),
'780x360 (Short Landscape Mount)': const Size(780, 360),