cf_waiting_room 0.2.0
cf_waiting_room: ^0.2.0 copied to clipboard
Unofficial Flutter widget for integrating with Cloudflare Waiting Room — WebView-based queue gate with native overlay, session timeout, force re-queue flow, and custom UI builders.
cf_waiting_room #
Disclaimer: This package is an unofficial community library and is not affiliated with, endorsed by, or supported by Cloudflare, Inc. Cloudflare® is a registered trademark of Cloudflare, Inc.
An unofficial Flutter widget that gates your app behind a Cloudflare Waiting Room, with a two-phase WebView/native-overlay approach and full UI customisation.
Features #
- Two-phase display — shows the live CF queue page immediately (Phase 1), then switches to a native overlay while keeping the WebView alive at 1×1 px so CF's auto-refresh JS keeps the session cookie valid (Phase 2).
- Dynamic keyword detection — queue/pass keywords and CSS selectors are driven by
WaitingRoomConfig, ready for Firebase Remote Config. - Session timeout callback — fires
onSessionTimeoutafter a configurable number of minutes. - Force re-queue —
forceReQueue()shows a non-dismissible page, clears CF cookies, then calls your callback. - Custom UI builders — supply
waitingOverlayBuilderandreQueuePageBuilderto render your own brand UI. - 訪特權 mode — set
clearCookieOnStart: falseto skip cookie clearing (skip-queue pass). - Dev mock —
isMock: trueloads a bundled HTML page with a "simulate done" button.
Installation #
dependencies:
cf_waiting_room: ^0.1.0
For local development inside a monorepo:
dependencies:
cf_waiting_room:
path: packages/cf_waiting_room
Basic usage #
Wrap the widget in a Stack — it returns Positioned children internally.
Stack(
children: [
CFWaitingRoomOverlayWidget(
config: WaitingRoomConfig(
isEnable: true,
queueUrl: 'https://your-site.com/',
queueKeyWord: ['waiting', 'queue'],
passKeyWord: ['myapp'],
sessionTimeoutMinutes: 25,
),
onQueueDone: () => setState(() => _queueDone = true),
onSessionTimeout: () => _showTimeoutDialog(),
),
],
)
Locale #
The widget sends an Accept-Language header with every queue page request so
Cloudflare can serve the waiting room in the user's language.
Locale resolution order:
CFWaitingRoomOverlayWidget.locale— widget-level override (Localeobject).WaitingRoomConfig.locale— Remote Config string, e.g."zh-TW".- Device system locale (
PlatformDispatcher.instance.locale).
// Override to a specific locale
CFWaitingRoomOverlayWidget(
config: config,
locale: const Locale('zh', 'TW'), // → Accept-Language: zh-TW
onQueueDone: _onDone,
)
// Or via Remote Config JSON:
// { "locale": "en-US", ... }
Custom UI #
Waiting overlay (Phase 2) #
CFWaitingRoomOverlayWidget(
config: config,
onQueueDone: _onDone,
waitingOverlayBuilder: (context, info) {
return MyWaitingScreen(
title: info.title ?? 'You are in the queue',
eta: info.eta,
lastUpdated: info.lastUpdated,
);
},
)
Force re-queue page #
CFWaitingRoomOverlayWidget(
config: config,
onQueueDone: _onDone,
reQueuePageBuilder: (context, onConfirm) {
return MyReQueuePage(onConfirm: onConfirm);
},
)
Trigger force re-queue (e.g. after a successful purchase) #
await CFWaitingRoomOverlayWidget.forceReQueue(
context,
config: waitingRoomConfig,
onConfirm: () => _resetToQueuePhase(),
);
Firebase Remote Config integration #
Store WaitingRoomConfig as a JSON string in Firebase Remote Config under the key waitingRoomConfig:
{
"isEnable": true,
"queueUrl": "https://your-site.com/",
"queueKeyWord": ["waiting", "queue"],
"passKeyWord": ["myapp"],
"etaId": "waitTime",
"lastUpdatedId": "last-updated",
"sessionTimeoutMinutes": 25,
"clearCookieOnStart": true,
"reQueueDialogMessage": "You have successfully purchased. Please re-queue for another attempt.",
"reQueueDialogBtnText": "Re-join queue",
"locale": "zh-TW"
}
Then parse it in your config layer:
final raw = remoteConfig.getString('waitingRoomConfig');
final config = raw.isNotEmpty
? WaitingRoomConfig.fromJson(jsonDecode(raw))
: WaitingRoomConfig(isEnable: false);
Platform support #
| Platform | Support |
|---|---|
| Android | ✅ |
| iOS | ✅ |
| Web | ❌ (webview_flutter not supported on Web) |