Files
dmc/app/lib/ui/app_shell.dart
T
Constantin LeueandClaude Sonnet 5 fc7d014fda Add top bar for switching between Plan and Fly mode
- TopModeBar widget: persistent pill-shaped header (HTML prototype:
  #topBarWrap/#editModeBtn/#flyModeBtn) tinted in the active mode's color,
  with the inactive mode offered as a solid button in the corner to switch
  into it.
- AppShell now provides a single shared Scaffold + Stack, overlaying
  TopModeBar on top of whichever screen (Plan/Fly) is active, instead of
  each screen owning its own Scaffold.
- Wired the Fly button to AppModeCubit.toFly(), which enforces the
  Ready-to-Fly gate (doc 4.5). Since upload/verify isn't wired up yet, the
  gate is never satisfied yet, so tapping Fly now shows a SnackBar instead
  of throwing an uncaught StateError.
- Extended the widget test to cover both the bar's presence and the
  gate-rejection path (was the source of a real bug: an initial
  negative-margin Container hack for the "bleed into the corner" look
  violated Container's margin.isNonNegative assertion and crashed the
  whole tree - fixed with padding instead).

Verified with flutter analyze, flutter test, and a real run on the
Pixel_10a emulator (visually matches the prototype screenshots in design/,
Fly-tap correctly shows the gate message without crashing or switching mode).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-27 07:40:40 +02:00

31 lines
1010 B
Dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../app_mode/app_mode_cubit.dart';
import 'screens/fly/fly_screen.dart';
import 'screens/plan/plan_screen.dart';
import 'widgets/top_mode_bar.dart';
/// Haelt die persistente Kopfleiste (Plan/Fly-Umschalter) und schaltet
/// darunter zwischen Plan- und Fly-Screen um, gesteuert von der App-Mode
/// State Machine (Architektur-Doku 2.2). Connect/Upload sind
/// Uebergangszustaende innerhalb des Plan-Screens (Handover-Prozess).
class AppShell extends StatelessWidget {
const AppShell({super.key});
@override
Widget build(BuildContext context) {
final mode = context.select((AppModeCubit c) => c.state.mode);
final screen = mode == AppMode.fly ? const FlyScreen() : const PlanScreen();
return Scaffold(
body: Stack(
children: [
Positioned.fill(child: screen),
const Align(alignment: Alignment.topCenter, child: TopModeBar()),
],
),
);
}
}