complycube 1.0.6 copy "complycube: ^1.0.6" to clipboard
complycube: ^1.0.6 copied to clipboard

The official Flutter SDK for integrating ComplyCube's Identity Verification UI into your mobile app.

example/lib/main.dart

import 'dart:async';

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

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const ComplyCubeExampleApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ComplyCube Flutter SDK Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF0F766E)),
        useMaterial3: true,
      ),
      home: const ComplyCubeExamplePage(),
    );
  }
}

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

  @override
  State<ComplyCubeExamplePage> createState() => _ComplyCubeExamplePageState();
}

class _ComplyCubeExamplePageState extends State<ComplyCubeExamplePage> {
  StreamSubscription<ComplyCubeEvent>? _sdkEventsSub;
  final List<String> _eventLog = <String>[];
  bool _isLaunching = false;

  @override
  void initState() {
    super.initState();
    _appendLog('Subscribing to ComplyCube.events stream...');
    _sdkEventsSub = ComplyCube.events.listen(
      _handleSdkEvent,
      onError: (Object error, StackTrace stackTrace) {
        _appendLog('events stream error: $error');
      },
    );
  }

  @override
  void dispose() {
    _sdkEventsSub?.cancel();
    super.dispose();
  }

  void _handleSdkEvent(ComplyCubeEvent event) {
    if (event is ComplyCubeSuccess) {
      _appendLog('onSuccess: payload=${event.payload}');
      return;
    }
    if (event is ComplyCubeError) {
      _appendLog(
        'onError: code=${event.code}, message=${event.message}, details=${event.details}',
      );
      return;
    }
    if (event is ComplyCubeCancelled) {
      _appendLog('onCancelled: code=${event.code}, reason=${event.reason}');
      return;
    }
    if (event is ComplyCubeCustom) {
      _appendLog('onCustomEvent: ${event.event}');
      return;
    }
    _appendLog('onUnknownEvent: $event');
  }

  void _appendLog(String message) {
    if (!mounted) {
      return;
    }
    final String timestamp = DateTime.now().toIso8601String();
    setState(() {
      _eventLog.insert(0, '[$timestamp] $message');
    });
  }

  Future<void> _launch(
    String label,
    Future<ComplyCubeEvent> Function() launcher,
  ) async {
    if (_isLaunching) {
      _appendLog('Skipped "$label": a launch is already in progress.');
      return;
    }

    setState(() {
      _isLaunching = true;
    });

    _appendLog('Launching flow: $label');
    try {
      final ComplyCubeEvent launchResult = await launcher();
      _appendLog('launch call result: ${_describeEvent(launchResult)}');
    } catch (error) {
      _appendLog('launch call threw: $error');
    } finally {
      if (mounted) {
        setState(() {
          _isLaunching = false;
        });
      }
    }
  }

  String _describeEvent(ComplyCubeEvent event) {
    if (event is ComplyCubeSuccess) {
      return 'ComplyCubeSuccess(payload=${event.payload})';
    }
    if (event is ComplyCubeError) {
      return 'ComplyCubeError(code=${event.code}, message=${event.message})';
    }
    if (event is ComplyCubeCancelled) {
      return 'ComplyCubeCancelled(code=${event.code}, reason=${event.reason})';
    }
    if (event is ComplyCubeCustom) {
      return 'ComplyCubeCustom(event=${event.event})';
    }
    return event.runtimeType.toString();
  }

  Future<void> _launchWithStages() async {
    await _launch(
      'ComplyCube.start(stages config)',
      () => ComplyCube.start(_stagesFlowSettings()),
    );
  }

  Future<void> _launchWithWorkflowTemplate() async {
    await _launch(
      'ComplyCube.start(workflowTemplateId config)',
      () => ComplyCube.start(_workflowTemplateSettings()),
    );
  }

  Future<void> _launchWithPreview() async {
    await _launch(
      'ComplyCube.start(preview + workflowDefinition)',
      () => ComplyCube.start(_previewFlowSettings()),
    );
  }

