flutter_bug_report 0.2.0 copy "flutter_bug_report: ^0.2.0" to clipboard
flutter_bug_report: ^0.2.0 copied to clipboard

Flutter bug reports with the log already attached. Captures logger output, debugPrint and crashes, redacts secrets, and builds a bounded txt/json/zip. No vendor, no SDK.

example/lib/main.dart

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_bug_report/flutter_bug_report.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Before runApp, so the log covers startup — which is where the errors nobody
  // can reproduce tend to live.
  await BugReport.init();

  runApp(const ExampleApp());
}

class ExampleApp extends StatelessWidget {
  const ExampleApp({super.key});

  @override
  Widget build(BuildContext context) => MaterialApp(
    title: 'flutter_bug_report',
    theme: ThemeData(colorSchemeSeed: Colors.indigo),
    home: const ReportPage(),
  );
}

class ReportPage extends StatefulWidget {
  const ReportPage({super.key});

  @override
  State<ReportPage> createState() => _ReportPageState();
}

class _ReportPageState extends State<ReportPage> {
  final _description = TextEditingController(
    text: 'The list was empty after I pressed refresh',
  );

  String? _preview;
  Bundle? _bundle;

  /// Stands in for a session: a few ordinary lines, a print nobody logged on
  /// purpose, a secret that should not survive, and something that throws.
  void _makeSomeNoise() {
    BugReport.info('opened the clients screen');
    BugReport.info(
      'GET /clients',
      extra: const {'status': 500, 'authorization': 'Bearer s3cr3t-token'},
    );
    BugReport.warning('retrying in 2s');

    debugPrint('a plugin printed this, and nobody asked it to');

    try {
      throw StateError('the list came back null');
    } on Object catch (error, stackTrace) {
      BugReport.error(
        'could not load clients',
        error: error,
        stackTrace: stackTrace,
      );
    }

    setState(() => _preview = null);
  }

  Future<void> _build() async {
    final bundle = await BugReport.build(
      description: _description.text,
      metadata: const {
        'app_version': '1.0.0+1',
        'platform': 'android',
        'device_model': 'Pixel 7',
      },
      // Text here only so the example can show it on screen. Ship zip.
      format: BundleFormat.text,
    );

    setState(() {
      _bundle = bundle;
      _preview = utf8.decode(bundle.bytes);
    });
  }

  @override
  void dispose() {
    _description.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final bundle = _bundle;

    return Scaffold(
      appBar: AppBar(title: const Text('flutter_bug_report')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            TextField(
              controller: _description,
              decoration: const InputDecoration(
                labelText: 'What went wrong',
                border: OutlineInputBorder(),
              ),
              maxLines: 2,
            ),
            const SizedBox(height: 12),
            Row(
              children: [
                Expanded(
                  child: OutlinedButton(
                    onPressed: _makeSomeNoise,
                    child: const Text('Make some noise'),
                  ),
                ),
                const SizedBox(width: 12),
                Expanded(
                  child: FilledButton(
                    onPressed: _build,
                    child: const Text('Build bundle'),
                  ),
                ),
              ],
            ),
            if (bundle != null) ...[
              const SizedBox(height: 12),
              Text(
                '${bundle.fileName} · ${bundle.sizeInBytes} bytes · '
                '${bundle.entryCount} entries'
                '${bundle.truncated ? ' · truncated' : ''}',
                style: Theme.of(context).textTheme.labelMedium,
              ),
            ],
            const SizedBox(height: 12),
            Expanded(
              child: Container(
                width: double.infinity,
                padding: const EdgeInsets.all(12),
                decoration: BoxDecoration(
                  color: Theme.of(context).colorScheme.surfaceContainerHighest,
                  borderRadius: BorderRadius.circular(8),
                ),
                child: SingleChildScrollView(
                  child: SelectableText(
                    _preview ?? 'Make some noise, then build the bundle.\n\n'
                        'Note what the bearer token looks like by the time it '
                        'reaches the file.',
                    style: const TextStyle(fontFamily: 'monospace', fontSize: 11),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
1
likes
160
points
25
downloads

Documentation

API reference

Publisher

verified publisherahadjonovss.uz

Weekly Downloads

Flutter bug reports with the log already attached. Captures logger output, debugPrint and crashes, redacts secrets, and builds a bounded txt/json/zip. No vendor, no SDK.

Repository (GitHub)
View/report issues

Topics

#bug-report #logging #crash-reporting #diagnostics #debugging

License

MIT (license)

Dependencies

archive, flutter, path_provider

More

Packages that depend on flutter_bug_report