uxlens_sdk 0.1.6
uxlens_sdk: ^0.1.6 copied to clipboard
UxLens session replay & analytics SDK for Flutter apps.
uxlens_sdk #
Session replay & analytics SDK for Flutter apps — captures screen frames, touch/gesture events, and navigation, with sensitive-field masking applied client-side before anything is buffered. This is the Phase 1 build: capture and local buffering only, no backend yet (see the top-level repo README for the phase roadmap).
Integration #
void main() {
// Single init call, before runApp.
UxLens.start();
runApp(
UxLensRecorder(
child: MaterialApp(
navigatorObservers: [UxLens.instance!.navigatorObserver],
home: const HomePage(),
),
),
);
}
That's the entire integration surface. UxLensRecorder wraps your app in a
RepaintBoundary + root gesture listener; the navigator observer tracks
screen transitions.
What gets captured #
- Frames:
RepaintBoundaryscreenshots at a tunable rate (default 3fps), PNG-encoded, with sensitiveSemanticsregions painted black before encoding. - Touch events: tap/pan/scroll, normalized to a 0–1 coordinate space so heatmaps line up across device sizes.
- Navigation: route push/pop/replace/remove via
NavigatorObserver.
All of it is batched in memory (EventBuffer) and flushed to
<app documents>/uxlens_sessions/<sessionId>/ on a timer, when the buffer
fills, or when the app backgrounds — never streamed record-by-record.
Masking #
UxLensConfig.sensitiveLabelKeywords matches Semantics label/hint/value
text (password, card number, email, etc); autoMaskPasswordFields catches
obscured text fields regardless of label. Masking runs against the live
Semantics tree and paints the matched region's rect black on the captured
ui.Image before it's ever encoded or held as bytes — masked content never
exists in memory in unmasked form past the paint step.
Config #
const UxLensConfig({
double frameRate = 3.0,
Duration flushInterval = const Duration(seconds: 10),
int maxBufferedRecords = 500,
List<String> sensitiveLabelKeywords = const [...],
bool autoMaskPasswordFields = true,
});
Example app #
example/ is a 3-screen demo (login with a password field, a scrollable
home list, and a session inspector) — the inspector screen reads back
uxlens_sdk's own local dump so you can confirm capture/masking/buffering
without a backend. Run it with fvm flutter run from example/.
Testing note #
Widget tests that exercise UxLens.stop() (or anything that flushes to disk)
must wrap that call in tester.runAsync(...) — RenderRepaintBoundary.toImage()
and file I/O are real engine/OS async work that never resolves inside
testWidgets's fake-time zone otherwise. See example/test/widget_test.dart.