cx_flutter_plugin 0.0.20 copy "cx_flutter_plugin: ^0.0.20" to clipboard
cx_flutter_plugin: ^0.0.20 copied to clipboard

The Coralogix SDK for Flutter is designed to support various Flutter targets by leveraging the numerous platforms supported by Coralogix's native SDKs.

example/lib/main.dart

import 'dart:async';
import 'dart:convert';

import 'package:cx_flutter_plugin/cx_domain.dart';
import 'package:cx_flutter_plugin/cx_exporter_options.dart';
import 'package:cx_flutter_plugin/cx_http_client.dart';
import 'package:cx_flutter_plugin/cx_instrumentation_type.dart';
import 'package:cx_flutter_plugin/cx_types.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;

import 'package:flutter_dotenv/flutter_dotenv.dart';

import 'package:cx_flutter_plugin/cx_flutter_plugin.dart';
//import 'package:http/io_client.dart';

const channel = MethodChannel('example.flutter.coralogix.io');

void main() {
  runZonedGuarded(() async {
    await dotenv.load();

    runApp(MaterialApp(
      title: 'Coralogix SDK Demo',
      theme: ThemeData(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF6750A4),
          brightness: Brightness.light,
        ),
      ),
      darkTheme: ThemeData(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF6750A4),
          brightness: Brightness.dark,
        ),
      ),
      themeMode: ThemeMode.system,
      home: const MyApp(),
    ));
  }, (error, stackTrace) {
    CxFlutterPlugin.reportError(error.toString(), {}, stackTrace.toString());
  });
}

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

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

class _MyAppState extends State<MyApp> {
  String? _sessionId;
  bool _isLoadingSessionId = false;

  @override
  void initState() {
    super.initState();
    initPlatformState();
  }

  Future<void> _loadSessionId() async {
    setState(() {
      _isLoadingSessionId = true;
    });
    try {
      final sessionId = await CxFlutterPlugin.getSessionId();
      if (mounted) {
        setState(() {
          _sessionId = sessionId;
          _isLoadingSessionId = false;
        });
      }
    } catch (e) {
      if (mounted) {
        setState(() {
          _isLoadingSessionId = false;
        });
      }
      debugPrint('Error loading session ID: $e');
    }
  }