  Map<String, dynamic> _baseSettings() {
    return <String, dynamic>{
      // Required credentials:
      // Use your real credentials from a secure source at runtime.
      // Do NOT hardcode production secrets in source code.
      'clientID': '69662ca82b64c6000268004b',
      'clientToken': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXlsb2FkIjoiTTJGa056VTNZamMzWTJKa1lqVTBZelUzTVRFd1pEZzVOV1UxTkdNNE0yWXlaVEZsWXpVMk1XWXhNalkwWWpFek1tTmlOalU0TlRnMU5HRXhOVGs0WW1JM1lUY3dZVGcwWlRVMFlUVTNOMkl3WldSbE9HWTRNREkwTnpVME5EVXlORFEzTldRek1HUmxOalV3TVdRd09UWm1ZekkwTUdJM01XVmxPVGd6WkRRek9EVTNZbU15WVdKaU56WTRNekJpT0RNd04yTmlZMlV3WlRsaE1EWmpabVZpT1RrNU5XTTBaVGN4TURjelptRmtNMlUwTmpZNE1UUXhOMkZoT1RjMk4yTmlORGMzT0dWbFpXUmlZV1U0T1dWbU16bGxaalJrWm1ZME5HWTBNalEyTUROaE5USTVNMlUzTnpobU9XVTJNams1WWpWbE5qRm1OakUxWVRoa1pXTm1NRFU1WkRNMU5HVmhaVFl3TWpRNE56WTBPR1psT0RJMllUY3hNek5qIiwiZW52aXJvbm1lbnQiOiJsaXZlIiwidXJscyI6eyJhcGkiOiJodHRwczovL2FwaS5jb21wbHljdWJlLmNvbSIsInN5bmMiOiJ3c3M6Ly94ZHMuY29tcGx5Y3ViZS5jb20iLCJjcm9zc0RldmljZSI6Imh0dHBzOi8veGQuY29tcGx5Y3ViZS5jb20ifSwib3B0aW9ucyI6eyJoaWRlQ29tcGx5Q3ViZUxvZ28iOmZhbHNlLCJlbmFibGVDdXN0b21Mb2dvIjp0cnVlLCJlbmFibGVUZXh0QnJhbmQiOnRydWUsImVuYWJsZUN1c3RvbUNhbGxiYWNrcyI6dHJ1ZSwiZW5hYmxlTmZjIjp0cnVlLCJpZGVudGl0eUNoZWNrTGl2ZW5lc3NBdHRlbXB0cyI6NSwiZG9jdW1lbnRJbmZsaWdodFRlc3RBdHRlbXB0cyI6MiwibmZjUmVhZEF0dGVtcHRzIjo1LCJlbmFibGVBZGRyZXNzQXV0b2NvbXBsZXRlIjp0cnVlLCJlbmFibGVXaGl0ZUxhYmVsaW5nIjpmYWxzZX0sImlhdCI6MTc3NjkzNDkxMywiZXhwIjoxNzc2OTM4NTEzfQ.KLXoUp6_LsygOSfwW3ax2S79e-cOqA6jbpEqnSl8kBo',

      // Optional top-level settings:
      'disableScreenCapture': true,

      // Optional UI customization maps.
      // Android parser expects `colorScheme`.
      // iOS parser currently reads `scheme`.
      // Including both keeps this example cross-platform.
      'lookAndFeel': _lookAndFeelTemplate(),
      'colorScheme': _colorSchemeTemplate(),
      'scheme': _colorSchemeTemplate(),

      // Optional iOS-only explicit country list support.
      // When omitted, countries can still be inferred from stage config.
      'countries': <String>['GB', 'FR', 'US', 'CA'],
    };
  }

  Map<String, dynamic> _workflowTemplateSettings() {
    final Map<String, dynamic> settings = _baseSettings();
    settings['workflowTemplateId'] = 'YOUR_WORKFLOW_TEMPLATE_ID';
    return settings;
  }

