FeatureDiscoveryService<E extends Object> class

Orchestrates feature-discovery tips. Parameterized on E — the consumer- defined event type (typically an enum) whose values are emitted from screens as emit(context, MyEvent.onFoo, ctx).

Usage (typically a single instance per app, held in a top-level final or exposed through your DI / provider framework):

enum AppEvent { onStartupTick, onProductViewed }

final discovery = FeatureDiscoveryService<AppEvent>()
  ..registerAll([
    DiscoveryTip<AppEvent>(
      id: 'welcome_banner',
      priority: DiscoveryPriority.standard,
      triggers: {AppEvent.onStartupTick},
      shouldShow: (ctx) async => ctx.appLaunches >= 2,
      presentation: BannerPresentation(/* ... */),
    ),
  ]);

Priorities:

  • critical — always evaluated, ignores session lock, can chain with other critical tips in a single emit (e.g. permissions, data disclosures).
  • standard / optional — respect the session lock; claim the lock and end the chain when they fire.
  • tip — respects the session lock AND is suppressed by a held lock.

Only one non-critical tip runs per session-lock window. The lock is cleared automatically when onAppResumed detects a background long enough (see backgroundResetThreshold), or manually via resetSession.

Constructors

FeatureDiscoveryService({Duration backgroundResetThreshold = const Duration(seconds: 10)})

Properties

backgroundResetThreshold Duration
How long the app must stay backgrounded before onAppResumed clears the session lock. Short foregrounds (quickly checking a notification, answering a call) should NOT re-open the tip queue.
final
hashCode int
The hash code for this object.
no setterinherited
runtimeType Type
A representation of the runtime type of the object.
no setterinherited

Methods

clear() → void
Drop every registered tip and reset internal state. Mainly for tests.
emit(BuildContext context, E event, DiscoveryContext ctx) Future<bool>
Emit an event. Evaluates every tip whose triggers contain event, in priority + order, and presents the first eligible one (or a chain of critical tips).
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
onAppPaused() → void
Record the moment the app went to background. Call from WidgetsBindingObserver.didChangeAppLifecycleState on AppLifecycleState.paused.
onAppResumed() → void
On foreground resume, clear the session lock if the app was backgrounded for at least backgroundResetThreshold. Short foregrounds preserve the lock so a tip the user just dismissed doesn't re-fire mid-interaction.
register(DiscoveryTip<E> tip) → void
Register a tip once at app start. Duplicate ids are ignored.
registerAll(Iterable<DiscoveryTip<E>> tips) → void
Register every tip in tips. Convenience for bulk registration.
resetSession() → void
Manually clear the session lock so the next eligible non-critical tip can fire. Use when a lifecycle event outside the app's pause/resume cycle should re-open the tip queue (e.g. the user completed onboarding).
toString() String
A string representation of this object.
inherited
wasPresentedInCurrentEmit(String tipId) bool
Whether tipId has already been presented during the current emit call. Useful inside a tip's shouldShow to avoid piling tips on top of one another within a single trigger.

Operators

operator ==(Object other) bool
The equality operator.
inherited