  Future<void> _copySessionId() async {
    if (_sessionId != null && _sessionId!.isNotEmpty) {
      await Clipboard.setData(ClipboardData(text: _sessionId!));
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(
            content: Text('Session ID copied to clipboard'),
            duration: Duration(seconds: 2),
          ),
        );
      }
    }
  }

  Future<void> initPlatformState() async {
    // Setup the cx SDK
    var userContext = UserMetadata(
      userId: 'user123',
      userName: 'John Doe',
      userEmail: 'john@example.com',
      userMetadata: {'role': 'admin'},
    );

    var coralogixDomain = CXDomain.eu2;

    var options = CXExporterOptions(
      coralogixDomain: coralogixDomain,
      userContext: userContext,
      environment: 'production',
      application: 'demo-app-flutter',
      version: '1.0.0',
      publicKey: dotenv.env['CORALOGIX_PUBLIC_KEY_EU2']!,
      ignoreUrls: [],
      ignoreErrors: [],
      proxyUrl: dotenv.env['CORALOGIX_PROXY_URL'],
      labels: {'item': 'playstation 5', 'itemPrice': 1999},
      sdkSampler: 100,
      mobileVitalsFPSSamplingRate: 150,
      instrumentations: {
        CXInstrumentationType.network.value: true,
        CXInstrumentationType.custom.value: true,
        CXInstrumentationType.errors.value: true,
        CXInstrumentationType.anr.value: false,
        CXInstrumentationType.lifeCycle.value: false,
        CXInstrumentationType.mobileVitals.value: false,
        CXInstrumentationType.userActions.value: false,
      },
      collectIPData: true,
      enableSwizzling: true,
      traceParentInHeader: { 'enable': true, 
                            'options': {
                                'allowedTracingUrls': ['https://jsonplaceholder.typicode.com/posts/']
                              }
                          },
      debug: true,
    );

    final isInitialize = await CxFlutterPlugin.initSdk(options);
    debugPrint('SDK: $isInitialize');
    await CxFlutterPlugin.setView("Main screen");

    // Load session ID after SDK initialization
    if (mounted) {
      _loadSessionId();
    }

    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) return;
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final colorScheme = theme.colorScheme;

    return Scaffold(
      appBar: AppBar(
        title: const Text('Coralogix SDK Demo'),
        centerTitle: true,
        elevation: 0,
      ),
      body: SafeArea(
        child: SingleChildScrollView(
          key: const Key('sdk-options-list'),
          padding: const EdgeInsets.all(16),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              // Session ID Card
              _SessionIdCard(
                sessionId: _sessionId,
                isLoading: _isLoadingSessionId,
                onCopy: _copySessionId,
                onRefresh: _loadSessionId,
              ),
              const SizedBox(height: 24),
              // Network Operations Section
              _SectionHeader(
                icon: Icons.cloud_outlined,
                title: 'Network Operations',
                color: colorScheme.primary,
              ),
              const SizedBox(height: 12),
              _ActionCard(
                key: const Key('network-success-button'),
                icon: Icons.check_circle_outline,
                title: 'Successful Request',
                subtitle: 'Send a successful network request',
                color: Colors.green,
                onTap: () => sendNetworkRequest('https://jsonplaceholder.typicode.com/posts/'),
              ),
              const SizedBox(height: 8),
              _ActionCard(
                key: const Key('network-failure-button'),
                icon: Icons.error_outline,
                title: 'Failed Request',
                subtitle: 'Send a failed network request',
                color: Colors.red,
                onTap: () => sendNetworkRequest('https://coralogix.com/404'),
              ),
              const SizedBox(height: 24),

              // User & Context Section
              _SectionHeader(
                icon: Icons.person_outline,
                title: 'User & Context',
                color: colorScheme.secondary,
              ),
              const SizedBox(height: 12),
              _ActionCard(
                icon: Icons.account_circle_outlined,
                title: 'Set User Context',
                subtitle: 'Update user metadata',
                color: colorScheme.secondary,
                onTap: sendUserContext,
              ),
              const SizedBox(height: 8),
              _ActionCard(
                icon: Icons.label_outline,
                title: 'Set Labels',
                subtitle: 'Add custom labels',
                color: colorScheme.tertiary,
                onTap: setLabels,
              ),
              const SizedBox(height: 8),
              _ActionCard(
                icon: Icons.label,
                title: 'Get Labels',
                subtitle: 'Retrieve current labels',
                color: colorScheme.tertiary,
                onTap: getLabels,
              ),
              const SizedBox(height: 8),
              _ActionCard(
                icon: Icons.app_settings_alt_outlined,
                title: 'Set Application Context',
                subtitle: 'Update app name and version',
                color: colorScheme.secondary,
                onTap: setApplicationContext,
              ),
              const SizedBox(height: 24),

              // Errors & Logging Section
              const _SectionHeader(
                icon: Icons.bug_report_outlined,
                title: 'Errors & Logging',
                color: Colors.orange,
              ),
              const SizedBox(height: 12),
              const _ActionCard(
                key: Key('report-error-button'),
                icon: Icons.report_problem_outlined,
                title: 'Report Error',
                subtitle: 'Send an error report',
                color: Colors.red,
                onTap: reportError,
              ),
              const SizedBox(height: 8),
              const _ActionCard(
                key: Key('send-error-log-button'),
                icon: Icons.description_outlined,
                title: 'Send Log',
                subtitle: 'Send a custom log message',
                color: Colors.blue,
                onTap: sendLog,
              ),
              const SizedBox(height: 8),
              _ActionCard(
                icon: Icons.rule_outlined,
                title: 'Assert Exception',
                subtitle: 'Trigger an assert failure',
                color: Colors.red,
                onTap: () {
                  assert(false, 'assert failure');
                },
              ),
              const SizedBox(height: 8),
              const _ActionCard(
                key: Key('error-with-custom-labels-button'),
                icon: Icons.warning_amber_outlined,
                title: 'Throw Exception',
                subtitle: 'Throw and catch an exception',
                color: Colors.orange,
                onTap: throwTryCatchInDart,
              ),
              const SizedBox(height: 8),
              const _ActionCard(
                icon: Icons.error_outline,
                title: 'Throw on Pressed',
                subtitle: 'Throw exception on button press',
                color: Colors.red,
                onTap: throwEcexpotionInDart,
              ),
              const SizedBox(height: 8),
              _ActionCard(
                icon: Icons.dangerous_outlined,
                title: 'Swift Fatal Error',
                subtitle: 'Trigger native fatal error',
                color: Colors.deepPurple,
                onTap: () => platformExecute('fatalError'),
              ),
              const SizedBox(height: 24),

              // SDK Management Section
              _SectionHeader(
                icon: Icons.settings_outlined,
                title: 'SDK Management',
                color: colorScheme.primary,
              ),
              const SizedBox(height: 12),
              const _ActionCard(
                icon: Icons.power_settings_new_outlined,
                title: 'SDK Shutdown',
                subtitle: 'Shutdown the SDK',
                color: Colors.grey,
                onTap: sdkShutdown,
              ),
              const SizedBox(height: 8),
              const _ActionCard(
                icon: Icons.check_circle,
                title: 'Is Initialized',
                subtitle: 'Check SDK initialization status',
                color: Colors.green,
                onTap: isInitialized,
              ),
              const SizedBox(height: 8),
              _ActionCard(
                icon: Icons.fingerprint_outlined,
                title: 'Get Session ID',
                subtitle: 'Retrieve current session ID',
                color: colorScheme.primary,
                onTap: getSessionId,
              ),
              const SizedBox(height: 8),
              const _ActionCard(
                key: Key('send-custom-measurement-button'),
                icon: Icons.analytics_outlined,
                title: 'Custom Measurement',
                subtitle: 'Send a custom measurement',
                color: Colors.teal,
                onTap: sendCustomMeasurement,
              ),
              const SizedBox(height: 8),
              _ActionCard(
                key: const Key('verify-logs-button'),
                icon: Icons.verified_outlined,
                title: 'Verify Logs',
                subtitle: 'Validate logs for current session',
                color: Colors.blue,
                onTap: () => verifyLogs(context),
              ),
              const SizedBox(height: 24),

              // Navigation Section
              _SectionHeader(
                icon: Icons.navigation_outlined,
                title: 'Navigation',
                color: colorScheme.tertiary,
              ),
              const SizedBox(height: 12),
              _ActionCard(
                icon: Icons.open_in_new_outlined,
                title: 'Navigate to New Screen',
                subtitle: 'Open a new screen',
                color: colorScheme.tertiary,
                onTap: () => navigateToNewScreen(context),
              ),
              const SizedBox(height: 32),
            ],
          ),
        ),
      ),
    );
  }
}

