smart_phone_number 1.0.2 copy "smart_phone_number: ^1.0.2" to clipboard
smart_phone_number: ^1.0.2 copied to clipboard

A smart phone number parser that automatically detects country codes from number prefixes and validates WhatsApp accounts

example/main.dart

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

void main() => runApp(MyApp());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Phone Validator Example',
      theme: ThemeData(primarySwatch: Colors.blue, useMaterial3: true),
      home: PhoneValidatorExample(),
    );
  }
}

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

  @override
  _PhoneValidatorExampleState createState() => _PhoneValidatorExampleState();
}

class _PhoneValidatorExampleState extends State<PhoneValidatorExample> {
  final TextEditingController _controller = TextEditingController();
  String _result = '';
  bool _loading = false;
  String _selectedMethod = 'Auto Detect';

  final List<String> _methods = [
    'Auto Detect',
    'Specific Country',
    'Force Country',
  ];

  String _selectedCountry = '967'; // Yemen default
  final List<Map<String, String>> _countries = [
    {'code': '967', 'name': 'šŸ‡¾šŸ‡Ŗ Yemen'},
    {'code': '966', 'name': 'šŸ‡øšŸ‡¦ Saudi Arabia'},
    {'code': '962', 'name': 'šŸ‡ÆšŸ‡“ Jordan'},
    {'code': '20', 'name': 'šŸ‡ŖšŸ‡¬ Egypt'},
    {'code': '964', 'name': 'šŸ‡®šŸ‡¶ Iraq'},
    {'code': '971', 'name': 'šŸ‡¦šŸ‡Ŗ UAE'},
    {'code': '965', 'name': 'šŸ‡°šŸ‡¼ Kuwait'},
    {'code': '974', 'name': 'šŸ‡¶šŸ‡¦ Qatar'},
    {'code': '973', 'name': 'šŸ‡§šŸ‡­ Bahrain'},
    {'code': '968', 'name': 'šŸ‡“šŸ‡² Oman'},
    {'code': '961', 'name': 'šŸ‡±šŸ‡§ Lebanon'},
    {'code': '970', 'name': 'šŸ‡µšŸ‡ø Palestine'},
    {'code': '218', 'name': 'šŸ‡±šŸ‡¾ Libya'},
    {'code': '216', 'name': 'šŸ‡¹šŸ‡³ Tunisia'},
    {'code': '213', 'name': 'šŸ‡©šŸ‡æ Algeria'},
    {'code': '212', 'name': 'šŸ‡²šŸ‡¦ Morocco'},
    {'code': '1', 'name': 'šŸ‡ŗšŸ‡ø USA'},
    {'code': '44', 'name': 'šŸ‡¬šŸ‡§ UK'},
    {'code': '49', 'name': 'šŸ‡©šŸ‡Ŗ Germany'},
    {'code': '33', 'name': 'šŸ‡«šŸ‡· France'},
    {'code': '39', 'name': 'šŸ‡®šŸ‡¹ Italy'},
    {'code': '34', 'name': 'šŸ‡ŖšŸ‡ø Spain'},
    {'code': '90', 'name': 'šŸ‡¹šŸ‡· Turkey'},
    {'code': '91', 'name': 'šŸ‡®šŸ‡³ India'},
  ];

  Future<void> _validateNumber() async {
    if (_controller.text.isEmpty) {
      setState(() => _result = 'āš ļø Please enter a phone number');
      return;
    }

    setState(() {
      _loading = true;
      _result = '';
    });

    try {
      PhoneResult result;

      switch (_selectedMethod) {
        case 'Auto Detect':
          result = await SmartPhoneNumber.detectAndValidate(_controller.text);
          break;

        case 'Specific Country':
          result = await SmartPhoneNumber.validateWithCountryCode(
            phoneNumber: _controller.text,
            countryCode: _selectedCountry,
          );
          break;

        case 'Force Country':
          result = await SmartPhoneNumber.validateWithCountryCode(
            phoneNumber: _controller.text,
            countryCode: _selectedCountry,
            forceCountryCode: true,
          );
          break;

        default:
          result = await SmartPhoneNumber.detectAndValidate(_controller.text);
      }

      setState(() {
        if (result.success) {
          _result =
              '''
āœ… WhatsApp Account Found!

šŸ“± Phone: ${result.phoneNumber}
šŸŒ Country Code: +${result.countryCode}
šŸ“ Region: ${result.regionCode}

šŸ’” Tip: You can now open WhatsApp and start chatting!
''';
        } else {
          _result = 'āŒ ${result.message}';

          if (result.possibleCountries != null &&
              result.possibleCountries!.isNotEmpty) {
            _result += '\n\nšŸ“‹ Possible Countries:';
            for (var country in result.possibleCountries!) {
              _result +=
                  '\n• ${country.nameAr} (${country.name}) - +${country.code}';
            }
          }

          if (result.possibleNumbers != null &&
              result.possibleNumbers!.isNotEmpty) {
            _result += '\n\nšŸ“ž Possible Formats:';
            for (var number in result.possibleNumbers!) {
              _result += '\n• $number';
            }
          }
        }
      });
    } catch (e) {
      setState(() => _result = 'āŒ Error: $e');
    } finally {
      setState(() => _loading = false);
    }
  }

  void _clearAll() {
    _controller.clear();
    setState(() => _result = '');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('šŸ“± Phone Validator'),
        backgroundColor: Colors.blue,
        foregroundColor: Colors.white,
        actions: [
          IconButton(
            icon: Icon(Icons.help_outline),
            onPressed: () => _showHelpDialog(),
          ),
        ],
      ),
      body: Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            // Method Selection
            Card(
              child: Padding(
                padding: EdgeInsets.all(12),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Validation Method',
                      style: TextStyle(
                        fontWeight: FontWeight.bold,
                        fontSize: 16,
                      ),
                    ),
                    SizedBox(height: 8),
                    SegmentedButton<String>(
                      segments: _methods.map((method) {
                        return ButtonSegment<String>(
                          value: method,
                          label: Text(method),
                        );
                      }).toList(),
                      selected: {_selectedMethod},
                      onSelectionChanged: (Set<String> selection) {
                        setState(() {
                          _selectedMethod = selection.first;
                        });
                      },
                    ),
                    if (_selectedMethod != 'Auto Detect') ...[
                      SizedBox(height: 12),
                      DropdownButtonFormField<String>(
                        initialValue: _selectedCountry,
                        decoration: InputDecoration(
                          labelText: 'Select Country',
                          border: OutlineInputBorder(),
                        ),
                        items: _countries.map((country) {
                          return DropdownMenuItem<String>(
                            value: country['code'],
                            child: Text(country['name']!),
                          );
                        }).toList(),
                        onChanged: (value) {
                          setState(() {
                            _selectedCountry = value!;
                          });
                        },
                      ),
                      if (_selectedMethod == 'Force Country')
                        Padding(
                          padding: EdgeInsets.only(top: 8),
                          child: Container(
                            padding: EdgeInsets.all(8),
                            decoration: BoxDecoration(
                              color: Colors.orange.shade50,
                              borderRadius: BorderRadius.circular(8),
                              border: Border.all(color: Colors.orange),
                            ),
                            child: Row(
                              children: [
                                Icon(Icons.info_outline, color: Colors.orange),
                                SizedBox(width: 8),
                                Expanded(
                                  child: Text(
                                    'āš ļø Will force using +$_selectedCountry even if number has another prefix',
                                    style: TextStyle(fontSize: 12),
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ),
                    ],
                  ],
                ),
              ),
            ),

            SizedBox(height: 16),

            // Phone Input
            TextField(
              controller: _controller,
              decoration: InputDecoration(
                labelText: 'Enter phone number',
                hintText: 'e.g., 712345678 or +967712345678',
                border: OutlineInputBorder(),
                prefixIcon: Icon(Icons.phone),
                suffixIcon: IconButton(
                  icon: Icon(Icons.clear),
                  onPressed: _clearAll,
                ),
              ),
              keyboardType: TextInputType.phone,
              onSubmitted: (_) => _validateNumber(),
            ),

            SizedBox(height: 16),

            // Validate Button
            ElevatedButton(
              onPressed: _loading ? null : _validateNumber,
              style: ElevatedButton.styleFrom(
                padding: EdgeInsets.symmetric(vertical: 16),
                backgroundColor: Colors.blue,
                foregroundColor: Colors.white,
              ),
              child: _loading
                  ? SizedBox(
                      width: 24,
                      height: 24,
                      child: CircularProgressIndicator(
                        strokeWidth: 2,
                        valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
                      ),
                    )
                  : Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Icon(Icons.check_circle_outline),
                        SizedBox(width: 8),
                        Text('Validate Number'),
                      ],
                    ),
            ),

            SizedBox(height: 16),

            // Result Container
            Expanded(
              child: Container(
                padding: EdgeInsets.all(12),
                decoration: BoxDecoration(
                  border: Border.all(color: Colors.grey.shade300),
                  borderRadius: BorderRadius.circular(8),
                  color: Colors.grey.shade50,
                ),
                child: _result.isEmpty
                    ? Center(
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Icon(
                              Icons.phone_android,
                              size: 48,
                              color: Colors.grey.shade400,
                            ),
                            SizedBox(height: 8),
                            Text(
                              'Enter a phone number and tap Validate',
                              style: TextStyle(color: Colors.grey.shade600),
                            ),
                          ],
                        ),
                      )
                    : SingleChildScrollView(
                        child: Text(
                          _result,
                          style: TextStyle(fontSize: 14, height: 1.5),
                        ),
                      ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  void _showHelpDialog() {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('How to Use'),
        content: SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(
                '1. Enter a phone number',
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
              Text(
                '  • Can be local (712345678) or international (+967712345678)',
              ),
              SizedBox(height: 8),
              Text(
                '2. Choose validation method',
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
              Text('  • Auto Detect: Automatically detects country'),
              Text('  • Specific Country: Use your chosen country'),
              Text(
                '  • Force Country: Force country code even if number has another',
              ),
              SizedBox(height: 8),
              Text(
                '3. Tap Validate',
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
              Text('  • Checks if number exists on WhatsApp'),
              Text('  • Shows country info and possible formats'),
            ],
          ),
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: Text('Got it!'),
          ),
        ],
      ),
    );
  }
}
1
likes
0
points
546
downloads

Publisher

unverified uploader

Weekly Downloads

A smart phone number parser that automatically detects country codes from number prefixes and validates WhatsApp accounts

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, get_country_ip, phone_number, url_launcher

More

Packages that depend on smart_phone_number