dvModuleTheme function
Wraps child in whatever theme the module mounted as moduleId should
render in.
Applied by the generated router around a module's own pages. A module
nobody registered, or one that declared no theme of its own, renders in
the application's: a parent can ask for override and mount a module that
has nothing to override with, and dropping to Flutter's bare defaults
there would look like the application had broken.
Implementation
Widget dvModuleTheme(BuildContext context, String moduleId, Widget child) {
final DVModule? module = dvModuleRegistry.maybeGet(moduleId);
if (module == null) return child;
final DVModuleThemeMode mode = module.themeMode;
if (mode == DVModuleThemeMode.inherit) return child;
final ThemeData? own = module.declaredTheme;
if (own == null) return child;
final ThemeData parent = Theme.of(context);
final ThemeData resolved = switch (mode) {
// override and isolated coincide here, and it is worth being plain about
// that rather than writing two branches that do the same thing. Theme
// replaces what descendants see, so neither leaves a path back to the
// parent's values -- not even through the fields the module left at
// their defaults. Where the specification distinguishes them is what a
// module may *reach for*, and a theme is not reached for: it is found by
// looking up, and this stops the lookup either way.
DVModuleThemeMode.override || DVModuleThemeMode.isolated => own,
// What the module said, over what the application said. A ThemeData
// carries a value for every field whether or not its author set one, so
// "what the module did not say" is read from the fields that still hold
// the framework's default.
DVModuleThemeMode.extend => _extend(parent, own),
DVModuleThemeMode.inherit => parent,
};
return Theme(data: resolved, child: child);
}