flutter_blackbox 0.4.0 copy "flutter_blackbox: ^0.4.0" to clipboard
flutter_blackbox: ^0.4.0 copied to clipboard

In-app debug & QA overlay for Flutter. Network inspector, mock engine, live logs, FPS monitor, feature flags, and automated QA reports. Dio & http adapters.

example/lib/main.dart

// This example uses adapters generated by:
//   dart run flutter_blackbox:init --generate
//
// The generated file (blackbox_adapters.dart) contains only the adapters
// your project actually needs — zero unnecessary packages installed.
import 'package:flutter_blackbox/flutter_blackbox.dart';
import 'blackbox_adapters.dart'; // generated by: dart run flutter_blackbox:init --generate
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

final dio = Dio(BaseOptions(baseUrl: 'https://api.example.com'));

void main() {
  BlackBox.setup(
    // ── Network — observe silently via Dio interceptors ──────────────
    httpAdapters: [DioBlackBoxAdapter(dio)],

    // ── Logging — auto-capture all debugPrint output ─────────────────
    logAdapter: PrintLogAdapter(),

    // ── Storage — inspect SharedPreferences (add more adapters here) ─
    storageAdapters: [SharedPrefsStorageAdapter()],

    // ── Privacy — sensitive keys auto-redacted (default: true) ───────
    redactSensitiveData: true,

    // ── Trigger — floating button for easy access ────────────────────
    trigger: const BlackBoxTrigger.floatingButton(),

    // ── Ignore specific high-frequency widgets from the Rebuild list ─
    ignoredRebuildWidgets: const ['MyNoisyWidget'],

    // ── Only active in debug mode ────────────────────────────────────
    enabled: kDebugMode,
  );

  // ── Mock an API endpoint ────────────────────────────────────────────
  BlackBox.mock(
    pattern: '/api/orders',
    method: 'GET',
    response:
        const MockResponse(statusCode: 200, body: {'orders': <dynamic>[]}),
  );

  runApp(const BlackBoxOverlay(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) => MaterialApp(
        title: 'BlackBox Example',
        theme: ThemeData.dark(useMaterial3: true),
        navigatorObservers: [BlackBox.journeyObserver],
        home: const HomeScreen(),
      );
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('BlackBox Example')),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          // ── Logging demos ─────────────────────────────────────────
          const _Section('Logging'),
          _Tile(
            'Log info',
            Icons.info_outline,
            () => BlackBox.log('User opened home',
                level: LogLevel.info, tag: 'Home'),
          ),
          _Tile(
            'Log error',
            Icons.error_outline,
            () => BlackBox.log('Payment failed',
                level: LogLevel.error,
                tag: 'Payment',
                data: {'orderId': '12345'}),
          ),
          _Tile(
            'debugPrint (auto-captured)',
            Icons.print,
            () => debugPrint('[Auth] token refreshed successfully'),
          ),

          // ── Network demos ─────────────────────────────────────────
          const SizedBox(height: 16),
          const _Section('Network'),
          _Tile(
            'GET /api/orders (mocked)',
            Icons.cloud_download,
            () async {
              try {
                await dio.get<dynamic>('/api/orders');
              } catch (_) {}
            },
          ),

          // ── Storage demos ─────────────────────────────────────────
          const SizedBox(height: 16),
          const _Section('Storage'),
          _Tile(
            'Write sample preferences',
            Icons.save,
            () async {
              final prefs = await SharedPreferences.getInstance();
              await prefs.setString('username', 'john_doe');
              await prefs.setBool('dark_mode', true);
              await prefs.setInt('login_count', 42);
              await prefs.setString('auth_token', 'eyJhbGciOiJIUzI1NiJ9...');
              await prefs.setString('user_password_hash', 'bcrypt\$2b\$12...');
              await prefs.setString('app_version', '2.1.0');
              debugPrint('Sample preferences written — check Storage tab');
            },
          ),

          // ── Rebuild tracking demos ────────────────────────────────
          const SizedBox(height: 16),
          const _Section('Rebuild Tracking'),
          const _Tile(
            'Start auto-tracking',
            Icons.visibility,
            BlackBox.startRebuildTracking,
          ),
          const _Tile(
            'Stop auto-tracking',
            Icons.visibility_off,
            BlackBox.stopRebuildTracking,
          ),

          // ── Manual rebuild tracker example ────────────────────────
          // This widget tracks its own rebuild count
          RebuildTracker(
            label: 'ExampleCard',
            child: _Tile(
              'I am tracked by RebuildTracker',
              Icons.refresh,
              () {
                // Force a rebuild to see the count increase
                (context as Element).markNeedsBuild();
              },
            ),
          ),

          // ── Overlay control ───────────────────────────────────────
          const SizedBox(height: 16),
          const _Section('Overlay'),
          const _Tile('Open BlackBox', Icons.bug_report, BlackBox.open),
        ],
      ),
    );
  }
}

// ─────────────────────────────────────────────────────────────────────────────
// UI Components
// ─────────────────────────────────────────────────────────────────────────────

class _Section extends StatelessWidget {
  const _Section(this.title);
  final String title;
  @override
  Widget build(BuildContext context) => Padding(
        padding: const EdgeInsets.only(bottom: 8),
        child: Text(
          title,
          style: TextStyle(
            fontSize: 13,
            fontWeight: FontWeight.w700,
            color: Colors.white.withValues(alpha: 0.4),
            letterSpacing: 1.2,
          ),
        ),
      );
}

class _Tile extends StatelessWidget {
  const _Tile(this.title, this.icon, this.onTap);
  final String title;
  final IconData icon;
  final VoidCallback onTap;
  @override
  Widget build(BuildContext context) => Card(
        margin: const EdgeInsets.only(bottom: 6),
        child: ListTile(
          leading: Icon(icon, size: 20),
          title: Text(title, style: const TextStyle(fontSize: 13)),
          trailing: const Icon(Icons.chevron_right, size: 16),
          onTap: onTap,
          dense: true,
        ),
      );
}
11
likes
160
points
573
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

In-app debug & QA overlay for Flutter. Network inspector, mock engine, live logs, FPS monitor, feature flags, and automated QA reports. Dio & http adapters.

Repository (GitHub)
View/report issues

Topics

#debug #developer-tools #overlay #network #logging

License

MIT (license)

Dependencies

connectivity_plus, device_info_plus, flutter, package_info_plus, yaml

More

Packages that depend on flutter_blackbox