Future<void> platformExecute(String method) async {
  await channel.invokeMethod(method);
}

Future<void> throwEcexpotionInDart() async {
  throw Exception('Throws onPressed');
}

Future<void> throwTryCatchInDart() async {
  try {
    throw StateError('state error try catch');
  } catch (error, stackTrace) {
    if (error is StateError) {
      // Handle the StateError
      var result = await CxFlutterPlugin.reportError(error.message, {}, stackTrace.toString());
      debugPrint('$result');
    }
  }
}

Future<void> setApplicationContext() async {
  await CxFlutterPlugin.setApplicationContext('demoApp-flutter2', '8.0.0');
}

Future<void> getSessionId() async {
  final sessionId = await CxFlutterPlugin.getSessionId();
  debugPrint('Session Id: $sessionId');
}

Future<void> setView(String name) async {
  await CxFlutterPlugin.setView(name);
}

Future<void> navigateToNewScreen(BuildContext context) async {
  Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => const NewScreen()),
  );
}

Future<void> sendLog() async {
  await CxFlutterPlugin.log(CxLogSeverity.error, 'this is an error',
      {'fruit': 'banna', 'price': 1.30});
}

Future<void> reportError() async {
  var result = await CxFlutterPlugin.reportError(
      'this is an error', {'fruit': 'banna', 'price': 1.30}, "");
  debugPrint('$result');
}

Future<void> sdkShutdown() async {
  await CxFlutterPlugin.shutdown();
}

Future<void> setLabels() async {
  final labels = {'stock': 'NVDA', 'price': 104};
  await CxFlutterPlugin.setLabels(labels);
}

Future<void> sendCustomMeasurement() async {
  await CxFlutterPlugin.sendCustomMeasurement('test', 1.0);
}

