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>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
62d655fe8e
commit
346fcc2183
@@ -0,0 +1,65 @@
|
||||
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());
|
||||
}
|
||||
Reference in New Issue
Block a user