[go: up one dir, main page]

avy_debug_panel 1.1.1 copy "avy_debug_panel: ^1.1.1" to clipboard
avy_debug_panel: ^1.1.1 copied to clipboard

A powerful in-app developer debug console for Flutter apps. Features gesture triggers, logs viewer, network inspector, device info, storage viewer, and feature toggles.

avy_debug_panel #

pub package License: MIT Flutter Dart

A powerful, customizable in-app developer debug console for Flutter apps. Features gesture triggers, logs viewer, network inspector, device info, storage viewer, feature toggles, and theme customization.

Features #

  • ๐Ÿ”ง Debug Overlay - Full-screen modal panel that appears above your app UI
  • ๐Ÿ‘† Gesture Triggers - Long press, three-finger tap, or device shake to open
  • ๐Ÿ“‹ Logs Viewer - Timestamped, searchable logs with level filtering and tags
  • ๐ŸŒ Network Inspector - Dio interceptor for HTTP request/response logging
  • ๐Ÿ”„ Environment Switcher - Switch between dev, staging, and production environments at runtime
  • ๐Ÿ” State Inspector - Monitor Provider, Riverpod, BLoC, and GetX state changes
  • ๐Ÿ“ฑ Device Info Panel - Display device model, OS version, app version, build number
  • ๐Ÿ’พ Storage Viewer - View all SharedPreferences keys and values
  • ๐ŸŽš๏ธ Feature Toggles - Runtime feature flag management with categories
  • ๐ŸŽจ Theme Customization - Multiple built-in themes or create your own
  • ๐Ÿ“‹ Copy/Export - Copy logs and data to clipboard or export as JSON
  • ๐ŸŒ™ Dark/Light Themes - Clean developer-style UI with multiple color schemes
  • ๐Ÿ“‘ Tabbed Interface - Organized tabs for Logs, Network, Env, State, Device, Storage, Features
  • ๐Ÿงช Fully Tested - Comprehensive unit and widget tests

Screenshots #

Logs Panel Network Panel Device Info
Logs Network Device

Installation #

Add this to your package's pubspec.yaml file:

dependencies:
  avy_debug_panel: ^1.0.0

Or install via command line:

flutter pub add avy_debug_panel

Quick Start #

1. Initialize and Wrap Your App #

import 'package:avy_debug_panel/flutter_debug_panel.dart';

void main() {
  // Initialize the debug panel
  FlutterDebugPanel.init(
    enable: true,
    enableShake: true,
    enableLongPress: true,
    enableThreeFingerTap: true,
  );

  runApp(
    FlutterDebugPanel.wrap(
      MyApp(),
    ),
  );
}

2. Log Messages #

import 'package:avy_debug_panel/flutter_debug_panel.dart';

// Basic logging
DebugLogger.log("User logged in");

// With log level
DebugLogger.log("API error", level: LogLevel.error);

// With tag
DebugLogger.log("Network request", tag: "Network");

// Convenience methods
DebugLogger.debug("Debug message");
DebugLogger.info("Info message");
DebugLogger.warning("Warning message");
DebugLogger.error("Error message");

3. Network Inspector (Dio) #

import 'package:dio/dio.dart';
import 'package:avy_debug_panel/flutter_debug_panel.dart';

final dio = Dio();
dio.interceptors.add(DebugNetworkInterceptor());

// All requests will now be logged
final response = await dio.get('https://api.example.com/data');

4. Environment Switcher #

import 'package:avy_debug_panel/flutter_debug_panel.dart';

// Register environments
DebugEnvironmentManager.registerAll([
  Environment(
    id: 'dev',
    name: 'Development',
    baseUrl: 'https://dev-api.example.com',
    socketUrl: 'wss://dev-ws.example.com',
    description: 'Development environment',
    config: {'timeout': 30000, 'debug': true},
  ),
  Environment(
    id: 'staging',
    name: 'Staging',
    baseUrl: 'https://staging-api.example.com',
    description: 'Staging environment',
  ),
  Environment(
    id: 'prod',
    name: 'Production',
    baseUrl: 'https://api.example.com',
    description: 'Production environment',
  ),
]);

