Book a pickup, track it to delivery — the rebuilt customer app. - Design language from doormile-screens.html: brand #8F0F06, Manrope + Geist Mono (variable fonts), bordered cards instead of shadows, crimson brand headers, sliding tab indicator, mono for anything read digit by digit. - lib/data (one live API implementation, plus a debug-only offline fake), lib/state, lib/ui (tokens, widgets, screens). - 84 tests, plus a design snapshot harness that renders every screen with the real fonts: flutter test test/design_snapshot_test.dart --run-skipped --update-goldens This replaces the previous app (pubspec 'doormile', app id com.doormile.customer). That tree remains in history at 6c7d656; note its android/app/google-services.json is not carried over, and the application id here is in.doormile.customer. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
25 lines
950 B
Dart
25 lines
950 B
Dart
import 'package:flutter/widgets.dart';
|
|
|
|
import 'app_state.dart';
|
|
|
|
/// Makes [AppState] available to the widget tree and rebuilds dependents when
|
|
/// it changes. Deliberately dependency-free — no external state package.
|
|
class AppScope extends InheritedNotifier<AppState> {
|
|
const AppScope({super.key, required AppState state, required super.child})
|
|
: super(notifier: state);
|
|
|
|
/// Subscribes the calling widget to changes.
|
|
static AppState of(BuildContext context) {
|
|
final scope = context.dependOnInheritedWidgetOfExactType<AppScope>();
|
|
assert(scope != null, 'AppScope.of() called outside an AppScope');
|
|
return scope!.notifier!;
|
|
}
|
|
|
|
/// Reads without subscribing — for callbacks and one-shot lookups.
|
|
static AppState read(BuildContext context) {
|
|
final scope = context.getInheritedWidgetOfExactType<AppScope>();
|
|
assert(scope != null, 'AppScope.read() called outside an AppScope');
|
|
return scope!.notifier!;
|
|
}
|
|
}
|