algo_widget
In-app bug reporting for Flutter apps. A user reports a problem from inside your app — text, screenshot, voice narration, screen recording, and a recorded interaction trace — and reports land in AlgoSoft OS as first-class issues.
Part of algo-widget-mobile. The wire contract is documented in PROTOCOL.md.
What makes a report worth having
The interaction trace — ~50 KB against a video's ~50 MB, and the part a fix is actually derived from. Every event names the element it touched through an identity ladder, so "I tap here and this breaks" becomes a string an agent can grep for in your repository:
Semantics(
identifier: 'submit_order', // ← the best rung
child: ElevatedButton(onPressed: submit, child: const Text('Save')),
)
If your widgets already carry Keys or Semantics(identifier:), you are most of
the way there.
Privacy
Not negotiable, and checked in CI rather than promised in prose:
- the trace records that a field was typed into, never what — there is no code path that reads a value;
- nothing is captured before Record is pressed. No always-on buffer, ever;
- requests carry no headers, no bodies and no query strings;
cancel()discards everything on-device.
Usage
final client = AlgoWidgetClient(
host: 'https://os.example.com',
portalKey: 'pk_…',
platform: AlgoPlatform.android,
appId: 'com.acme.orders',
app: const AppFacts(appVersion: '3.2.1', buildNumber: '451'),
attest: (challenge) => PlayIntegrity.token(nonce: challenge),
);
final recorder = TraceRecorder(
platform: AlgoPlatform.android,
framework: AlgoFramework.flutter,
maxSeconds: client.portal?.recordingMaxSeconds ?? 300,
)..start('/orders/42');
recorder.tap(el: const TraceElement(testid: 'orders_refresh'));
recorder.navigate('/orders/42/edit');
final trace = await client.stageTrace(recorder.stop());
await client.report(
description: 'Saving an order does nothing',
route: '/orders/42',
attachments: [if (trace != null) trace],
);
Register your app first in AlgoSoft OS — Settings → Algo Widget → Mobile apps — with its package name and, on Android, both signing certificate fingerprints. With Play App Signing a Play Store build presents a different certificate than the same build off your machine, and registering only one locks out half your users.
Attaching files
Works out of the box, and needs no permission — no manifest entry, no
runtime prompt. The picker goes through Android's system photo picker (13+) or
the Storage Access Framework below it, both of which grant access to the one
item the reporter chose. Asking for READ_MEDIA_IMAGES would request a
customer's users' entire gallery to read a file they had already handed over.
Android needs the wiring because an <input type="file"> in an Android WebView
opens nothing on its own: the platform asks the embedder through
onShowFileChooser, and an unanswered request is dropped silently — no error,
no dialog. AlgoWidgetPanel answers it. iOS is deliberately left alone, since
WKWebView presents its own picker.
The default covers images and video. To widen it — documents, or a picker your app already ships — pass your own:
AlgoWidgetPanel(
widget: algo,
readFile: (path) => File(path).readAsBytes(),
fileSelector: (params) async => myPicker(params.acceptTypes),
)
Return [] when the reporter cancels, and never throw: Android expects an
answer either way, and a dropped one wedges the file input for the rest of the
session.
Licence
Apache-2.0.
Libraries
- algo_widget
- Algo Widget for Flutter — in-app bug reporting with screen recording, voice narration, a recorded interaction trace, and automatic crash capture.