// Get current environment
final currentEnv = DebugEnvironmentManager.currentEnvironment;
final baseUrl = DebugEnvironmentManager.currentBaseUrl;

// Switch environment
DebugEnvironmentManager.setEnvironment('staging');

// Check environment type
if (DebugEnvironmentManager.isProduction) {
  // Production-specific logic
}

// Listen to environment changes
DebugEnvironmentManager.addListener((environment) {
  print('Switched to: ${environment?.name}');
  // Update your API client with new baseUrl
});

5. State Inspector #

import 'package:avy_debug_panel/flutter_debug_panel.dart';

// Register state providers for monitoring
DebugStateInspector.registerProvider(
  id: 'user_provider',
  name: 'User Provider',
  stateType: StateManagementType.provider,
  initialValue: 'null',
);

DebugStateInspector.registerProvider(
  id: 'cart_provider',
  name: 'Cart Provider',
  stateType: StateManagementType.riverpod,
  initialValue: 'Cart(items: 0)',
);

// Log state changes
DebugStateInspector.logChange(
  providerId: 'user_provider',
  previousValue: 'null',
  newValue: 'User(id: 123, name: "John")',
  description: 'User logged in',
);

// Get change history
final changes = DebugStateInspector.changes;
final userChanges = DebugStateInspector.getChangesForProvider('user_provider');

// Export for debugging
final json = DebugStateInspector.exportJson();

Flutter Riverpod Integration

For flutter_riverpod, you can monitor state changes using the RiverpodInspector helper or by listening to provider changes:

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:avy_debug_panel/flutter_debug_panel.dart';

// Define your providers
final counterProvider = StateProvider<int>((ref) => 0);

final userProvider = StateNotifierProvider<UserNotifier, User?>((ref) {
  return UserNotifier();
});

class UserNotifier extends StateNotifier<User?> {
  UserNotifier() : super(null);

  void login(User user) => state = user;
  void logout() => state = null;
}

class User {
  final int id;
  final String name;
  User({required this.id, required this.name});
  
  @override
  String toString() => 'User(id: $id, name: "$name")';
}

// Initialize and register providers for inspection
void initStateInspector() {
  // Register Riverpod providers for monitoring
  RiverpodInspector.register<int>(
    providerName: 'counterProvider',
    value: 0,
  );
  
  RiverpodInspector.register<User?>(
    providerName: 'userProvider',
    value: null,
  );
}

// Widget that monitors provider changes
class MonitoredConsumer extends ConsumerWidget {
  const MonitoredConsumer({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // Listen to counter changes and log to inspector
    ref.listen<int>(counterProvider, (previous, next) {
      RiverpodInspector.logChange<int>(
        providerName: 'counterProvider',
        newValue: next,
        previousValue: previous,
      );
    });

    // Listen to user changes
    ref.listen<User?>(userProvider, (previous, next) {
      RiverpodInspector.logChange<User?>(
        providerName: 'userProvider',
        newValue: next,
        previousValue: previous,
        description: next != null ? 'User logged in' : 'User logged out',
      );
    });

    final counter = ref.watch(counterProvider);
    final user = ref.watch(userProvider);

    return Column(
      children: [
        Text('Counter: $counter'),
        Text('User: ${user?.name ?? "Not logged in"}'),
        ElevatedButton(
          onPressed: () => ref.read(counterProvider.notifier).state++,
          child: const Text('Increment'),
        ),
        ElevatedButton(
          onPressed: () => ref.read(userProvider.notifier).login(
            User(id: 1, name: 'John Doe'),
          ),
          child: const Text('Login'),
        ),
      ],
    );
  }
}

// Alternative: Create a reusable inspection wrapper
class InspectableProviderListener<T> extends ConsumerWidget {
  final ProviderListenable<T> provider;
  final String providerName;
  final Widget Function(T value) builder;
  final String Function(T value)? valueToString;

  const InspectableProviderListener({
    super.key,
    required this.provider,
    required this.providerName,
    required this.builder,
    this.valueToString,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    ref.listen<T>(provider, (previous, next) {
      DebugStateInspector.logChange(
        providerId: providerName,
        newValue: valueToString?.call(next) ?? next.toString(),
        previousValue: previous != null 
            ? (valueToString?.call(previous) ?? previous.toString()) 
            : null,
      );
    });

    return builder(ref.watch(provider));
  }
}

// Usage of the wrapper
class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return InspectableProviderListener<int>(
      provider: counterProvider,
      providerName: 'counterProvider',
      builder: (value) => Text('Count: $value'),
    );
  }
}