  Map<String, dynamic> _previewFlowSettings() {
    final Map<String, dynamic> settings = _baseSettings();
    settings['environment'] = ComplyCubeEnvironment.preview;
    settings['workflowDefinition'] = <String, dynamic>{
      'id': '696e57bb37ebc8000276325d',
      'version': 1,
      'status': 'inactive',
      'workflowTemplateId': '694b9cbd9761050002908e24',
      'workflowTemplateName': 'December Testing',
      'workflowTemplateDescription': 'December',
      'type': 'linear',
      'useCaseType': 'standard',
      'additionalVerificationRules': <Map<String, dynamic>>[
        <String, dynamic>{'type': 'otp_verification', 'mode': 'none'},
        <String, dynamic>{'type': 'autofill', 'mode': 'none'},
      ],
      'tasks': <Map<String, dynamic>>[
        <String, dynamic>{
          'taskId': 'start',
          'type': 'ui',
          'subType': 'welcome_screen',
          'isExplicit': false,
          'defaultNextTask': 'consent',
        },
        <String, dynamic>{
          'taskId': 'consent',
          'type': 'ui',
          'subType': 'consent_screen',
          'isExplicit': false,
          'defaultNextTask': 'task_10_97h_lp9',
        },
        <String, dynamic>{
          'taskId': 'task_10_97h_lp9',
          'type': 'ui',
          'subType': 'document_capture_screen',
          'implicitlyAddedForTasks': <String>['task_10_97h'],
          'options': <String, dynamic>{
            'showGuidance': true,
            'enableMLAssistance': true,
            'retryAttempts': 3,
            'liveCaptureOnly': false,
            'crossDeviceOnly': false,
            'strictDocumentSelection': false,
            'nfcCapture': false,
            'documentTypes': <String, dynamic>{
              'passport': <String, dynamic>{'enabled': true},
              'residence_permit': <String, dynamic>{'enabled': true},
              'driving_license': <String, dynamic>{'enabled': true},
              'national_identity_card': <String, dynamic>{'enabled': true},
            },
          },
          'isExplicit': false,
          'defaultNextTask': 'task_10_97h',
        },
        <String, dynamic>{
          'taskId': 'task_10_97h',
          'type': 'check',
          'subType': 'document_check',
          'additionalParameters': <String, dynamic>{'action': 'create_check'},
          'options': <String, dynamic>{
            'minimumPermittedAge': 25,
            'clientDataValidation': false,
            'securityElementsThreshold': 50,
            'livenessThreshold': 50,
            'documentModelValidity': true,
          },
          'isExplicit': true,
          'defaultNextTask': 'complete',
        },
        <String, dynamic>{
          'taskId': 'complete',
          'type': 'ui',
          'subType': 'complete_screen',
          'isExplicit': true,
          'isFinalTask': true,
          'defaultNextTask': 'complete',
        },
      ],
      'updatedAt': '2026-01-19T16:11:47.460Z',
      'createdAt': '2026-01-19T16:11:39.899Z',
      'description': 'Document check',
    };
    return settings;
  }

