flutter_adaptive_cards_host_fs 0.10.0
flutter_adaptive_cards_host_fs: ^0.10.0 copied to clipboard
Backend invoke bridge for Flutter Adaptive Cards — request serialization, response parsing, and handler wiring.
flutter_adaptive_cards_host_fs #
Backend invoke bridge for pub.dev and on GitHub at flutter_adaptive_cards_fs — serialize host callbacks, POST to your flow-service, parse responses, and apply patches to the rendered card.
Published on pub.dev and on gitub at flutter_adaptive_cards_host_fs.
Usage #
Import the barrel:
import 'package:flutter_adaptive_cards_host_fs/flutter_adaptive_cards_host_fs.dart';
Full guide: docs/backend-host-integration.md
Package structure #
Wires core invoke callbacks to your flow-service. Parsing and overlay application delegate to flutter_adaptive_cards_fs (RawAdaptiveCardState.applyUpdates, document notifier).
flowchart TB
subgraph host_pkg["flutter_adaptive_cards_host_fs"]
BH["AdaptiveCardBackendHandlers\nwrap() · onSubmit · onExecute · onChange · onRefresh"]
REQ["models/\nAdaptiveCardInvokeRequest · Response · Effect · Kind"]
subgraph adapters["adapters/"]
PJ["PlainJsonInvokeAdapter + response parser"]
TM["TeamsInvokeAdapter"]
EU["element_update_json.dart"]
end
subgraph client["client/"]
BC["AdaptiveCardBackendClient"]
HTTP["HttpAdaptiveCardBackendClient"]
end
BH --> REQ
REQ --> PJ
REQ --> TM
PJ --> BC
TM --> BC
BC --> HTTP
REQ --> EU
end
subgraph core["flutter_adaptive_cards_fs"]
IH["InheritedAdaptiveCardHandlers"]
RS["RawAdaptiveCardState.applyTo / applyUpdates"]
DOC["Document overlays · onCardReplaced"]
end
UI["User Submit · Execute · Refresh · input change"] --> BH
BH -. replaces handlers .-> IH
BH -->|"POST serialized body"| HTTP
HTTP -->|"effects in order"| RS
RS --> DOC
Quick start #
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter_adaptive_cards_fs/flutter_adaptive_cards_fs.dart';
import 'package:flutter_adaptive_cards_host_fs/flutter_adaptive_cards_host_fs.dart';
final cardKey = GlobalKey<RawAdaptiveCardState>();
AdaptiveCardBackendHandlers(
client: HttpAdaptiveCardBackendClient(
endpoint: Uri.parse('https://api.example.com/adaptive-card/invoke'),
),
cardKey: cardKey,
onError: (error) => log('invoke failed', error: error),
).wrap(
RawAdaptiveCard.fromMap(
key: cardKey,
map: cardJson,
hostConfigs: HostConfigs(),
),
onCardReplaced: (map) => setState(() => cardJson = map),
);
Assign the same GlobalKey<RawAdaptiveCardState> to both AdaptiveCardBackendHandlers and RawAdaptiveCard.fromMap. InputChangeInvoke uses invoke.cardState directly; Submit, Execute, and Refresh resolve state from cardKey.
Wired callbacks #
| Handler | Invoked when |
|---|---|
onSubmit |
Action.Submit |
onExecute |
Action.Execute |
onRefresh |
Root card refresh (manual affordance or auto-expire) |
onChange |
Input value changes (includes Data.Query with associatedInputs) |
Pass onOpenUrl / onOpenUrlDialog on AdaptiveCardBackendHandlers when you need non–backend URL handling (defaults to no-op).
PlainJson request shape #
{
"kind": "execute",
"verb": "saveProfile",
"actionId": "act1",
"data": { "email": "user@example.com" }
}
Input changes include inputId, value, and optional dataQuery (Teams Data.Query shape with merged parameters when associatedInputs is "auto").
Refresh requests use kind: execute with the nested refresh action's verb and merged input data.
PlainJson response contract #
Patches + validation errors:
{
"type": "adaptiveCard.invokeResponse",
"effects": [
{
"type": "applyPatches",
"elements": [
{
"id": "city",
"choices": [{ "title": "Paris", "value": "paris" }]
}
]
},
{
"type": "setInputErrors",
"errors": { "email": "Invalid format" }
}
]
}
Full card replacement:
{
"type": "adaptiveCard.invokeResponse",
"card": { "type": "AdaptiveCard", "version": "1.5", "body": [] }
}
Effect apply order #
Effects run in JSON array order. Recommended server order:
applyPatches—RawAdaptiveCardState.applyUpdates(choices, visibility, text, …)setInputErrors— validation overlays on input idsreplaceCard— callsonCardReplacedwith full card JSON (required when this effect is present)
Error handling #
| Case | Behavior |
|---|---|
| Network failure | onError; card unchanged |
| Parse failure | AdaptiveCardInvokeResponseParseException → onError |
| Unknown effect type | Skipped (debug log in debug builds) |
replaceCard without onCardReplaced |
StateError from applyTo |
Always implement onError in production hosts.
Teams adapter #
Use TeamsInvokeAdapter.toMap / TeamsInvokeAdapter.responseFromMap for Bot Framework–shaped invoke activities:
AdaptiveCardBackendHandlers(
client: client,
cardKey: cardKey,
requestAdapter: TeamsInvokeAdapter.toMap,
responseParser: TeamsInvokeAdapter.responseFromMap,
...
)
Custom client #
Implement AdaptiveCardBackendClient for gRPC, WebSocket, or in-memory mocks:
class MyBackendClient implements AdaptiveCardBackendClient {
@override
Future<Map<String, dynamic>> post(Map<String, dynamic> body) async {
// ...
}
}