Complete Riverpod Example with ProviderScope

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:avy_debug_panel/flutter_debug_panel.dart';

void main() {
  // Initialize debug panel
  FlutterDebugPanel.init(enable: true);
  
  // Register providers for state inspection
  RiverpodInspector.register(providerName: 'counter', value: 0);
  RiverpodInspector.register(providerName: 'theme', value: 'light');
  
  runApp(
    FlutterDebugPanel.wrap(
      ProviderScope(
        child: MyApp(),
      ),
    ),
  );
}

// Providers
final counterProvider = StateProvider<int>((ref) => 0);
final themeModeProvider = StateProvider<String>((ref) => 'light');

// App
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: HomeScreen());
  }
}

class HomeScreen extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // Monitor state changes
    ref.listen<int>(counterProvider, (prev, next) {
      RiverpodInspector.logChange(
        providerName: 'counter',
        newValue: next,
        previousValue: prev,
      );
    });
    
    ref.listen<String>(themeModeProvider, (prev, next) {
      RiverpodInspector.logChange(
        providerName: 'theme',
        newValue: next,
        previousValue: prev,
      );
    });
    
    final count = ref.watch(counterProvider);
    
    return Scaffold(
      body: Center(
        child: Text('Count: $count'),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => ref.read(counterProvider.notifier).state++,
        child: Icon(Icons.add),
      ),
    );
  }
}

6. Feature Flags #

import 'package:avy_debug_panel/flutter_debug_panel.dart';

// Register feature flags
DebugFeatureFlags.register(
  'new_checkout',
  'New Checkout Flow',
  description: 'Enable the redesigned checkout experience',
  category: 'Commerce',
  defaultValue: false,
);

// Check if enabled
if (DebugFeatureFlags.isEnabled('new_checkout')) {
  // Show new checkout
}

// Toggle at runtime
DebugFeatureFlags.enable('new_checkout');
DebugFeatureFlags.disable('new_checkout');

Configuration #

Basic Configuration #

FlutterDebugPanel.init(
  // Enable/disable the entire panel
  enable: true,
  
  // Enable individual gesture triggers
  enableShake: true,
  enableLongPress: true,
  enableThreeFingerTap: true,
  
  // Long press duration before panel opens
  longPressDuration: Duration(seconds: 2),
  
  // Custom colors
  backgroundColor: Color(0xFF1E1E1E),
  accentColor: Colors.cyanAccent,
);

Advanced Configuration with Theme #

FlutterDebugPanel.initWithConfig(
  DebugPanelConfig(
    enable: true,
    enableShake: true,
    enableLongPress: true,
    enableThreeFingerTap: true,
    // Use predefined color scheme
    colorScheme: DebugPanelColorScheme.darkPurple,
    // Or provide a completely custom theme
    theme: DebugPanelTheme(
      backgroundColor: Color(0xFF121212),
      surfaceColor: Color(0xFF1E1E1E),
      accentColor: Colors.purple,
      textPrimary: Colors.white,
      textSecondary: Colors.grey,
      successColor: Colors.green,
      warningColor: Colors.orange,
      errorColor: Colors.red,
      infoColor: Colors.blue,
      borderColor: Color(0xFF333333),
    ),
  ),
);

Theming #

Built-in Color Schemes #

// Dark theme with cyan accent (default)
DebugPanelColorScheme.darkCyan

// Dark theme with purple accent
DebugPanelColorScheme.darkPurple

// Dark theme with green accent
DebugPanelColorScheme.darkGreen

// Dark theme with orange accent
DebugPanelColorScheme.darkOrange

// Light theme with blue accent
DebugPanelColorScheme.lightBlue

Custom Theme #

Create your own theme by extending DebugPanelTheme:

const myTheme = DebugPanelTheme(
  backgroundColor: Color(0xFF1A1A2E),
  surfaceColor: Color(0xFF16213E),
  accentColor: Color(0xFFE94560),
  textPrimary: Colors.white,
  textSecondary: Color(0xFFA0A0A0),
  successColor: Color(0xFF4CAF50),
  warningColor: Color(0xFFFF9800),
  errorColor: Color(0xFFF44336),
  infoColor: Color(0xFF2196F3),
  borderColor: Color(0xFF2A2A4A),
  borderRadius: 12.0,
  defaultPadding: 16.0,
  monoFontFamily: 'monospace',
);

Panels Overview #

Logs Panel #

  • Displays timestamped log messages
  • Filter by log level (debug, info, warning, error)
  • Search functionality
  • Copy logs to clipboard
  • Tap to view details
  • Auto-scroll to latest logs
  • Export as JSON

Network Panel #

  • HTTP request/response logging
  • View request URL, headers, body
  • View response status code, headers, body
  • Response time tracking
  • Filter by status (success/failed)
  • Search by URL
  • Color-coded HTTP methods (GET, POST, PUT, DELETE, etc.)
  • Formatted JSON body display

Device Panel #

  • App information (name, version, build number)
  • Device information (model, manufacturer, OS)
  • System information (platform, Dart version)
  • Copy any value to clipboard
  • Platform-specific details (Android, iOS, Web, etc.)

Storage Panel #

  • View all SharedPreferences keys/values
  • Search functionality
  • Delete individual keys
  • Clear all storage
  • Copy values to clipboard
  • Type indicators (String, Int, Double, Bool, List)

Features Panel #

  • View all registered feature flags
  • Toggle flags on/off
  • Enable/disable all flags
  • Reset to defaults
  • Grouped by category
  • Search functionality

API Reference #

FlutterDebugPanel #

Method Description
init(...) Initialize with named parameters
initWithConfig(config) Initialize with config object
wrap(app) Wrap your app widget
log(message, level, tag) Log a message
clearLogs() Clear all logs
clearNetworkLogs() Clear all network logs
enableFeature(key) Enable a feature flag
disableFeature(key) Disable a feature flag
isFeatureEnabled(key) Check if flag is enabled
config Get current configuration
isEnabled Check if panel is enabled

DebugLogger #

Method Description
log(message, level, tag) Log with level and optional tag
debug(message, tag) Log debug message
info(message, tag) Log info message
warning(message, tag) Log warning message
error(message, tag) Log error message
clear() Clear all logs
export() Export logs as string
exportJson() Export logs as JSON
search(query) Search logs
getLogsByLevel(level) Get logs by level
getLogsByTag(tag) Get logs by tag
addListener(listener) Add log listener
removeListener(listener) Remove log listener

DebugNetworkLogger #

Method Description
logRequest(request) Log a network request
updateRequest(request) Update an existing request
clear() Clear all requests
search(query) Search by URL
getByStatus(success) Filter by status
addListener(listener) Add request listener
removeListener(listener) Remove request listener

DebugFeatureFlags #

Method Description
register(key, name, ...) Register a new flag
registerAll(flags) Register multiple flags
enable(key) Enable a flag
disable(key) Disable a flag
toggle(key) Toggle a flag
set(key, value) Set flag to specific value
isEnabled(key) Check if enabled
getFlag(key) Get flag by key
exists(key) Check if flag exists
unregister(key) Remove a flag
clear() Remove all flags
enableAll() Enable all flags
disableAll() Disable all flags
resetAll() Reset all to defaults
export() Export flags as map
import(values) Import flags from map
allFlags Get all flags
flagsByCategory Get flags grouped by category
categories Get all categories
addListener(listener) Add flag change listener
removeListener(listener) Remove listener

LogEntry #

Property Description
timestamp When the log was created
message The log message
level Log level (debug, info, warning, error)
tag Optional category tag
formattedTimestamp Formatted time string
toMap() Convert to map
toJson() Convert to JSON

DebugNetworkRequest #

Property Description
id Unique identifier
url Request URL
method HTTP method
headers Request headers
body Request body
statusCode Response status code
responseBody Response body
durationMs Response time in ms
isSuccess Whether request succeeded
isError Whether request failed
shortUrl URL path without domain
queryParams Query parameters