  Map<String, dynamic> _stagesFlowSettings() {
    final Map<String, dynamic> settings = _baseSettings();
    settings['stages'] = <Map<String, dynamic>>[
      // Supported stage names (map-based): intro, consent, complete, outro,
      // documentCapture, faceCapture/face_capture, poaCapture, addressCapture, customerInfo.
      <String, dynamic>{
        'name': 'intro',
        'title': 'Welcome',
        'message': 'We will now verify your identity.',
      },
      <String, dynamic>{
        'name': 'consent',
        'title': 'Consent',
        'message': 'Please accept to continue verification.',
      },
      <String, dynamic>{
        'name': 'documentCapture',
        // documentCapture specific options:
        'nfcEnabled': false,
        'captureDocumentId': false,
        'showGuidance': true,
        'useLiveCaptureOnly': false,
        'useMLAssistance': true,
        'retryLimit': 3,
        // `documentTypes` supports bool or country arrays.
        'documentTypes': <String, dynamic>{
          'passport': true,
          'driving_license': <String>['GB', 'FR'],
          'national_identity_card': <String>['GB', 'FR'],
          'residence_permit': <String>['GB', 'FR'],
        },
      },
      <String, dynamic>{
        // Alias supported too: face_capture
        'name': 'faceCapture',
        'mode': 'photo',
        'showGuidance': true,
        'useLiveCaptureOnly': true,
        'useMLAssistance': true,
        'retryLimit': 2,
      },
      <String, dynamic>{
        'name': 'poaCapture',
        'showGuidance': true,
        'useLiveCaptureOnly': true,
        'useMLAssistance': true,
        'retryLimit': 3,
        'isAddressCaptureEnabled': true,
        'documentTypes': <String, dynamic>{
          'utility_bill': <String>['GB', 'FR'],
          'bank_statement': true,
        },
      },
      <String, dynamic>{
        'name': 'customerInfo',
        'title': 'Customer Information',
        'customerInfoFields': <dynamic>[
          // Built-in fields can be provided as strings.
          'first_name',
          'middle_name',
          'last_name',
          'date_of_birth',
          // Complex details and metadata payload:
          <String, dynamic>{
            'details': <Map<String, dynamic>>[
              <String, dynamic>{
                'person': <dynamic>[
                  'nationality',
                  'birth_country',
                  'national_id',
                  <String, dynamic>{
                    'name': 'ssn',
                    'constraint': <String, dynamic>{
                      'expression': 'metadata.Has SSN contains yes',
                    },
                  },
                ],
                'company': <dynamic>[
                  'name',
                  'website',
                  'registration_number',
                ],
              },
            ],
            'metadata': <Map<String, dynamic>>[
              <String, dynamic>{
                'key': 'Tax Residence',
                'question': 'Are you a tax resident outside of your home country?',
                'componentType': 'SINGLE_CHOICE',
                'options': <Map<String, String>>[
                  <String, String>{'label': 'No', 'value': 'No'},
                  <String, String>{'label': 'Yes', 'value': 'Outside'},
                ],
                'required': true,
                'description': 'Select your tax residency status.',
              },
              <String, dynamic>{
                'key': 'Jurisdiction Country',
                'question': 'Select tax residence countries',
                'componentType': 'MULTI_SELECT_COUNTRY',
                // Country filtering for MULTI_SELECT_COUNTRY:
                'countries': <String, dynamic>{
                  'mode': 'inclusion', // inclusion | exclusion
                  'list': <String>['US', 'CA', 'GB', 'FR'],
                },
                'constraint': <String, dynamic>{
                  'expression': 'metadata.Tax Residence contains Outside',
                },
                'required': true,
                'description': 'All countries where you are tax resident.',
              },
              <String, dynamic>{
                'key': 'Has SSN',
                'question': 'Do you have a Social Security Number?',
                'componentType': 'SINGLE_CHOICE',
                'options': <Map<String, String>>[
                  <String, String>{'label': 'Yes', 'value': 'yes'},
                  <String, String>{'label': 'No', 'value': 'no'},
                ],
                'constraint': <String, dynamic>{
                  'expression': 'metadata.Jurisdiction Country contains US',
                },
                'required': true,
                'description': 'Required for US tax residents.',
              },
              <String, dynamic>{
                'key': 'SSN Reason',
                'question': 'Why do you not have an SSN?',
                'componentType': 'PARAGRAPH',
                'format': <String, String>{
                  'type': 'MAXCHAR',
                  'validation': '500',
                },
                'constraint': <String, dynamic>{
                  'expression': 'metadata.Has SSN contains no',
                },
                'required': false,
                'description': 'Optional explanation.',
              },
            ],
            // Metadata templates for dynamic country-driven questions.
            'metadataTemplates': <Map<String, dynamic>>[
              <String, dynamic>{
                'templateKey': 'TIN_HAS',
                'question': 'Do you have a TIN for {country}?',
                'componentType': 'SINGLE_CHOICE',
                'options': <Map<String, String>>[
                  <String, String>{'label': 'Yes', 'value': 'yes'},
                  <String, String>{'label': 'No', 'value': 'no'},
                ],
                'description': 'Select one option.',
              },
              <String, dynamic>{
                'templateKey': 'TIN',
                'question': 'Tax Identification Number for {country}',
                'componentType': 'SHORT_ANSWER',
                'format': <String, String>{
                  'type': 'MAXCHAR',
                  'validation': '100',
                },
                'description': 'Enter the TIN value.',
              },
              <String, dynamic>{
                'templateKey': 'TIN_REASON',
                'question': 'Reason for missing TIN in {country}',
                'componentType': 'SINGLE_CHOICE',
                'options': <Map<String, String>>[
                  <String, String>{'label': 'Pending', 'value': 'pending'},
                  <String, String>{'label': 'Not applicable', 'value': 'na'},
                  <String, String>{'label': 'Other', 'value': 'other'},
                ],
              },
              <String, dynamic>{
                'templateKey': 'TIN_REASON_OTHER',
                'question': 'Please explain why no TIN is available.',
                'componentType': 'PARAGRAPH',
                'format': <String, String>{
                  'type': 'MAXCHAR',
                  'validation': '500',
                },
              },
            ],
          },
        ],
      },
      <String, dynamic>{
        // Android parser supports complete/outro.
        'name': 'complete',
        'title': 'Verification Completed',
        'message': 'Your verification flow is now complete.',
      },
      <String, dynamic>{
        'name': 'outro',
        'title': 'Done',
        'message': 'You can now return to your app.',
      },
    ];
    return settings;
  }