Future<void> verifyLogs(BuildContext context) async {
  try {
    final sessionId = await CxFlutterPlugin.getSessionId();
    if (sessionId == null || sessionId.isEmpty) {
      if (context.mounted) {
        _showAlertDialog(
          context,
          'Error',
          'No session ID available',
        );
      }
      return;
    }

    final url = 'https://schema-validator-latest.onrender.com/logs/validate/$sessionId';
    debugPrint('will now fetch logs for: $url');

    http.Response response;
    try {
      response = await http.get(
        Uri.parse(url),
        headers: {
          'Accept': 'application/json',
        },
      ).timeout(
        const Duration(seconds: 30),
        onTimeout: () {
          throw TimeoutException('Request timed out after 30 seconds');
        },
      );
    } on TimeoutException catch (e) {
      debugPrint('Request timeout: $e');
      if (context.mounted) {
        _showAlertDialog(
          context,
          'Error',
          'Request timed out. Please try again.',
        );
      }
      return;
    } on Exception catch (e) {
      debugPrint('Request error: $e');
      if (context.mounted) {
        _showAlertDialog(
          context,
          'Error',
          'Failed to fetch logs: $e',
        );
      }
      return;
    }

    if (!context.mounted) return;

    if (response.statusCode != 200) {
      debugPrint('Fetch failed with status: ${response.statusCode} ${response.reasonPhrase}');
      _showAlertDialog(
        context,
        'Error',
        'Failed to fetch logs: ${response.statusCode} - ${response.reasonPhrase}',
      );
      return;
    }

    final decoded = json.decode(response.body);
    if (decoded is! List) {
      _showAlertDialog(
        context,
        'Error',
        'Unexpected response format: expected a list',
      );
      return;
    }
    final data = decoded;
    bool allValid = true;
    List<String> errorMessages = [];

    for (var item in data) {
      try {
        final itemMap = item as Map<String, dynamic>?;
        if (itemMap == null) {
          allValid = false;
          errorMessages.add('Invalid item format: expected map');
          continue;
        }

        final validationResult =
            itemMap['validationResult'] as Map<String, dynamic>?;
        if (validationResult == null) {
          allValid = false;
          errorMessages.add('Missing validationResult in response');
          continue;
        }

        final statusCode = validationResult['statusCode'] as int?;
        if (statusCode == null) {
          allValid = false;
          errorMessages.add('Missing status code in validation result');
          continue;
        }

        // Handle message - it might be a List or String
        final messageValue = validationResult['message'];
        String? message;
        if (messageValue is String) {
          message = messageValue;
        } else if (messageValue is List) {
          // If message is a list, join it
          message = messageValue.map((e) => e.toString()).join(', ');
        } else if (messageValue != null) {
          message = messageValue.toString();
        }

        if (statusCode != 200) {
          allValid = false;
          errorMessages.add(message ?? 'Invalid status code: $statusCode');
        }
      } catch (e, stackTrace) {
        debugPrint('Error processing item: $e');
        debugPrint('Item structure: $item');
        debugPrint('Stack trace: $stackTrace');
        allValid = false;
        errorMessages.add('Error processing validation item: $e');
        // Continue processing other items even if one fails
      }
    }

    if (data.isEmpty) {
      allValid = false;
      errorMessages.add('No logs found for validation.');
    }

    if (allValid) {
      _showAlertDialog(
        context,
        'Success',
        'All logs are valid! ✅',
      );
    } else {
      _showAlertDialog(
        context,
        'Validation Failed',
        'Some logs failed validation:\n${errorMessages.join('\n')}',
      );
    }
  } catch (error) {
    debugPrint('Verify logs error: $error');
    if (context.mounted) {
      _showAlertDialog(
        context,
        'Error',
        'Failed to verify logs: $error',
      );
    }
  }
}

void _showAlertDialog(BuildContext context, String title, String message) {
  showDialog(
    context: context,
    builder: (BuildContext context) {
      return AlertDialog(
        title: Text(title),
        content: SingleChildScrollView(
          child: Text(message),
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(),
            child: const Text('OK'),
          ),
        ],
      );
    },
  );
}

Future<void> sendUserContext() async {
  var userContext = UserMetadata(
    userId: 'user123',
    userName: 'John Doe',
    userEmail: 'john@example.com',
    userMetadata: {'role': 'admin'},
  );

  await CxFlutterPlugin.setUserContext(userContext);
}