Best Practices #

Only Enable in Debug Mode #

FlutterDebugPanel.init(
  enable: kDebugMode,  // Only in debug builds
  enableShake: kDebugMode,
  enableLongPress: kDebugMode,
);

Use Tags for Categorization #

DebugLogger.log("User action", tag: "Analytics");
DebugLogger.log("API response", tag: "Network");
DebugLogger.log("Database query", tag: "Database");

Use Log Levels Appropriately #

DebugLogger.debug("Verbose debug info");  // Detailed debugging
DebugLogger.info("User logged in");       // Important events
DebugLogger.warning("Slow network");       // Potential issues
DebugLogger.error("API failed");           // Errors

Organize Feature Flags with Categories #

DebugFeatureFlags.register('dark_mode', 'Dark Mode', category: 'UI');
DebugFeatureFlags.register('analytics', 'Analytics', category: 'Tracking');
DebugFeatureFlags.register('new_api', 'New API', category: 'Backend');

Architecture #

The package follows a clean architecture with:

  • Core Services: DebugLogger, DebugNetworkLogger, DebugFeatureFlags
  • Configuration: DebugPanelConfig, DebugPanelTheme
  • UI Layer: Panels, overlay, and common widgets
  • Theme System: Customizable theming with color schemes
lib/
โ”œโ”€โ”€ flutter_debug_panel.dart  # Main entry point
โ”œโ”€โ”€ logger.dart               # Logger implementation
โ”œโ”€โ”€ network_logger.dart       # Network logger + Dio interceptor
โ”œโ”€โ”€ feature_flags.dart        # Feature flags manager
โ”œโ”€โ”€ debug_overlay.dart        # Overlay widget
โ”œโ”€โ”€ debug_panel.dart          # Main panel widget
โ”œโ”€โ”€ panels/
โ”‚   โ”œโ”€โ”€ logs_panel.dart
โ”‚   โ”œโ”€โ”€ network_panel.dart
โ”‚   โ”œโ”€โ”€ device_panel.dart
โ”‚   โ”œโ”€โ”€ storage_panel.dart
โ”‚   โ””โ”€โ”€ feature_flags_panel.dart
โ””โ”€โ”€ src/
    โ”œโ”€โ”€ theme/
    โ”‚   โ””โ”€โ”€ debug_panel_theme.dart
    โ”œโ”€โ”€ widgets/
    โ”‚   โ””โ”€โ”€ common_widgets.dart
    โ””โ”€โ”€ services/
        โ””โ”€โ”€ logger_service.dart

Testing #

The package includes comprehensive tests. Run them with:

flutter test

Test coverage includes:

  • Unit tests for all core services
  • Widget tests for panels and UI components
  • Integration tests for the debug panel workflow

Dependencies #

  • dio - HTTP client for network interceptor
  • device_info_plus - Device information
  • shared_preferences - Storage viewer
  • shake - Shake gesture detection
  • intl - Date formatting

Platform Support #

Platform Support
Android โœ…
iOS โœ…
Web โœ…
macOS โœ…
Windows โœ…
Linux โœ…

Changelog #

See CHANGELOG.md for a list of changes.

License #

MIT License - see LICENSE file.

Contributing #

Contributions are welcome! Please read the contributing guidelines before submitting a PR.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Development Setup #

# Clone the repo
git clone https://github.com/Avinashrola/avy_debug_panel.git

# Install dependencies
flutter pub get

# Run tests
flutter test

# Run the example app
cd example && flutter run

Issues #

Please file issues on the GitHub issue tracker.

Author #

Created by Avinash Rola

If you find this package useful, consider sponsoring its development.

2
likes
130
points
370
downloads

Documentation

Documentation
API reference

Publisher

unverified uploader

Weekly Downloads

A powerful in-app developer debug console for Flutter apps. Features gesture triggers, logs viewer, network inspector, device info, storage viewer, and feature toggles.

Repository (GitHub)
View/report issues

Topics

#debug #development #logging #network #inspector

Funding

Consider supporting this project:

github.com

License

MIT (license)

Dependencies

device_info_plus, dio, flutter, intl, shake, shared_preferences

More

Packages that depend on avy_debug_panel