  Map<String, dynamic> _lookAndFeelTemplate() {
    return <String, dynamic>{
      // General:
      'isDarkMode': false,
      'uiInterfaceStyle': 'inherited', // inherited | light | dark
      'borderRadius': 8,
      'enableAnimations': true,

      // Primary button:
      'primaryButtonColor': '#0F766E',
      'primaryButtonBgColor': '#0F766E',
      'primaryButtonPressedBgColor': '#115E59',
      'primaryButtonTextColor': '#FFFFFF',
      'primaryButtonBorderColor': '#0F766E',

      // Secondary button:
      'secondaryButtonColor': '#0F766E',
      'secondaryButtonBgColor': '#FFFFFF',
      'secondaryButtonPressedBgColor': '#E6FFFA',
      'secondaryButtonTextColor': '#0F766E',
      'secondaryButtonBorderColor': '#0F766E',

      // Document selector (modern + legacy names):
      'documentSelectorColor': '#FFFFFF',
      'documentSelectorBorderColor': '#D1D5DB',
      'documentSelectorIconColor': '#0F766E',
      'documentSelectorTitleTextColor': '#111827',
      'documentSelectorDescriptionTextColor': '#4B5563',
      'documentTypeSelectorBgColor': '#FFFFFF',
      'documentTypeSelectorBorderColor': '#D1D5DB',
      'documentTypeSelectorIconColor': '#0F766E',
      'documentTypeSelectorTitleTextColor': '#111827',
      'documentTypeSelectorDescriptionTextColor': '#4B5563',

      // Info popup/panel:
      'infoPopupColor': '#F0FDFA',
      'infoPopupIconColor': '#0F766E',
      'infoPopupTitleTextColor': '#115E59',
      'infoPopupDescriptionTextColor': '#0F172A',
      'infoPanelColor': '#F0FDFA',
      'infoPanelBgColor': '#F0FDFA',
      'infoPanelIconColor': '#0F766E',
      'infoPanelTitleColor': '#115E59',
      'infoPanelTitleTextColor': '#115E59',
      'infoPanelDescriptionTextColor': '#0F172A',
      'popUpBgColor': '#F0FDFA',
      'popUpTitleColor': '#115E59',

      // Error popup/panel:
      'errorPopupColor': '#FEF2F2',
      'errorPopupIconColor': '#B91C1C',
      'errorPopupTitleTextColor': '#991B1B',
      'errorPopupDescriptionTextColor': '#7F1D1D',
      'errorPanelColor': '#FEF2F2',
      'errorPanelBgColor': '#FEF2F2',
      'errorPanelIconColor': '#B91C1C',
      'errorPanelTitleTextColor': '#991B1B',
      'errorPanelDescriptionTextColor': '#7F1D1D',

      // Camera and text:
      'cameraButtonColor': '#0F766E',
      'bodyTextColor': '#111827',
      'headingTextColor': '#0F172A',
      'subheadingTextColor': '#334155',
      'linkButtonTextColor': '#0F766E',
      'blueBigType': '#0F766E',
      'textItemType': '#111827',

      // Surfaces and input:
      'backgroundColor': '#F8FAFC',
      'backgroundContentColor': '#FFFFFF',
      'backgroundContentContrastColor': '#F1F5F9',
      'backgroundDividerColor': '#E2E8F0',
      'editTextColor': '#111827',
    };
  }