Future<void> getLabels() async {
  try {
    final labels = await CxFlutterPlugin.getLabels();
    if (labels != null) {
      debugPrint('Current labels: $labels');
    } else {
      debugPrint('No labels found');
    }
  } catch (e, stackTrace) {
    debugPrint('Error getting labels: $e');
    debugPrint('Stack trace: $stackTrace');
  }
}

Future<void> isInitialized() async {
  final isInitialized = await CxFlutterPlugin.isInitialized();
  debugPrint('Is Initialized: $isInitialized');
}

Future<void> sendNetworkRequest(String url) async {
  final client = CxHttpClient();
   await client.get(
    Uri.parse(url),
    headers: {
      'Accept': 'application/json',
      'User-Agent': 'FlutterApp/1.0', // Many APIs require this!
    },
  );
}

//  Future<void> sendNetworkRequest(String url) async {
//   final client = await createCxHttpClientWithProxy(); // ✅ await here

//   try {
//     final response = await client.get(
//       Uri.parse(url),
//       headers: {
//        'Accept': 'application/json',
//        'User-Agent': 'FlutterApp/1.0', // Many APIs require this!
//       },
//    );

//   } catch (e) {
//     debugPrint('Request error: $e');
//   } finally {
//     client.close();
//   }
//  }

// Future<CxHttpClient> createCxHttpClientWithProxy() async {
//   // Use 10.0.2.2 for Android emulator, localhost for iOS simulator
//   final proxy = Platform.isAndroid ? '10.0.2.2:9090' : 'localhost:9090';

//   final httpClient = HttpClient();
//   httpClient.findProxy = (uri) => "PROXY $proxy";
//   httpClient.badCertificateCallback = (X509Certificate cert, String host, int port) => true;
//   final ioClient = IOClient(httpClient);

//   return CxHttpClient(ioClient);
// }

class _SectionHeader extends StatelessWidget {
  final IconData icon;
  final String title;
  final Color color;

  const _SectionHeader({
    required this.icon,
    required this.title,
    required this.color,
  });

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Row(
      children: [
        Container(
          padding: const EdgeInsets.all(8),
          decoration: BoxDecoration(
            color: color.withValues(alpha: 0.1),
            borderRadius: BorderRadius.circular(8),
          ),
          child: Icon(icon, color: color, size: 20),
        ),
        const SizedBox(width: 12),
        Text(
          title,
          style: theme.textTheme.titleMedium?.copyWith(
            fontWeight: FontWeight.bold,
            color: color,
          ),
        ),
      ],
    );
  }
}

class _ActionCard extends StatelessWidget {
  final IconData icon;
  final String title;
  final String subtitle;
  final Color color;
  final VoidCallback? onTap;

