handleAction method
Implementation
void handleAction(GuideAction action) {
final state = _orchestrator.state;
if (state == null) return;
// Guides only have Step Clicked in the matrix (no Experience Clicked), so
// the click is Digia analytics only — never forwarded to the CEP plugin.
_events().toDigia(
GuideStepClicked(
itemIndex: _currentItemIndex,
ctaLabel: action.label,
actionType: _actionTypeWire(action.type),
actionUrl: action.url,
),
state.payload,
);
// A CTA tap (anything but back/prev) on the last or only step is the guide's
// "Completed" — the single place completion is decided. Scrim taps, the close
// button, the back gesture, and an outside-tap advance never reach here, so
// they stay plain dismissals. Mirrors RN's handleActionPress rule.
if (_isOnLastActiveStep &&
!_completedFired &&
action.type != GuideActionType.back &&
action.type != GuideActionType.prev) {
_completedFired = true;
// Permanent stop when the policy opted into stopOn: experienceCompleted.
_frequency().recordCompleted(state.campaign);
_events().toDigia(
GuideCompleted(
itemTotal: state.config.stepCount,
timeToCompleteMs: _dwell.elapsedMs(state.payload.cepCampaignId),
),
state.payload,
);
}
switch (action.type) {
case GuideActionType.next:
_transition(forward: true);
break;
case GuideActionType.back:
case GuideActionType.prev:
_transition(forward: false);
break;
case GuideActionType.dismiss:
_view.dismiss();
break;
case GuideActionType.deepLink:
_runLink(OpenDeeplinkAction(action.url ?? ''), state);
break;
case GuideActionType.openUrl:
_runLink(OpenUrlAction(action.url ?? ''), state);
break;
case GuideActionType.fireEvent:
// Custom analytics event — not yet bridged to the Flutter event model.
break;
}
}