Files
dmc/app/lib/app_mode/app_mode_cubit.dart
T
Constantin LeueandClaude Sonnet 5 346fcc2183 Add Flutter project skeleton (Android-only MVP)
Five-layer architecture per DMC_Architektur_und_Design.md: FlightControllerLink
abstraction (Mock + MSP stub), protocol-neutral mission domain layer, App-Mode
state machine with Ready-to-Fly gate, Drift persistence schema, and placeholder
UI screens wired via go_router. App icon generated from design/Y2_pink_dark.svg.
Verified with flutter analyze and flutter test.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 21:28:25 +02:00

66 lines
1.9 KiB
Dart

import 'package:flutter_bloc/flutter_bloc.dart';
/// Explizite Zustandsfolge Plan -> Connect -> Upload -> Fly
/// (Architektur-Doku 2.2).
enum AppMode { plan, connect, upload, fly }
class AppModeState {
const AppModeState({
this.mode = AppMode.plan,
this.missionUploaded = false,
this.missionVerified = false,
this.droneArmed = false,
});
final AppMode mode;
final bool missionUploaded;
final bool missionVerified;
final bool droneArmed;
/// Ready-to-Fly-Gate (Doku 2.2 / 4.5): Upload + verifiziert + disarmed.
/// Muss technisch erzwungen werden, nicht nur als UI-Konvention gelten.
bool get readyToFly => missionUploaded && missionVerified && !droneArmed;
AppModeState copyWith({
AppMode? mode,
bool? missionUploaded,
bool? missionVerified,
bool? droneArmed,
}) {
return AppModeState(
mode: mode ?? this.mode,
missionUploaded: missionUploaded ?? this.missionUploaded,
missionVerified: missionVerified ?? this.missionVerified,
droneArmed: droneArmed ?? this.droneArmed,
);
}
}
class AppModeCubit extends Cubit<AppModeState> {
AppModeCubit() : super(const AppModeState());
void toConnect() => emit(state.copyWith(mode: AppMode.connect));
void toUpload() => emit(state.copyWith(mode: AppMode.upload));
void missionUploadConfirmed() =>
emit(state.copyWith(missionUploaded: true));
void missionVerifiedConfirmed() =>
emit(state.copyWith(missionVerified: true));
void droneArmedChanged(bool armed) =>
emit(state.copyWith(droneArmed: armed));
/// Wirft, wenn das Ready-to-Fly-Gate nicht erfuellt ist (Doku 4.5).
void toFly() {
if (!state.readyToFly) {
throw StateError('Ready-to-Fly-Gate nicht erfuellt.');
}
emit(state.copyWith(mode: AppMode.fly));
}
/// Verlassen des Fly-Modus setzt den kompletten Handover-Status zurueck.
void toPlan() => emit(const AppModeState());
}