  const _ActionCard({
    super.key,
    required this.icon,
    required this.title,
    required this.subtitle,
    required this.color,
    this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Card(
      elevation: 1,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(16),
      ),
      child: InkWell(
        onTap: onTap,
        borderRadius: BorderRadius.circular(16),
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Row(
            children: [
              Container(
                width: 48,
                height: 48,
                decoration: BoxDecoration(
                  color: color.withValues(alpha: 0.1),
                  borderRadius: BorderRadius.circular(12),
                ),
                child: Icon(icon, color: color, size: 24),
              ),
              const SizedBox(width: 16),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      title,
                      style: theme.textTheme.titleSmall?.copyWith(
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                    const SizedBox(height: 4),
                    Text(
                      subtitle,
                      style: theme.textTheme.bodySmall?.copyWith(
                        color: theme.colorScheme.onSurfaceVariant,
                      ),
                    ),
                  ],
                ),
              ),
              Icon(
                Icons.chevron_right,
                color: theme.colorScheme.onSurfaceVariant,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class _SessionIdCard extends StatelessWidget {
  final String? sessionId;
  final bool isLoading;
  final VoidCallback onCopy;
  final VoidCallback onRefresh;

  const _SessionIdCard({
    required this.sessionId,
    required this.isLoading,
    required this.onCopy,
    required this.onRefresh,
  });

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final colorScheme = theme.colorScheme;

    return Card(
      elevation: 2,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(16),
      ),
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Container(
                  padding: const EdgeInsets.all(8),
                  decoration: BoxDecoration(
                    color: colorScheme.primary.withValues(alpha: 0.1),
                    borderRadius: BorderRadius.circular(8),
                  ),
                  child: Icon(
                    Icons.fingerprint,
                    color: colorScheme.primary,
                    size: 20,
                  ),
                ),
                const SizedBox(width: 12),
                Text(
                  'Session ID',
                  style: theme.textTheme.titleMedium?.copyWith(
                    fontWeight: FontWeight.bold,
                    color: colorScheme.primary,
                  ),
                ),
                const Spacer(),
                IconButton(
                  icon: Icon(
                    Icons.refresh,
                    color: colorScheme.primary,
                    size: 20,
                  ),
                  onPressed: isLoading ? null : onRefresh,
                  tooltip: 'Refresh Session ID',
                ),
              ],
            ),
            const SizedBox(height: 12),
            if (isLoading)
              const Center(
                child: Padding(
                  padding: EdgeInsets.all(16.0),
                  child: CircularProgressIndicator(),
                ),
              )
            else if (sessionId != null && sessionId!.isNotEmpty)
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Container(
                    width: double.infinity,
                    padding: const EdgeInsets.all(12),
                    decoration: BoxDecoration(
                      color: colorScheme.surfaceContainerHighest.withValues(alpha: 0.5),
                      borderRadius: BorderRadius.circular(8),
                      border: Border.all(
                        color: colorScheme.outline.withValues(alpha: 0.2),
                      ),
                    ),
                    child: SelectableText(
                      sessionId!,
                      key: const Key('session-id'),
                      style: theme.textTheme.bodyMedium?.copyWith(
                        fontFamily: 'monospace',
                        color: colorScheme.onSurface,
                      ),
                    ),
                  ),
                  const SizedBox(height: 12),
                  SizedBox(
                    width: double.infinity,
                    child: FilledButton.icon(
                      onPressed: onCopy,
                      icon: const Icon(Icons.copy, size: 18),
                      label: const Text('Copy Session ID'),
                      style: FilledButton.styleFrom(
                        padding: const EdgeInsets.symmetric(vertical: 12),
                      ),
                    ),
                  ),
                ],
              )
            else
              Padding(
                padding: const EdgeInsets.all(16.0),
                child: Center(
                  child: Text(
                    'Session ID not available',
                    style: theme.textTheme.bodyMedium?.copyWith(
                      color: colorScheme.onSurfaceVariant,
                    ),
                  ),
                ),
              ),
          ],
        ),
      ),
    );
  }
}

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

  @override
  State<NewScreen> createState() => _NewScreenState();
}

class _NewScreenState extends State<NewScreen> {
  @override
  void initState() {
    super.initState();
    CxFlutterPlugin.setView('New Screen');
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final colorScheme = theme.colorScheme;

    return Scaffold(
      appBar: AppBar(
        title: const Text('New Screen'),
        elevation: 0,
      ),
      body: SafeArea(
        child: SingleChildScrollView(
          padding: const EdgeInsets.all(16),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              _SectionHeader(
                icon: Icons.cloud_outlined,
                title: 'Network Operations',
                color: colorScheme.primary,
              ),
              const SizedBox(height: 12),
              _ActionCard(
                icon: Icons.check_circle_outline,
                title: 'Successful Request',
                subtitle: 'Send a successful network request',
                color: Colors.green,
                onTap: () => sendNetworkRequest('https://jsonplaceholder.typicode.com/todos/1'),
              ),
              const SizedBox(height: 24),
              const _SectionHeader(
                icon: Icons.bug_report_outlined,
                title: 'Error Testing',
                color: Colors.orange,
              ),
              const SizedBox(height: 12),
              _ActionCard(
                icon: Icons.error_outline,
                title: 'Show Scaffold Error',
                subtitle: 'Trigger a scaffold error',
                color: Colors.red,
                onTap: () => Scaffold.of(context)
                    .showBottomSheet(
                      (context) => Container(
                        padding: const EdgeInsets.all(24),
                        child: const Text('Scaffold error'),
                      ),
                    ),
              ),
              const SizedBox(height: 32),
            ],
          ),
        ),
      ),
    );
  }
}
1
likes
150
points
649
downloads

Publisher

unverified uploader

Weekly Downloads

The Coralogix SDK for Flutter is designed to support various Flutter targets by leveraging the numerous platforms supported by Coralogix's native SDKs.

Homepage

Documentation

API reference

License

Apache-2.0 (license)

Dependencies

flutter, http, json_annotation, plugin_platform_interface

More

Packages that depend on cx_flutter_plugin

Packages that implement cx_flutter_plugin