  Map<String, dynamic> _colorSchemeTemplate() {
    return <String, dynamic>{
      // Primary button:
      'primaryButtonBgColor': '#0F766E',
      'primaryButtonPressedBgColor': '#115E59',
      'primaryButtonTextColor': '#FFFFFF',
      'primaryButtonBorderColor': '#0F766E',

      // Secondary button:
      'secondaryButtonBgColor': '#FFFFFF',
      'secondaryButtonPressedBgColor': '#E6FFFA',
      'secondaryButtonTextColor': '#0F766E',
      'secondaryButtonBorderColor': '#0F766E',

      // Document selector aliases:
      'docTypeBgColor': '#FFFFFF',
      'docTypeTextColor': '#111827',
      'docTypeBorderColor': '#D1D5DB',
      'documentSelectorColor': '#FFFFFF',
      'documentSelectorBorderColor': '#D1D5DB',
      'documentSelectorIconColor': '#0F766E',
      'documentSelectorTitleTextColor': '#111827',
      'documentSelectorDescriptionTextColor': '#4B5563',

      // Info popup aliases:
      'popUpBgColor': '#F0FDFA',
      'popUpTitleColor': '#115E59',
      'infoPopupColor': '#F0FDFA',
      'infoPopupIconColor': '#0F766E',
      'infoPopupTitleTextColor': '#115E59',
      'infoPopupDescriptionTextColor': '#0F172A',

      // Error popup:
      'errorPopupColor': '#FEF2F2',
      'errorPopupIconColor': '#B91C1C',
      'errorPopupTitleTextColor': '#991B1B',
      'errorPopupDescriptionTextColor': '#7F1D1D',

      // Text aliases:
      'textSecondary': '#111827',
      'headerTitle': '#0F172A',
      'subheaderTitle': '#334155',
      'linkButtonTextColor': '#0F766E',
      'blueBigType': '#0F766E',
      'textItemType': '#111827',

      // Background/input:
      'backgroundColor': '#F8FAFC',
      'backgroundContentColor': '#FFFFFF',
      'backgroundContentContrastColor': '#F1F5F9',
      'backgroundDividerColor': '#E2E8F0',
      'editTextColor': '#111827',

      // Misc:
      'cameraButtonColor': '#0F766E',
    };
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('ComplyCube Flutter SDK Example')),
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              const Text(
                'This example demonstrates recommended SDK launch patterns:\n'
                '1) map-based staged flow, 2) workflowTemplateId flow, '
                '3) preview + workflowDefinition.\n'
                'Replace placeholder credentials before using in production.',
              ),
              const SizedBox(height: 16),
              ElevatedButton(
                onPressed: _isLaunching ? null : _launchWithStages,
                child: const Text('Launch with stages map'),
              ),
              const SizedBox(height: 8),
              ElevatedButton(
                onPressed: _isLaunching ? null : _launchWithWorkflowTemplate,
                child: const Text('Launch with workflowTemplateId'),
              ),
              const SizedBox(height: 8),
              ElevatedButton(
                onPressed: _isLaunching ? null : _launchWithPreview,
                child: const Text('Launch with preview + workflowDefinition'),
              ),
              const SizedBox(height: 8),
              OutlinedButton(
                onPressed: () => setState(_eventLog.clear),
                child: const Text('Clear event log'),
              ),
              const SizedBox(height: 12),
              const Text(
                'SDK Event Log',
                style: TextStyle(fontWeight: FontWeight.w600),
              ),
              const SizedBox(height: 8),
              Expanded(
                child: Container(
                  decoration: BoxDecoration(
                    border: Border.all(color: Theme.of(context).dividerColor),
                    borderRadius: BorderRadius.circular(8),
                  ),
                  child: _eventLog.isEmpty
                      ? const Center(
                          child: Text('No events yet. Launch the SDK to begin.'),
                        )
                      : ListView.separated(
                          padding: const EdgeInsets.all(12),
                          itemCount: _eventLog.length,
                          separatorBuilder: (_, __) => const Divider(height: 16),
                          itemBuilder: (BuildContext context, int index) {
                            return Text(
                              _eventLog[index],
                              style: const TextStyle(fontFamily: 'monospace'),
                            );
                          },
                        ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
2
likes
140
points
354
downloads

Documentation

API reference

Publisher

verified publishercomplycube.com

Weekly Downloads

The official Flutter SDK for integrating ComplyCube's Identity Verification UI into your mobile app.

Homepage

License

MIT (license)

Dependencies

flutter

More

Packages that depend on complycube

Packages that implement complycube