feat(flags): Feature-Flags aus Config-Datei; Gutschriften-Abschnitt abschaltbar

- Schalter stehen in assets/feature_flags.json (Key -> enabled +
  Beschreibung) statt als Konstanten im Code
- Enum Feature buendelt die stabilen Keys; FeatureFlags liest die Datei,
  ignoriert unbekannte Keys und nutzt fuer fehlende den Default aus dem Enum
- Laden beim App-Start im AppBloc, bereitgestellt per RepositoryProvider;
  FeatureGate blendet Bereiche bei inaktivem Feature komplett aus
- articles.credit_section = false: Abschnitt "Gutschriften" im
  Artikel-Step ist ausgeblendet
- Bisheriges Stepper-Flag migriert (articles.credit_amount_stepper); die
  fuenf ungenutzten statischen Flags mit veralteten Kommentaren entfernt
- Tests: Asset enthaelt alle Keys, Parsing, Defaults, FeatureGate

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Dennis Nemec
2026-09-25 15:07:40 +02:00
parent 6b934e4534
commit 200992262a
15 changed files with 307 additions and 87 deletions

View File

@ -1,9 +1,11 @@
import 'package:hl_lieferservice/data/network/backend_environment.dart';
import 'package:hl_lieferservice/feature/feature_flags/feature_flags.dart';
/// Lifecycle-States des App-Bootstraps.
///
/// `AppConfigLoaded` heißt: Server-Config ist gelesen, die aktive Umgebung
/// steht fest und das Networking dafür ist im Locator registriert.
/// steht fest, das Networking dafür ist im Locator registriert und die
/// Feature-Schalter sind geladen.
abstract class AppState {
const AppState();
}
@ -17,13 +19,20 @@ class AppConfigLoading extends AppState {
}
class AppConfigLoaded extends AppState {
const AppConfigLoaded({required this.catalog, required this.active});
const AppConfigLoaded({
required this.catalog,
required this.active,
required this.featureFlags,
});
/// Alle auswählbaren Umgebungen aus der Config-Datei.
final ServerCatalog catalog;
/// Die Umgebung, gegen die die App gerade spricht.
final BackendEnvironment active;
/// Feature-Schalter aus `assets/feature_flags.json`.
final FeatureFlags featureFlags;
}
class AppConfigLoadingFailed extends AppState {