Skip to main content

reach 0.0.1 copy "reach: ^0.0.1" to clipboard
reach: ^0.0.1 copied to clipboard

A reliable internet connection checking package for Flutter and Dart applications that validates active socket connections.

example/lib/main.dart

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Reach Example',
      theme: ThemeData(useMaterial3: true, colorSchemeSeed: Colors.indigo),
      home: const ReachHomePage(),
    );
  }
}

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

  @override
  State<ReachHomePage> createState() => _ReachHomePageState();
}

class _ReachHomePageState extends State<ReachHomePage> {
  late final Reach _reach;
  final List<String> _logs = [];
  bool _isCheckingManual = false;

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

    // Initialize Reach with a 15-second recheck interval
    _reach = Reach(
      host: '1.1.1.1',
      port: 443,
      timeout: const Duration(seconds: 3),
      retryGap: const Duration(seconds: 4),
      debounce: const Duration(milliseconds: 500),
      recheckInterval: const Duration(seconds: 15),
    );

    // Start listening to connectivity events
    _reach.start();

    // Log status updates received through the stream
    _reach.stream.listen((isOnline) {
      _addLog('Stream update: ${isOnline ? "ONLINE" : "OFFLINE"}');
    });
  }

  @override
  void dispose() {
    // Always dispose Reach to cancel active timers and stream subscriptions
    _reach.dispose();
    super.dispose();
  }

  void _addLog(String message) {
    if (!mounted) return;
    setState(() {
      final timestamp = TimeOfDay.now().format(context);
      _logs.insert(0, '[$timestamp] $message');
    });
  }

  Future<void> _performManualCheck() async {
    setState(() => _isCheckingManual = true);
    _addLog('Initiating manual probe...');

    final isOnline = await _reach.check();

    if (mounted) {
      setState(() => _isCheckingManual = false);
      _addLog('Manual probe result: ${isOnline ? "ONLINE 🌐" : "OFFLINE 🔴"}');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Reach Connectivity Monitor'),
        centerTitle: true,
      ),
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              // Real-time connection status banner
              StreamBuilder<bool>(
                stream: _reach.stream,
                initialData: _reach.current,
                builder: (context, snapshot) {
                  final isOnline = snapshot.data;

                  return Card(
                    elevation: 2,
                    color: _getStatusColor(isOnline),
                    child: Padding(
                      padding: const EdgeInsets.all(20.0),
                      child: Column(
                        children: [
                          Icon(
                            _getStatusIcon(isOnline),
                            size: 48,
                            color: Colors.white,
                          ),
                          const SizedBox(height: 12),
                          Text(
                            _getStatusText(isOnline),
                            style: const TextStyle(
                              fontSize: 22,
                              fontWeight: FontWeight.bold,
                              color: Colors.white,
                            ),
                          ),
                          const SizedBox(height: 4),
                          Text(
                            isOnline == null
                                ? 'Initializing probe...'
                                : 'Cached status (Reach.current): ${_reach.current}',
                            style: const TextStyle(
                              color: Colors.white70,
                              fontSize: 13,
                            ),
                          ),
                        ],
                      ),
                    ),
                  );
                },
              ),
              const SizedBox(height: 16),

              // Action Bar
              Row(
                children: [
                  Expanded(
                    child: FilledButton.icon(
                      onPressed: _isCheckingManual ? null : _performManualCheck,
                      icon: _isCheckingManual
                          ? const SizedBox(
                              width: 18,
                              height: 18,
                              child: CircularProgressIndicator(
                                strokeWidth: 2,
                                color: Colors.white,
                              ),
                            )
                          : const Icon(Icons.refresh),
                      label: Text(
                        _isCheckingManual ? 'Probing...' : 'Check Now',
                      ),
                    ),
                  ),
                  const SizedBox(width: 12),
                  OutlinedButton.icon(
                    onPressed: () => setState(() => _logs.clear()),
                    icon: const Icon(Icons.delete_outline),
                    label: const Text('Clear Log'),
                  ),
                ],
              ),
              const SizedBox(height: 20),

              // Activity Log Header
              const Text(
                'Activity Log',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
              const SizedBox(height: 8),

              // Activity Log List
              Expanded(
                child: Container(
                  decoration: BoxDecoration(
                    color: Theme.of(context)
                        .colorScheme
                        .surfaceContainerHighest,
                    borderRadius: BorderRadius.circular(12),
                  ),
                  child: _logs.isEmpty
                      ? const Center(
                          child: Text(
                            'No events logged yet.',
                            style: TextStyle(color: Colors.grey),
                          ),
                        )
                      : ListView.separated(
                          padding: const EdgeInsets.all(12),
                          itemCount: _logs.length,
                          separatorBuilder: (_, _) => const Divider(height: 8),
                          itemBuilder: (context, index) {
                            return Text(
                              _logs[index],
                              style: const TextStyle(
                                fontFamily: 'monospace',
                                fontSize: 13,
                              ),
                            );
                          },
                        ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Color _getStatusColor(bool? isOnline) {
    if (isOnline == null) return Colors.orange;
    return isOnline ? Colors.green.shade700 : Colors.red.shade700;
  }

  IconData _getStatusIcon(bool? isOnline) {
    if (isOnline == null) return Icons.sync;
    return isOnline ? Icons.wifi : Icons.wifi_off;
  }

  String _getStatusText(bool? isOnline) {
    if (isOnline == null) return 'Checking Connection...';
    return isOnline ? 'Internet Connected' : 'No Internet Access';
  }
}
0
likes
160
points
381
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A reliable internet connection checking package for Flutter and Dart applications that validates active socket connections.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

connectivity_plus, flutter, plugin_platform_interface

More

Packages that depend on reach