smart_dev_pinning_plugin 4.0.0 copy "smart_dev_pinning_plugin: ^4.0.0" to clipboard
smart_dev_pinning_plugin: ^4.0.0 copied to clipboard

This plugin creates a secure native TLS connection to execute HTTP requests with certificate pinning.

example/lib/main.dart

import 'dart:convert';
import 'dart:io';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:smart_dev_pinning_plugin/smart_dev_pinning_plugin.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  // --- Configuration State ---
  final TextEditingController _urlController = TextEditingController(
    text: 'https://jsonplaceholder.typicode.com/posts/1',
  );
  final TextEditingController _hashController = TextEditingController();
  PinningMethod _selectedMethod = PinningMethod.certificate;

  // Known valid hashes for jsonplaceholder.typicode.com (for demo purposes)
  final Map<PinningMethod, String> _demoHashes = {
    PinningMethod.certificate: "av2cD1Ongt8KXvUIHVMi09oimOn1RTkzIjmxtNDJP6g=",
    PinningMethod.publicKey:
        "k+swi1D7Mu27FDJ9DAfns27/YipZz5s7BezuYsaXM/s=", // Check actual value if it fails
    PinningMethod.intermediateCertificate:
        "HfwWBfutNY2LyET3bRUgP6ycpcGnn9SFf/ryhk++v5Y=",
    PinningMethod.intermediatePublicKey:
        "kIdp6NNEd8wsugYyyIYFsi1ylMCED3hZbSR8ZFsa/A4=",
  };

  // --- Execution State ---
  String _response = "";
  bool _isRequestRunning = false;
  bool _isSuccess = false;

  // --- Benchmark State ---
  String benchmarkResults = "";
  bool isBenchmarkRunning = false;
  double? avgStandard;
  double? avgSecure;
  int? minStandard;
  int? maxStandard;
  int? minSecure;
  int? maxSecure;
  double? stdDevStandard;
  double? stdDevSecure;
  double? performanceImpact;
  String? performanceVerdict;
  String? verdictEmoji;
  String? performanceAnalysis;

  @override
  void initState() {
    super.initState();
    _hashController.text = _demoHashes[_selectedMethod]!;
  }

  @override
  void dispose() {
    _urlController.dispose();
    _hashController.dispose();
    super.dispose();
  }

  void _onMethodChanged(PinningMethod? method) {
    if (method != null) {
      setState(() {
        _selectedMethod = method;
        // Auto-fill hash if it's the default URL
        if (_urlController.text.contains('jsonplaceholder.typicode.com')) {
          _hashController.text = _demoHashes[method] ?? "";
        }
      });
    }
  }

  String _getMethodDescription(PinningMethod method) {
    switch (method) {
      case PinningMethod.certificate:
        return 'Validates the complete Leaf certificate (DER hash). Most specific, requires hash update on renewal.';
      case PinningMethod.publicKey:
        return 'Validates only the Leaf public key (SPKI hash). More flexible, survives renewals if key is kept.';
      case PinningMethod.intermediateCertificate:
        return 'Validates the Intermediate CA certificate. Recommended for services behind CDN/WAF.';
      case PinningMethod.intermediatePublicKey:
        return 'Validates the Intermediate CA public key. Most stable option for CDN/WAF services.';
    }
  }

  /// Makes an HTTP request using Dart's native HTTP client
  Future<String> _makeStandardHttpRequest() async {
    final httpClient = HttpClient();
    try {
      final request = await httpClient.getUrl(Uri.parse(_urlController.text));
      request.headers.set('Content-type', 'application/json; charset=UTF-8');

      final response = await request.close();
      final responseBody = await response.transform(utf8.decoder).join();
      return responseBody;
    } finally {
      httpClient.close();
    }
  }

  /// Makes an HTTP request using the secure client with SSL Pinning
  Future<SmartResponse> _makeSecureHttpRequest() async {
    final client = SecureClient();
    return await client.httpRequest(
      certificateHashes: [_hashController.text.trim()],
      method: 'GET',
      url: _urlController.text.trim(),
      headers: {'Content-type': 'application/json; charset=UTF-8'},
      pinningMethod: _selectedMethod,
    );
  }

  Future<void> _testConnection() async {
    // Hide keyboard
    FocusScope.of(context).unfocus();

    setState(() {
      _isRequestRunning = true;
      _response = "Connecting...\nMethod: ${_selectedMethod.name}";
    });

    try {
      final result = await _makeSecureHttpRequest();

      setState(() {
        _isSuccess = result.success;
        if (result.success) {
          _response =
              "Code: ${result.statusCode}\n\nData:\n${_truncateData(result.data ?? 'No data', 300)}";
        } else {
          _response =
              "Error Type: ${result.errorType}\nDetails: ${result.error}";
        }
      });
    } catch (e) {
      setState(() {
        _isSuccess = false;
        _response = "Exception: $e";
      });
    } finally {
      setState(() {
        _isRequestRunning = false;
      });
    }
  }

  String _truncateData(String data, int maxLength) {
    if (data.length <= maxLength) return data;
    return '${data.substring(0, maxLength)}...\n\n[Truncated for demo]';
  }

  /// Executes benchmark comparing both clients
  Future<void> _runBenchmark() async {
    // Hide keyboard
    FocusScope.of(context).unfocus();

    setState(() {
      isBenchmarkRunning = true;
      benchmarkResults = "Running benchmark tests...";
      // Reset previous data
      avgStandard = null;
      avgSecure = null;
    });

    const int iterations = 10;
    final List<Duration> standardTimes = [];
    final List<Duration> secureTimes = [];

    try {
      // Benchmark standard client
      for (int i = 0; i < iterations; i++) {
        final stopwatch = Stopwatch()..start();
        await _makeStandardHttpRequest();
        stopwatch.stop();
        standardTimes.add(stopwatch.elapsed);

        setState(() {
          benchmarkResults =
              "Testing Standard HTTP Client: ${i + 1}/$iterations";
        });

        await Future.delayed(const Duration(milliseconds: 50));
      }

      // Benchmark secure client
      for (int i = 0; i < iterations; i++) {
        final stopwatch = Stopwatch()..start();
        try {
          await _makeSecureHttpRequest();
        } catch (e) {
          // Continue even with pinning errors
        }
        stopwatch.stop();
        secureTimes.add(stopwatch.elapsed);

        setState(() {
          benchmarkResults =
              "Testing Secure SSL Pinning Client: ${i + 1}/$iterations";
        });

        await Future.delayed(const Duration(milliseconds: 50));
      }

      // Calculate comprehensive statistics
      final avgStandardCalc =
          standardTimes.map((d) => d.inMilliseconds).reduce((a, b) => a + b) /
          iterations;
      final avgSecureCalc =
          secureTimes.map((d) => d.inMilliseconds).reduce((a, b) => a + b) /
          iterations;

      final minStandardCalc = standardTimes
          .map((d) => d.inMilliseconds)
          .reduce((a, b) => a < b ? a : b);
      final maxStandardCalc = standardTimes
          .map((d) => d.inMilliseconds)
          .reduce((a, b) => a > b ? a : b);

      final minSecureCalc = secureTimes
          .map((d) => d.inMilliseconds)
          .reduce((a, b) => a < b ? a : b);
      final maxSecureCalc = secureTimes
          .map((d) => d.inMilliseconds)
          .reduce((a, b) => a > b ? a : b);

      final stdDevStandardCalc = _calculateStandardDeviation(
        standardTimes,
        avgStandardCalc,
      );
      final stdDevSecureCalc = _calculateStandardDeviation(
        secureTimes,
        avgSecureCalc,
      );

      final performanceImpactCalc =
          ((avgSecureCalc - avgStandardCalc) / avgStandardCalc * 100);

      String performanceVerdictCalc;
      String verdictEmojiCalc;
      String performanceAnalysisCalc;

      if (performanceImpactCalc < -5) {
        performanceVerdictCalc = "Faster than standard!";
        verdictEmojiCalc = "🚀";
        performanceAnalysisCalc =
            "The secure client outperforms standard HTTP by ${(-performanceImpactCalc).toStringAsFixed(1)}%. Due to Rust's optimized connection pool and fast TLS handshakes.";
      } else if (performanceImpactCalc < 5) {
        performanceVerdictCalc = "Excellent performance";
        verdictEmojiCalc = "🟢";
        performanceAnalysisCalc =
            "SSL Certificate Pinning adds negligible overhead (${performanceImpactCalc.toStringAsFixed(1)}%) while providing critical security benefits.";
      } else if (performanceImpactCalc < 15) {
        performanceVerdictCalc = "Good performance";
        verdictEmojiCalc = "🟡";
        performanceAnalysisCalc =
            "Moderate ${performanceImpactCalc.toStringAsFixed(1)}% performance impact. Fully acceptable for secure API calls.";
      } else {
        performanceVerdictCalc = "Noticeable overhead";
        verdictEmojiCalc = "🟠";
        performanceAnalysisCalc =
            "There's a ${performanceImpactCalc.toStringAsFixed(1)}% performance overhead compared to standard Dart client.";
      }

      setState(() {
        avgStandard = avgStandardCalc;
        avgSecure = avgSecureCalc;
        minStandard = minStandardCalc;
        maxStandard = maxStandardCalc;
        minSecure = minSecureCalc;
        maxSecure = maxSecureCalc;
        stdDevStandard = stdDevStandardCalc;
        stdDevSecure = stdDevSecureCalc;
        performanceImpact = performanceImpactCalc;
        performanceVerdict = performanceVerdictCalc;
        verdictEmoji = verdictEmojiCalc;
        performanceAnalysis = performanceAnalysisCalc;

        benchmarkResults =
            "Benchmark completed successfully with $iterations iterations";
      });
    } catch (e) {
      setState(() {
        benchmarkResults = "❌ Benchmark Error: $e";
      });
    } finally {
      setState(() {
        isBenchmarkRunning = false;
      });
    }
  }

  double _calculateStandardDeviation(List<Duration> times, double mean) {
    if (times.isEmpty) return 0.0;
    final sumSquaredDiffs = times
        .map((time) => time.inMilliseconds - mean)
        .map((diff) => diff * diff)
        .reduce((a, b) => a + b);
    return sqrt(sumSquaredDiffs / times.length);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Smart Dev SSL Pinning',
      theme: ThemeData(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF0F172A), // Slate 900
          primary: const Color(0xFF2563EB), // Blue 600
          secondary: const Color(0xFF10B981), // Emerald 500
          tertiary: const Color(0xFF8B5CF6), // Violet 500
          surface: Colors.white,
        ),
        appBarTheme: const AppBarTheme(
          centerTitle: true,
          elevation: 0,
          scrolledUnderElevation: 2,
          backgroundColor: Color(0xFF0F172A),
          foregroundColor: Colors.white,
          titleTextStyle: TextStyle(
            fontSize: 18,
            fontWeight: FontWeight.w600,
            letterSpacing: 0.5,
          ),
        ),
        cardTheme: const CardThemeData(
          elevation: 0,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.all(Radius.circular(16)),
            side: BorderSide(color: Color(0xFFE2E8F0)), // Slate 200
          ),
          color: Colors.white,
          margin: EdgeInsets.only(bottom: 20),
        ),
        inputDecorationTheme: InputDecorationTheme(
          filled: true,
          fillColor: const Color(0xFFF1F5F9), // Slate 100
          border: OutlineInputBorder(
            borderRadius: BorderRadius.circular(12),
            borderSide: BorderSide.none,
          ),
          enabledBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(12),
            borderSide: BorderSide.none,
          ),
          focusedBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(12),
            borderSide: const BorderSide(color: Color(0xFF2563EB), width: 2),
          ),
          contentPadding: const EdgeInsets.symmetric(
            horizontal: 16,
            vertical: 16,
          ),
        ),
        elevatedButtonTheme: ElevatedButtonThemeData(
          style: ElevatedButton.styleFrom(
            elevation: 0,
            padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(12),
            ),
          ),
        ),
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Smart Dev Settings'),
          actions: [
            IconButton(
              icon: const Icon(Icons.shield),
              tooltip: 'SSL Pinning',
              onPressed: () {},
            ),
          ],
        ),
        body: SafeArea(
          child: SingleChildScrollView(
            physics: const BouncingScrollPhysics(),
            padding: const EdgeInsets.symmetric(
              horizontal: 16.0,
              vertical: 20.0,
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                _buildConfigurationCard(),
                if (_response.isNotEmpty || _isRequestRunning)
                  _buildResultsCard(),
                _buildBenchmarkCard(),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildConfigurationCard() {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Row(
              children: [
                Container(
                  padding: const EdgeInsets.all(10),
                  decoration: BoxDecoration(
                    color: Theme.of(
                      context,
                    ).colorScheme.primary.withOpacity(0.1),
                    borderRadius: BorderRadius.circular(10),
                  ),
                  child: Icon(
                    Icons.settings_ethernet,
                    color: Theme.of(context).colorScheme.primary,
                  ),
                ),
                const SizedBox(width: 12),
                const Text(
                  'Connection Setup',
                  style: TextStyle(
                    fontSize: 18,
                    fontWeight: FontWeight.bold,
                    color: Color(0xFF1E293B),
                  ),
                ),
              ],
            ),
            const SizedBox(height: 24),

            // URL Input
            const Text(
              'API Endpoint',
              style: TextStyle(
                fontSize: 13,
                fontWeight: FontWeight.w600,
                color: Color(0xFF64748B),
              ),
            ),
            const SizedBox(height: 8),
            TextField(
              controller: _urlController,
              decoration: const InputDecoration(
                hintText: 'https://api.example.com/data',
                prefixIcon: Icon(
                  Icons.link,
                  color: Color(0xFF94A3B8),
                ), // Slate 400
              ),
              keyboardType: TextInputType.url,
              style: const TextStyle(fontSize: 14),
            ),
            const SizedBox(height: 20),

            // Pinning Method Dropdown
            const Text(
              'Pinning Method',
              style: TextStyle(
                fontSize: 13,
                fontWeight: FontWeight.w600,
                color: Color(0xFF64748B),
              ),
            ),
            const SizedBox(height: 8),
            Container(
              decoration: BoxDecoration(
                color: const Color(0xFFF1F5F9),
                borderRadius: BorderRadius.circular(12),
              ),
              child: DropdownButtonHideUnderline(
                child: ButtonTheme(
                  alignedDropdown: true,
                  child: DropdownButton<PinningMethod>(
                    value: _selectedMethod,
                    isExpanded: true,
                    icon: const Icon(
                      Icons.keyboard_arrow_down,
                      color: Color(0xFF94A3B8),
                    ),
                    borderRadius: BorderRadius.circular(12),
                    items:
                        PinningMethod.values.map((method) {
                          return DropdownMenuItem(
                            value: method,
                            child: Text(
                              method.name
                                  .replaceAll('intermediate', 'Intermediate ')
                                  .replaceAll(RegExp(r'(?<!^)(?=[A-Z])'), ' '),
                              style: const TextStyle(
                                fontSize: 14,
                                fontWeight: FontWeight.w500,
                              ),
                            ),
                          );
                        }).toList(),
                    onChanged: _onMethodChanged,
                  ),
                ),
              ),
            ),

            // Method Description
            Padding(
              padding: const EdgeInsets.only(top: 8, left: 4, right: 4),
              child: Text(
                _getMethodDescription(_selectedMethod),
                style: const TextStyle(
                  fontSize: 12,
                  color: Color(0xFF64748B),
                  height: 1.4,
                ),
              ),
            ),
            const SizedBox(height: 20),

            // Hash Input
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                const Text(
                  'SHA-256 Hash (Base64)',
                  style: TextStyle(
                    fontSize: 13,
                    fontWeight: FontWeight.w600,
                    color: Color(0xFF64748B),
                  ),
                ),
                GestureDetector(
                  onTap: () {
                    Clipboard.setData(
                      ClipboardData(text: _hashController.text),
                    );
                    ScaffoldMessenger.of(context).showSnackBar(
                      const SnackBar(
                        content: Text('Hash copied to clipboard'),
                        duration: Duration(seconds: 1),
                      ),
                    );
                  },
                  child: const Text(
                    'Copy',
                    style: TextStyle(
                      fontSize: 12,
                      fontWeight: FontWeight.bold,
                      color: Color(0xFF2563EB),
                    ),
                  ),
                ),
              ],
            ),
            const SizedBox(height: 8),
            TextField(
              controller: _hashController,
              decoration: const InputDecoration(
                hintText: 'Enter base64 encoded SHA-256 hash',
                prefixIcon: Icon(Icons.fingerprint, color: Color(0xFF94A3B8)),
              ),
              style: const TextStyle(fontSize: 14, fontFamily: 'monospace'),
            ),

            const SizedBox(height: 24),

            // Action Button
            ElevatedButton(
              onPressed: _isRequestRunning ? null : _testConnection,
              style: ElevatedButton.styleFrom(
                backgroundColor: Theme.of(context).colorScheme.primary,
                foregroundColor: Colors.white,
              ),
              child:
                  _isRequestRunning
                      ? const SizedBox(
                        height: 20,
                        width: 20,
                        child: CircularProgressIndicator(
                          strokeWidth: 2,
                          color: Colors.white,
                        ),
                      )
                      : const Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          Icon(Icons.rocket_launch, size: 20),
                          SizedBox(width: 8),
                          Text(
                            'Test Connection',
                            style: TextStyle(
                              fontSize: 16,
                              fontWeight: FontWeight.w600,
                            ),
                          ),
                        ],
                      ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildResultsCard() {
    Color statusColor = Colors.grey;
    IconData statusIcon = Icons.pending;

    if (!_isRequestRunning) {
      statusColor =
          _isSuccess ? const Color(0xFF10B981) : const Color(0xFFEF4444);
      statusIcon = _isSuccess ? Icons.check_circle : Icons.error;
    }

    return Card(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
            decoration: BoxDecoration(
              color: statusColor.withOpacity(0.1),
              borderRadius: const BorderRadius.vertical(
                top: Radius.circular(16),
              ),
              border: Border(
                bottom: BorderSide(color: statusColor.withOpacity(0.2)),
              ),
            ),
            child: Row(
              children: [
                Icon(statusIcon, color: statusColor, size: 20),
                const SizedBox(width: 10),
                Text(
                  _isRequestRunning
                      ? 'Executing Request...'
                      : (_isSuccess ? 'Response Received' : 'Request Failed'),
                  style: TextStyle(
                    fontSize: 15,
                    fontWeight: FontWeight.bold,
                    color: statusColor,
                  ),
                ),
              ],
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(20),
            child:
                _isRequestRunning
                    ? const Center(
                      child: Padding(
                        padding: EdgeInsets.all(20),
                        child: CircularProgressIndicator(),
                      ),
                    )
                    : Container(
                      width: double.infinity,
                      padding: const EdgeInsets.all(16),
                      decoration: BoxDecoration(
                        color: const Color(0xFF1E293B), // Slate 800
                        borderRadius: BorderRadius.circular(12),
                      ),
                      child: Text(
                        _response,
                        style: const TextStyle(
                          fontFamily: 'monospace',
                          color: Color(0xFFE2E8F0),
                          fontSize: 13,
                          height: 1.5,
                        ),
                      ),
                    ),
          ),
        ],
      ),
    );
  }

  Widget _buildBenchmarkCard() {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Row(
              children: [
                Container(
                  padding: const EdgeInsets.all(10),
                  decoration: BoxDecoration(
                    color: Theme.of(
                      context,
                    ).colorScheme.tertiary.withOpacity(0.1),
                    borderRadius: BorderRadius.circular(10),
                  ),
                  child: Icon(
                    Icons.speed,
                    color: Theme.of(context).colorScheme.tertiary,
                  ),
                ),
                const SizedBox(width: 12),
                const Text(
                  'Performance Benchmark',
                  style: TextStyle(
                    fontSize: 18,
                    fontWeight: FontWeight.bold,
                    color: Color(0xFF1E293B),
                  ),
                ),
              ],
            ),
            const SizedBox(height: 12),
            const Text(
              'Compare standard Dart HTTP client vs inside-Rust secure client.',
              style: TextStyle(fontSize: 13, color: Color(0xFF64748B)),
            ),
            const SizedBox(height: 20),

            if (avgStandard != null && avgSecure != null) ...[
              _buildBenchmarkVisualization(),
              const SizedBox(height: 20),
            ] else if (isBenchmarkRunning) ...[
              Center(
                child: Padding(
                  padding: const EdgeInsets.symmetric(vertical: 20),
                  child: Column(
                    children: [
                      const CircularProgressIndicator(),
                      const SizedBox(height: 16),
                      Text(
                        benchmarkResults,
                        style: const TextStyle(color: Color(0xFF64748B)),
                      ),
                    ],
                  ),
                ),
              ),
              const SizedBox(height: 20),
            ],

            OutlinedButton.icon(
              onPressed: isBenchmarkRunning ? null : _runBenchmark,
              icon: const Icon(Icons.analytics),
              label: const Text(
                'Run Benchmark',
                style: TextStyle(fontWeight: FontWeight.w600),
              ),
              style: OutlinedButton.styleFrom(
                foregroundColor: Theme.of(context).colorScheme.tertiary,
                side: BorderSide(
                  color: Theme.of(
                    context,
                  ).colorScheme.tertiary.withOpacity(0.5),
                ),
                padding: const EdgeInsets.symmetric(vertical: 14),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildBenchmarkVisualization() {
    final isSecureFaster = performanceImpact! < 0;
    final absoluteDiff = (avgSecure! - avgStandard!).abs();

    return Container(
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: const Color(0xFFF8FAFC),
        borderRadius: BorderRadius.circular(12),
        border: Border.all(color: const Color(0xFFE2E8F0)),
      ),
      child: Column(
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(verdictEmoji ?? '📊', style: const TextStyle(fontSize: 24)),
              const SizedBox(width: 8),
              Expanded(
                child: Text(
                  performanceVerdict ?? 'Results',
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 15,
                    color:
                        isSecureFaster
                            ? const Color(0xFF059669)
                            : const Color(0xFFD97706),
                  ),
                  textAlign: TextAlign.center,
                ),
              ),
            ],
          ),
          const SizedBox(height: 20),

          // Main Comparison
          _buildPerformanceBar(
            'Standard HTTP',
            avgStandard!,
            avgStandard! > avgSecure! ? avgStandard! : avgSecure!,
            const Color(0xFF64748B),
          ),
          const SizedBox(height: 12),
          _buildPerformanceBar(
            'Secure SSL Pinning',
            avgSecure!,
            avgStandard! > avgSecure! ? avgStandard! : avgSecure!,
            isSecureFaster ? const Color(0xFF10B981) : const Color(0xFFF59E0B),
          ),

          const SizedBox(height: 20),
          const Divider(height: 1, color: Color(0xFFE2E8F0)),
          const SizedBox(height: 16),

          // Stats Grid
          Row(
            children: [
              Expanded(
                child: _buildMetricCard(
                  'Diff',
                  '${performanceImpact! > 0 ? '+' : '-'}${absoluteDiff.toStringAsFixed(1)}ms',
                ),
              ),
              const SizedBox(width: 12),
              Expanded(
                child: _buildMetricCard(
                  'Impact',
                  '${performanceImpact! >= 0 ? '+' : ''}${performanceImpact!.toStringAsFixed(1)}%',
                ),
              ),
              const SizedBox(width: 12),
              Expanded(
                child: _buildMetricCard(
                  'Std Dev',
                  '${((stdDevStandard! + stdDevSecure!) / 2).toStringAsFixed(1)}ms',
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }

  Widget _buildPerformanceBar(
    String title,
    double value,
    double maxValue,
    Color color,
  ) {
    final percentage = (value / maxValue).clamp(0.0, 1.0);
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Text(
              title,
              style: const TextStyle(
                fontSize: 12,
                fontWeight: FontWeight.bold,
                color: Color(0xFF334155),
              ),
            ),
            Text(
              '${value.toStringAsFixed(1)}ms',
              style: TextStyle(
                fontSize: 12,
                fontWeight: FontWeight.bold,
                color: color,
              ),
            ),
          ],
        ),
        const SizedBox(height: 6),
        Container(
          height: 12,
          decoration: BoxDecoration(
            color: const Color(0xFFE2E8F0),
            borderRadius: BorderRadius.circular(6),
          ),
          child: FractionallySizedBox(
            widthFactor: percentage,
            alignment: Alignment.centerLeft,
            child: Container(
              decoration: BoxDecoration(
                color: color,
                borderRadius: BorderRadius.circular(6),
              ),
            ),
          ),
        ),
      ],
    );
  }

  Widget _buildMetricCard(String label, String value) {
    return Container(
      padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(8),
        border: Border.all(color: const Color(0xFFE2E8F0)),
      ),
      child: Column(
        children: [
          Text(
            value,
            style: const TextStyle(
              fontSize: 14,
              fontWeight: FontWeight.bold,
              color: Color(0xFF0F172A),
            ),
          ),
          const SizedBox(height: 4),
          Text(
            label,
            style: const TextStyle(
              fontSize: 11,
              color: Color(0xFF64748B),
              fontWeight: FontWeight.w500,
            ),
          ),
        ],
      ),
    );
  }
}
3
likes
150
points
395
downloads

Publisher

verified publishersmart-dev.com.co

Weekly Downloads

This plugin creates a secure native TLS connection to execute HTTP requests with certificate pinning.

Homepage

Documentation

API reference

License

MIT (license)

Dependencies

ffi, flutter, plugin_platform_interface

More

Packages that depend on smart_dev_pinning_plugin

Packages that implement smart_dev_pinning_plugin