Skip to content

feat(app): let the caller supply theme and feature config sources#1446

Open
SERDUN wants to merge 3 commits into
developfrom
feat/host-config-streams
Open

feat(app): let the caller supply theme and feature config sources#1446
SERDUN wants to merge 3 commits into
developfrom
feat/host-config-streams

Conversation

@SERDUN

@SERDUN SERDUN commented Jun 24, 2026

Copy link
Copy Markdown
Member

Overview

Makes RootApp agnostic about where its theme and feature config come from. It takes a ConfigSource (an {initial, updates} record) for each and wires it into the inherited StreamProvider — without reaching into the registry or branching on a host flag. The composition root decides the source.

This is the phone-side half of the embedding work (the configurator side comes next). It builds on the inherited-config groundwork already on develop, so the host only supplies a different source; consumers (App.build, ThemeModeScreen) stay agnostic.

Changes

typedef ConfigSource<T> = ({T initial, Stream<T> updates});

const RootApp({required this.instanceRegistry, required this.featureAccess, required this.themeSettings});
final ConfigSource<FeatureAccess> featureAccess;
final ConfigSource<ThemeSettings> themeSettings;
  • RootApp.build wires each ConfigSource straight into a StreamProvider (initialData: source.initial, create: source.updates) — no registry access, no host ?? default branch.
  • Standalone (main) resolves the sources from the bootstrap registry: the FeatureAccessStreamFactory stream, and the first AppThemes theme (static, so updates: const Stream.empty()).
  • A host (the configurator's realtime preview) passes its own streams + bootstrap(firebase: const FirebaseIntegrationDisabled()) — live edits flow through the same inherited values.

It's a record, not a wrapper class; no imperative relay.

Verification

  • flutter analyze — clean.
  • Standalone behaviour is unchanged (registry-resolved sources; theme updates is empty).

Make RootApp agnostic about where its theme and feature config come from: it
takes a ConfigSource (an {initial, updates} record) for each and wires it into
the inherited StreamProvider, without reaching into the registry or branching on
a host flag.

The composition root decides the source:
- standalone (main) resolves it from the bootstrap registry - the
  FeatureAccessStreamFactory stream and the first AppThemes theme (static, so an
  empty updates stream);
- a host that embeds this app in-process (the theme configurator's realtime
  preview) passes its own streams, so the preview reflects live edits through the
  same inherited ThemeSettings / FeatureAccess the app already consumes.

No wrapper class and no imperative relay; standalone behaviour is unchanged.
@SERDUN SERDUN force-pushed the feat/host-config-streams branch from 475dfd5 to ba5f6cb Compare June 24, 2026 14:51
@SERDUN SERDUN changed the title feat(app): let a host drive theme and feature config via streams feat(app): let the caller supply theme and feature config sources Jun 24, 2026
SERDUN added 2 commits June 24, 2026 18:05
The host (the configurator's realtime preview) needs to drive the displayed
light/dark mode, but FeatureAccess.supportedConfig.themeMode is not practically
settable from outside (FeatureAccess/SupportedConfig are plain Equatable value
objects with no copyWith), and the embedded AppBloc is unreachable.

Add an optional ConfigSource<ThemeMode> to RootApp, provided as an inherited
ThemeMode? (null in a standalone run). App.build uses it directly when present:
finalThemeMode = hostThemeMode ?? <FeatureAccess/AppState mode>. It is read-only
- nothing is persisted and AppBloc is untouched - so an ephemeral preview never
affects the real saved preference. Standalone behaviour is unchanged.
The theme refactor removed AppState.themeSettings / effectiveThemeMode, but the
screenshots package (used by the configurator's static/semi-dynamic preview) still
read them, breaking its build. Provide ThemeSettings as an inherited value here
too: bootstrap and the configurator's preview builder supply a Provider<ThemeSettings>,
ScreenshotApp reads context.watch<ThemeSettings>(), and the effective mode is
derived via the ThemeSettings extension from the settings plus AppState.themeMode.
MockAppBloc.allScreen no longer takes themeSettings.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant