appcare_flutter 2.0.1 copy "appcare_flutter: ^2.0.1" to clipboard
appcare_flutter: ^2.0.1 copied to clipboard

An all-in-one Flutter utility package for app maintenance, upgrader dialogs, device info, battery, network diagnostics, biometrics, security, and hardware controls.

example/lib/main.dart

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

void main() {
  runApp(const UpgradeAlert(child: AppCareExampleApp()));
}

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

  @override
  State<AppCareExampleApp> createState() => _AppCareExampleAppState();
}

class _AppCareExampleAppState extends State<AppCareExampleApp> {
  ThemeMode _themeMode = ThemeMode.system;

  void _toggleTheme() {
    setState(() {
      _themeMode = _themeMode == ThemeMode.dark
          ? ThemeMode.light
          : ThemeMode.dark;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'AppCare Flutter Showcase',
      debugShowCheckedModeBanner: false,
      themeMode: _themeMode,
      theme: ThemeData(
        useMaterial3: true,
        colorSchemeSeed: const Color(0xFF6366F1), // Modern Indigo
        brightness: Brightness.light,
        cardTheme: CardThemeData(
          elevation: 0,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(16),
            side: BorderSide(color: Colors.grey.shade200),
          ),
        ),
      ),
      darkTheme: ThemeData(
        useMaterial3: true,
        colorSchemeSeed: const Color(0xFF6366F1),
        brightness: Brightness.dark,
        cardTheme: CardThemeData(
          elevation: 0,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(16),
            side: BorderSide(color: Colors.grey.shade800),
          ),
        ),
      ),
      home: ShowcaseHomeScreen(
        isDark: _themeMode == ThemeMode.dark,
        onToggleTheme: _toggleTheme,
      ),
    );
  }
}

class ShowcaseHomeScreen extends StatefulWidget {
  final bool isDark;
  final VoidCallback onToggleTheme;

  const ShowcaseHomeScreen({
    super.key,
    required this.isDark,
    required this.onToggleTheme,
  });

  @override
  State<ShowcaseHomeScreen> createState() => _ShowcaseHomeScreenState();
}

class _ShowcaseHomeScreenState extends State<ShowcaseHomeScreen>
    with SingleTickerProviderStateMixin {
  final _appCare = AppCare();
  late TabController _tabController;

  // Diagnostics State
  bool _isConnected = true;
  NetworkType _netType = NetworkType.none;
  AppBaseInfo? _appInfo;
  DeviceInfo? _deviceInfo;
  GeoLocation? _location;
  BatteryInfo? _batteryInfo;
  StorageInfo? _storageInfo;
  AppLaunchInfo? _launchInfo;
  ThermalStatus _thermal = ThermalStatus.normal;
  bool _isLowRam = false;
  bool _isSystemDark = false;
  String _locale = '...';
  int _pingMs = -1;
  String _localIp = '...';
  int _wifiSignal = 0;

  // Security & Controls State
  bool _isSecurityEnabled = false;
  bool _keepScreenOn = false;
  double _volume = 1.0;
  bool _isMuted = false;
  bool _hasBiometrics = false;
  double _fontScale = 1.0;
  bool _isMockLoc = false;
  bool _isAutoTime = true;
  bool _isScreenRecording = false;
  bool _hasWhatsApp = false;
  bool _isTorchOn = false;
  bool _isLoading = false;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: 4, vsync: this);
    _initListeners();
    _loadAllData();
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  void _initListeners() {
    _appCare.checkConnectivity().then((value) {
      if (mounted) setState(() => _isConnected = value);
    });

    _appCare.onConnectivityChanged.listen((status) {
      if (mounted) {
        setState(() => _isConnected = status);
        _showSnackBar(
          status ? 'Network connection restored' : 'Network connection lost',
          isError: !status,
        );
      }
    });
  }

  Future<void> _loadAllData() async {
    setState(() => _isLoading = true);

    try {
      final appInfo = await _appCare.getAppBaseInfo();
      final deviceInfo = await _appCare.getDeviceInfo();
      final battery = await _appCare.getBatteryInfo();
      final storage = await _appCare.getStorageInfo();
      final netType = await _appCare.getNetworkType();
      final locale = await _appCare.getDeviceLocale();
      final launch = await _appCare.getAppLaunchInfo();
      final thermal = await _appCare.getThermalStatus();
      final lowRam = await _appCare.isLowMemory();
      final dark = await _appCare.isDarkMode();
      final volume = await _appCare.getVolume();
      final muted = await _appCare.isMuted();
      final ip = await _appCare.getLocalIpAddress();
      final bio = await _appCare.canAuthenticateBiometrics();
      final fontScale = await _appCare.getFontScale();
      final ping = await _appCare.pingHost();
      final mockLoc = await _appCare.isMockLocation();
      final autoTime = await _appCare.isAutomaticTime();
      final recording = await _appCare.isScreenBeingRecorded();
      final whatsApp = await _appCare.isAppInstalled('com.whatsapp');
      final wifiSignal = await _appCare.getWifiSignalStrength();

      if (mounted) {
        setState(() {
          _appInfo = appInfo;
          _deviceInfo = deviceInfo;
          _batteryInfo = battery;
          _storageInfo = storage;
          _netType = netType;
          _locale = locale;
          _launchInfo = launch;
          _thermal = thermal;
          _isLowRam = lowRam;
          _isSystemDark = dark;
          _volume = volume;
          _isMuted = muted;
          _localIp = ip ?? 'Unavailable';
          _hasBiometrics = bio;
          _fontScale = fontScale;
          _pingMs = ping;
          _isMockLoc = mockLoc;
          _isAutoTime = autoTime;
          _isScreenRecording = recording;
          _hasWhatsApp = whatsApp;
          _wifiSignal = wifiSignal;
          _isLoading = false;
        });
      }
    } catch (_) {
      if (mounted) setState(() => _isLoading = false);
    }
  }

  void _showSnackBar(String message, {bool isError = false}) {
    if (!mounted) return;
    ScaffoldMessenger.of(context).hideCurrentSnackBar();
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(message),
        backgroundColor: isError ? Colors.redAccent : const Color(0xFF6366F1),
        behavior: SnackBarBehavior.floating,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
      ),
    );
  }

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

    return Scaffold(
      appBar: AppBar(
        title: Row(
          children: [
            Container(
              padding: const EdgeInsets.all(8),
              decoration: BoxDecoration(
                color: theme.colorScheme.primaryContainer,
                borderRadius: BorderRadius.circular(10),
              ),
              child: Icon(
                Icons.shield_outlined,
                color: theme.colorScheme.primary,
                size: 22,
              ),
            ),
            const SizedBox(width: 12),
            const Text(
              'AppCare Showcase',
              style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
            ),
          ],
        ),
        actions: [
          IconButton(
            icon: Icon(widget.isDark ? Icons.light_mode : Icons.dark_mode),
            tooltip: 'Toggle Theme',
            onPressed: widget.onToggleTheme,
          ),
          IconButton(
            icon: _isLoading
                ? const SizedBox(
                    width: 18,
                    height: 18,
                    child: CircularProgressIndicator(strokeWidth: 2),
                  )
                : const Icon(Icons.refresh),
            tooltip: 'Refresh Data',
            onPressed: _loadAllData,
          ),
        ],
        bottom: TabBar(
          controller: _tabController,
          isScrollable: true,
          labelPadding: const EdgeInsets.symmetric(horizontal: 16),
          indicatorColor: theme.colorScheme.primary,
          labelColor: theme.colorScheme.primary,
          unselectedLabelColor: Colors.grey,
          tabs: const [
            Tab(icon: Icon(Icons.analytics_outlined), text: 'Diagnostics'),
            Tab(icon: Icon(Icons.security_outlined), text: 'Anti-Cheat'),
            Tab(icon: Icon(Icons.tune_outlined), text: 'Hardware'),
            Tab(icon: Icon(Icons.system_update_outlined), text: 'Launchers'),
          ],
        ),
      ),
      body: RefreshIndicator(
        onRefresh: _loadAllData,
        child: TabBarView(
          controller: _tabController,
          children: [
            _buildDiagnosticsTab(),
            _buildSecurityTab(),
            _buildHardwareTab(),
            _buildLaunchersTab(),
          ],
        ),
      ),
    );
  }

  // -------------------------------------------------------------
  // TAB 1: DIAGNOSTICS & SYSTEM STATS
  // -------------------------------------------------------------
  Widget _buildDiagnosticsTab() {
    return ListView(
      padding: const EdgeInsets.all(16),
      children: [
        // Live Network Banner
        Container(
          padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
          decoration: BoxDecoration(
            color: _isConnected
                ? Colors.green.withValues(alpha: 0.1)
                : Colors.red.withValues(alpha: 0.1),
            borderRadius: BorderRadius.circular(16),
            border: Border.all(
              color: _isConnected
                  ? Colors.green.withValues(alpha: 0.3)
                  : Colors.red.withValues(alpha: 0.3),
            ),
          ),
          child: Row(
            children: [
              Container(
                padding: const EdgeInsets.all(8),
                decoration: BoxDecoration(
                  color: _isConnected ? Colors.green : Colors.red,
                  shape: BoxShape.circle,
                ),
                child: Icon(
                  _isConnected ? Icons.wifi : Icons.wifi_off,
                  color: Colors.white,
                  size: 18,
                ),
              ),
              const SizedBox(width: 12),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      _isConnected
                          ? 'Connected (${_netType.name.toUpperCase()})'
                          : 'No Internet Connection',
                      style: TextStyle(
                        fontWeight: FontWeight.bold,
                        color: _isConnected
                            ? Colors.green.shade800
                            : Colors.red,
                      ),
                    ),
                    Text(
                      'Ping: ${_pingMs >= 0 ? "${_pingMs}ms" : "N/A"} | Wi-Fi Level: $_wifiSignal/4 | IP: $_localIp',
                      style: TextStyle(
                        fontSize: 12,
                        color: Colors.grey.shade700,
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
        const SizedBox(height: 16),

        // Battery & Storage Summary Grid
        Row(
          children: [
            Expanded(
              child: Card(
                child: Padding(
                  padding: const EdgeInsets.all(16),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          const Icon(
                            Icons.battery_charging_full,
                            color: Colors.green,
                          ),
                          Text(
                            '${_batteryInfo?.batteryLevel ?? -1}%',
                            style: const TextStyle(
                              fontSize: 18,
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                        ],
                      ),
                      const SizedBox(height: 8),
                      LinearProgressIndicator(
                        value: (_batteryInfo?.batteryLevel ?? 0) / 100,
                        backgroundColor: Colors.grey.withValues(alpha: 0.2),
                        color: Colors.green,
                        borderRadius: BorderRadius.circular(4),
                      ),
                      const SizedBox(height: 6),
                      Text(
                        _batteryInfo?.isCharging == true
                            ? '⚡ Charging'
                            : 'Discharging',
                        style: const TextStyle(
                          fontSize: 11,
                          color: Colors.grey,
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
            const SizedBox(width: 12),
            Expanded(
              child: Card(
                child: Padding(
                  padding: const EdgeInsets.all(16),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          const Icon(
                            Icons.storage_outlined,
                            color: Colors.deepPurple,
                          ),
                          Text(
                            _storageInfo != null
                                ? '${_storageInfo!.freeGB.toStringAsFixed(1)} GB'
                                : '...',
                            style: const TextStyle(
                              fontSize: 18,
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                        ],
                      ),
                      const SizedBox(height: 8),
                      LinearProgressIndicator(
                        value:
                            _storageInfo != null && _storageInfo!.totalBytes > 0
                            ? _storageInfo!.freeBytes / _storageInfo!.totalBytes
                            : 0.5,
                        backgroundColor: Colors.grey.withValues(alpha: 0.2),
                        color: Colors.deepPurple,
                        borderRadius: BorderRadius.circular(4),
                      ),
                      const SizedBox(height: 6),
                      Text(
                        'Total: ${_storageInfo != null ? "${_storageInfo!.totalGB.toStringAsFixed(1)} GB" : "..."}',
                        style: const TextStyle(
                          fontSize: 11,
                          color: Colors.grey,
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ],
        ),
        const SizedBox(height: 16),

        // Device & Package Details
        _buildSectionCard(
          title: 'Device & OS Specs',
          icon: Icons.phone_android_outlined,
          children: [
            _buildDataRow(
              'Model',
              '${_deviceInfo?.manufacturer} ${_deviceInfo?.model}',
            ),
            _buildDataRow(
              'OS',
              '${_deviceInfo?.osName} ${_deviceInfo?.osVersion}',
            ),
            _buildDataRow(
              'RAM Memory',
              _isLowRam ? 'Low Memory Pressure' : 'Normal',
            ),
            _buildDataRow('Thermal State', _thermal.name.toUpperCase()),
            _buildDataRow('Font Scale', '${_fontScale.toStringAsFixed(2)}x'),
            _buildDataRow(
              'System Theme',
              _isSystemDark ? 'Dark Mode' : 'Light Mode',
            ),
          ],
        ),
        const SizedBox(height: 16),

        // App Launch & Package Specs
        _buildSectionCard(
          title: 'App Package & Session',
          icon: Icons.info_outline,
          children: [
            _buildDataRow('App Name', _appInfo?.appName ?? '...'),
            _buildDataRow('Package ID', _appInfo?.packageName ?? '...'),
            _buildDataRow(
              'Version',
              '${_appInfo?.version ?? "..."}+${_appInfo?.buildNumber ?? "..."}',
            ),
            _buildDataRow('Locale', _locale),
            _buildDataRow(
              'First Launch',
              _launchInfo?.isFirstLaunch == true ? 'Yes' : 'No',
            ),
            _buildDataRow(
              'Post Update',
              _launchInfo?.isFirstLaunchAfterUpdate == true ? 'Yes' : 'No',
            ),
            _buildDataRow(
              'Session Uptime',
              '${_launchInfo?.sessionUptimeSeconds ?? 0} seconds',
            ),
          ],
        ),
      ],
    );
  }

  // -------------------------------------------------------------
  // TAB 2: SECURITY & ANTI-CHEAT
  // -------------------------------------------------------------
  Widget _buildSecurityTab() {
    return ListView(
      padding: const EdgeInsets.all(16),
      children: [
        _buildSectionCard(
          title: 'Anti-Cheat & Environmental Integrity',
          icon: Icons.gpp_good_outlined,
          children: [
            _buildStatusTile(
              title: 'Fake GPS / Mock Location',
              subtitle: 'Detects mock location mocking apps',
              status: _isMockLoc ? 'DETECTED' : 'CLEAN',
              isWarning: _isMockLoc,
              icon: Icons.location_off_outlined,
            ),
            _buildStatusTile(
              title: 'Network Time Sync',
              subtitle: 'Prevents device time tampering',
              status: _isAutoTime ? 'SYNCED' : 'MANUAL CLOCK',
              isWarning: !_isAutoTime,
              icon: Icons.access_time_outlined,
            ),
            _buildStatusTile(
              title: 'Active Screen Recording',
              subtitle: 'Monitors ongoing screen recording/casting',
              status: _isScreenRecording ? 'RECORDING' : 'OFF',
              isWarning: _isScreenRecording,
              icon: Icons.videocam_outlined,
            ),
            _buildStatusTile(
              title: 'WhatsApp Detection',
              subtitle: 'Checks external app installation',
              status: _hasWhatsApp ? 'INSTALLED' : 'NOT FOUND',
              isWarning: false,
              icon: Icons.chat_bubble_outline,
            ),
          ],
        ),
        const SizedBox(height: 16),

        _buildSectionCard(
          title: 'Screen Privacy Controls',
          icon: Icons.lock_outline,
          children: [
            SwitchListTile(
              title: const Text('Block Screenshots & Recording'),
              subtitle: Text(
                _isSecurityEnabled
                    ? 'Protected (Screenshots blocked)'
                    : 'Disabled (Screenshots allowed)',
                style: const TextStyle(fontSize: 12),
              ),
              value: _isSecurityEnabled,
              onChanged: (val) async {
                final ok = await _appCare.setScreenSecurity(enable: val);
                if (ok && mounted) {
                  setState(() => _isSecurityEnabled = val);
                  _showSnackBar(
                    val
                        ? 'Screenshot blocking enabled'
                        : 'Screenshot blocking disabled',
                  );
                }
              },
            ),
          ],
        ),
        const SizedBox(height: 16),

        // Geo Location Card
        _buildSectionCard(
          title: 'GPS Coordinates',
          icon: Icons.my_location_outlined,
          trailing: ElevatedButton.icon(
            onPressed: () async {
              final loc = await _appCare.getCurrentLocation();
              if (mounted) {
                setState(() => _location = loc);
                _showSnackBar(
                  loc != null
                      ? 'Location fetched: ${loc.latitude}, ${loc.longitude}'
                      : 'Location unavailable',
                );
              }
            },
            icon: const Icon(Icons.gps_fixed, size: 16),
            label: const Text('Get Location'),
          ),
          children: [
            _buildDataRow(
              'Latitude',
              _location != null ? '${_location!.latitude}' : 'N/A',
            ),
            _buildDataRow(
              'Longitude',
              _location != null ? '${_location!.longitude}' : 'N/A',
            ),
          ],
        ),
      ],
    );
  }

  // -------------------------------------------------------------
  // TAB 3: HARDWARE & CONTROLS
  // -------------------------------------------------------------
  Widget _buildHardwareTab() {
    return ListView(
      padding: const EdgeInsets.all(16),
      children: [
        // Flashlight & WakeLock Quick Toggles
        Card(
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                const Text(
                  'Hardware Toggles',
                  style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
                ),
                const SizedBox(height: 12),
                Row(
                  children: [
                    Expanded(
                      child: OutlinedButton.icon(
                        onPressed: () async {
                          final success = await _appCare.toggleFlashlight();
                          if (success && mounted) {
                            setState(() => _isTorchOn = !_isTorchOn);
                            _showSnackBar(
                              _isTorchOn ? 'Flashlight ON' : 'Flashlight OFF',
                            );
                          }
                        },
                        icon: Icon(
                          _isTorchOn ? Icons.flash_off : Icons.flash_on,
                          color: _isTorchOn ? Colors.orange : null,
                        ),
                        label: Text(_isTorchOn ? 'Torch OFF' : 'Torch ON'),
                      ),
                    ),
                    const SizedBox(width: 12),
                    Expanded(
                      child: OutlinedButton.icon(
                        onPressed: () async {
                          final newVal = !_keepScreenOn;
                          final ok = await _appCare.setKeepScreenOn(
                            keepOn: newVal,
                          );
                          if (ok && mounted) {
                            setState(() => _keepScreenOn = newVal);
                            _showSnackBar(
                              newVal
                                  ? 'Screen WakeLock ON'
                                  : 'Screen WakeLock OFF',
                            );
                          }
                        },
                        icon: Icon(
                          _keepScreenOn
                              ? Icons.visibility
                              : Icons.visibility_off,
                          color: _keepScreenOn ? Colors.blue : null,
                        ),
                        label: Text(_keepScreenOn ? 'Awake ON' : 'Awake OFF'),
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
        ),
        const SizedBox(height: 16),

        // Biometrics Hardware Status
        _buildSectionCard(
          title: 'Biometrics Security',
          icon: Icons.fingerprint_outlined,
          children: [
            _buildStatusTile(
              title: 'Biometric Hardware Enrolled',
              subtitle: 'Fingerprint / Face ID availability',
              status: _hasBiometrics ? 'ENROLLED' : 'NOT ENROLLED',
              isWarning: !_hasBiometrics,
              icon: Icons.fingerprint,
            ),
          ],
        ),
        const SizedBox(height: 16),

        // Haptic Feedback Presets
        _buildSectionCard(
          title: 'Haptic Vibration Engine',
          icon: Icons.vibration_outlined,
          children: [
            const Padding(
              padding: EdgeInsets.only(bottom: 12),
              child: Text(
                'Test native haptic tactile feedback patterns:',
                style: TextStyle(fontSize: 13, color: Colors.grey),
              ),
            ),
            Wrap(
              spacing: 8,
              runSpacing: 8,
              children: [
                _buildHapticChip('Light', HapticType.light),
                _buildHapticChip('Medium', HapticType.medium),
                _buildHapticChip('Heavy', HapticType.heavy),
                _buildHapticChip('Selection', HapticType.selection),
                _buildHapticChip('Success', HapticType.success),
                _buildHapticChip('Error', HapticType.error),
              ],
            ),
          ],
        ),
        const SizedBox(height: 16),

        // Audio & Volume
        _buildSectionCard(
          title: 'Audio & Volume Controller',
          icon: Icons.volume_up_outlined,
          children: [
            Row(
              children: [
                Icon(_isMuted ? Icons.volume_off : Icons.volume_up),
                const SizedBox(width: 8),
                Expanded(
                  child: Slider(
                    value: _volume.clamp(0.0, 1.0),
                    min: 0.0,
                    max: 1.0,
                    divisions: 10,
                    label: '${(_volume * 100).toInt()}%',
                    onChanged: (val) async {
                      setState(() => _volume = val);
                      await _appCare.setVolume(val);
                    },
                  ),
                ),
                Text('${(_volume * 100).toInt()}%'),
              ],
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Text(
                  'Silent Mode: ${_isMuted ? "Muted" : "Active"}',
                  style: const TextStyle(fontSize: 13),
                ),
                TextButton.icon(
                  onPressed: () async {
                    await _appCare.playSystemBeep();
                    _showSnackBar('Played system audio feedback');
                  },
                  icon: const Icon(Icons.music_note, size: 16),
                  label: const Text('Play Beep'),
                ),
              ],
            ),
          ],
        ),
        const SizedBox(height: 16),

        // Screen Orientation
        _buildSectionCard(
          title: 'Screen Orientation Controls',
          icon: Icons.screen_rotation_outlined,
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                ElevatedButton.icon(
                  onPressed: () =>
                      _appCare.setOrientation(ScreenOrientation.portrait),
                  icon: const Icon(Icons.stay_current_portrait, size: 16),
                  label: const Text('Portrait'),
                ),
                ElevatedButton.icon(
                  onPressed: () =>
                      _appCare.setOrientation(ScreenOrientation.landscape),
                  icon: const Icon(Icons.stay_current_landscape, size: 16),
                  label: const Text('Landscape'),
                ),
                OutlinedButton.icon(
                  onPressed: () =>
                      _appCare.setOrientation(ScreenOrientation.unlock),
                  icon: const Icon(Icons.screen_rotation, size: 16),
                  label: const Text('Unlock'),
                ),
              ],
            ),
          ],
        ),
      ],
    );
  }

  // -------------------------------------------------------------
  // TAB 4: LAUNCHERS & MAINTENANCE
  // -------------------------------------------------------------
  Widget _buildLaunchersTab() {
    return ListView(
      padding: const EdgeInsets.all(16),
      children: [
        // Upgrader Widget Live Preview
        const UpgradeCard(elevation: 0, title: 'In-App Update Status'),
        const SizedBox(height: 16),

        // In-App Rating & Review
        _buildSectionCard(
          title: 'In-App Rating & Review',
          icon: Icons.star_rate_outlined,
          children: [
            const Text(
              'Triggers native in-app review popup with 7-day cooldown logic.',
              style: TextStyle(fontSize: 13, color: Colors.grey),
            ),
            const SizedBox(height: 12),
            Row(
              children: [
                Expanded(
                  child: ElevatedButton.icon(
                    onPressed: () async {
                      final prompted = await _appCare.requestReview(
                        minDaysBeforePrompt: 7,
                      );
                      _showSnackBar(
                        prompted
                            ? 'Review prompt triggered!'
                            : 'Review prompt skipped (cooldown active)',
                      );
                    },
                    icon: const Icon(Icons.rate_review, size: 16),
                    label: const Text('Prompt Review'),
                  ),
                ),
                const SizedBox(width: 12),
                OutlinedButton(
                  onPressed: () async {
                    await _appCare.resetReviewHistory();
                    _showSnackBar('Review cooldown history cleared');
                  },
                  child: const Text('Reset Cooldown'),
                ),
              ],
            ),
          ],
        ),
        const SizedBox(height: 16),

        // Native Launchers Grid
        _buildSectionCard(
          title: 'Native App & URL Launchers',
          icon: Icons.launch_outlined,
          children: [
            _buildLauncherRow(
              icon: Icons.language,
              title: 'Open Website URL',
              subtitle: 'https://www.rahulreza.com',
              onTap: () => _appCare.openUrl('https://www.rahulreza.com'),
            ),
            _buildLauncherRow(
              icon: Icons.email_outlined,
              title: 'Send Support Email',
              subtitle: 'contact@rahulreza.com',
              onTap: () => _appCare.openEmail(
                'contact@rahulreza.com',
                subject: 'AppCare Support',
              ),
            ),
            _buildLauncherRow(
              icon: Icons.phone_outlined,
              title: 'Open Phone Dialer',
              subtitle: '+8801700000000',
              onTap: () => _appCare.openDialer('+8801700000000'),
            ),
            _buildLauncherRow(
              icon: Icons.storefront_outlined,
              title: 'Open App Store Listing',
              subtitle: 'Opens native Play/App store',
              onTap: () => _appCare.openStore(),
            ),
          ],
        ),
        const SizedBox(height: 16),

        // Clipboard & Badge Management
        _buildSectionCard(
          title: 'Clipboard & App Icon Badge',
          icon: Icons.copy_outlined,
          children: [
            Row(
              children: [
                Expanded(
                  child: ElevatedButton.icon(
                    onPressed: () async {
                      await _appCare.copyToClipboard('Hello from AppCare!');
                      _showSnackBar('Copied "Hello from AppCare!"');
                    },
                    icon: const Icon(Icons.copy, size: 16),
                    label: const Text('Copy Text'),
                  ),
                ),
                const SizedBox(width: 12),
                Expanded(
                  child: OutlinedButton.icon(
                    onPressed: () async {
                      final text = await _appCare.getTextFromClipboard();
                      _showSnackBar('Clipboard Content: $text');
                    },
                    icon: const Icon(Icons.paste, size: 16),
                    label: const Text('Read Text'),
                  ),
                ),
              ],
            ),
            const SizedBox(height: 12),
            Row(
              children: [
                Expanded(
                  child: ElevatedButton.icon(
                    onPressed: () async {
                      await _appCare.setAppBadgeCount(5);
                      _showSnackBar('App icon badge set to 5');
                    },
                    icon: const Icon(Icons.mark_email_unread, size: 16),
                    label: const Text('Set Badge (5)'),
                  ),
                ),
                const SizedBox(width: 12),
                OutlinedButton(
                  onPressed: () async {
                    await _appCare.clearAppBadge();
                    _showSnackBar('App icon badge cleared');
                  },
                  child: const Text('Clear Badge'),
                ),
              ],
            ),
          ],
        ),
      ],
    );
  }

  // -------------------------------------------------------------
  // HELPER WIDGETS
  // -------------------------------------------------------------
  Widget _buildSectionCard({
    required String title,
    required IconData icon,
    required List<Widget> children,
    Widget? trailing,
  }) {
    final theme = Theme.of(context);

    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Row(
                  children: [
                    Icon(icon, color: theme.colorScheme.primary, size: 20),
                    const SizedBox(width: 8),
                    Text(
                      title,
                      style: const TextStyle(
                        fontSize: 16,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ],
                ),
                ?trailing,
              ],
            ),
            const Divider(height: 24),
            ...children,
          ],
        ),
      ),
    );
  }

  Widget _buildDataRow(String label, String value) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 4),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text(label, style: const TextStyle(fontSize: 13, color: Colors.grey)),
          Text(
            value,
            style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w600),
          ),
        ],
      ),
    );
  }

  Widget _buildStatusTile({
    required String title,
    required String subtitle,
    required String status,
    required bool isWarning,
    required IconData icon,
  }) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 6),
      child: Row(
        children: [
          Icon(icon, size: 20, color: Colors.grey),
          const SizedBox(width: 12),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  title,
                  style: const TextStyle(
                    fontSize: 14,
                    fontWeight: FontWeight.w600,
                  ),
                ),
                Text(
                  subtitle,
                  style: const TextStyle(fontSize: 11, color: Colors.grey),
                ),
              ],
            ),
          ),
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
            decoration: BoxDecoration(
              color: isWarning
                  ? Colors.red.withValues(alpha: 0.15)
                  : Colors.green.withValues(alpha: 0.15),
              borderRadius: BorderRadius.circular(20),
            ),
            child: Text(
              status,
              style: TextStyle(
                fontSize: 11,
                fontWeight: FontWeight.bold,
                color: isWarning ? Colors.red : Colors.green,
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildHapticChip(String label, HapticType type) {
    return ActionChip(
      avatar: const Icon(Icons.touch_app, size: 14),
      label: Text(label),
      onPressed: () async {
        await _appCare.vibrate(type: type);
        _showSnackBar('Haptic: $label triggered');
      },
    );
  }

  Widget _buildLauncherRow({
    required IconData icon,
    required String title,
    required String subtitle,
    required VoidCallback onTap,
  }) {
    return ListTile(
      contentPadding: EdgeInsets.zero,
      leading: Container(
        padding: const EdgeInsets.all(8),
        decoration: BoxDecoration(
          color: Theme.of(context).colorScheme.primaryContainer,
          borderRadius: BorderRadius.circular(8),
        ),
        child: Icon(
          icon,
          size: 20,
          color: Theme.of(context).colorScheme.primary,
        ),
      ),
      title: Text(
        title,
        style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
      ),
      subtitle: Text(
        subtitle,
        style: const TextStyle(fontSize: 12, color: Colors.grey),
      ),
      trailing: const Icon(Icons.arrow_forward_ios, size: 14),
      onTap: onTap,
    );
  }
}
7
likes
160
points
155
downloads

Documentation

API reference

Publisher

verified publisherrahulreza.com

Weekly Downloads

An all-in-one Flutter utility package for app maintenance, upgrader dialogs, device info, battery, network diagnostics, biometrics, security, and hardware controls.

Homepage

Topics

#app-maintenance #upgrader #connectivity #haptics #battery

License

MIT (license)

Dependencies

flutter, flutter_web_plugins

More

Packages that depend on appcare_flutter

Packages that implement appcare_flutter