Flutter Phone-to-Phone Power Share Tracker (Wireless Charging Hacker UI App)

 Demo :


Click Video πŸ‘‡πŸ‘‡πŸ‘‡

























⭐ FEATURES :

  • Phone-to-phone wireless power tracker

  • BatteryManager API

  • NFC detection

  • Cyberpunk hacker UI

  • Live energy beam animation

  • All-device responsive

  • Viral Flutter project


Code :


import 'dart:async';

import 'dart:math' as math;

import 'dart:ui';


import 'package:battery_plus/battery_plus.dart';

import 'package:flutter/material.dart';

import 'package:flutter/services.dart';

import 'package:google_fonts/google_fonts.dart';

import 'package:nfc_manager/nfc_manager.dart';

import 'package:flutter_animate/flutter_animate.dart';


void main() {

  SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(

    statusBarColor: Colors.transparent,

    statusBarIconBrightness: Brightness.light,

    systemNavigationBarColor: Color(0xFF050505),

    systemNavigationBarIconBrightness: Brightness.light,

  ));

  runApp(const PowerShareApp());

}


class PowerShareApp extends StatelessWidget {

  const PowerShareApp({super.key});


  @override

  Widget build(BuildContext context) {

    return MaterialApp(

      debugShowCheckedModeBanner: false,

      title: 'PowerShare Protocol',

      theme: ThemeData.dark().copyWith(

        scaffoldBackgroundColor: const Color(0xFF050505),

        primaryColor: const Color(0xFF00F0FF),

        colorScheme: const ColorScheme.dark(

          primary: Color(0xFF00F0FF),

          secondary: Color(0xFFD000FF),

          surface: Color(0xFF101015),

        ),

        textTheme: GoogleFonts.rajdhaniTextTheme(ThemeData.dark().textTheme),

      ),

      home: const PowerShareHome(),

    );

  }

}


class PowerShareHome extends StatefulWidget {

  const PowerShareHome({super.key});


  @override

  State<PowerShareHome> createState() => _PowerShareHomeState();

}


class _PowerShareHomeState extends State<PowerShareHome>

    with TickerProviderStateMixin {

  // Battery State

  final Battery _battery = Battery();

  int _batteryLevel = 100;

  BatteryState _batteryState = BatteryState.full;

  StreamSubscription<BatteryState>? _batteryStateSubscription;


  // NFC & Connection State

  bool _isNfcAvailable = false;

  bool _isScanning = false;

  bool _isConnected = false;

  String _connectionStatus = "STANDBY";

  String _connectedDeviceName = "";

  

  // Power Sharing State

  bool _isSharing = false;

  bool _isReceiver = false; // Toggle between Giver/Receiver for simulation

  double _transferEfficiency = 0.0;

  double _transferRate = 0.0; // Watts

  Timer? _simulationTimer;

  

  // Animations

  late AnimationController _pulseController;

  late AnimationController _beamController;


  @override

  void initState() {

    super.initState();

    _initBattery();

    _initNfc();

    

    _pulseController = AnimationController(

        vsync: this, duration: const Duration(seconds: 2))..repeat();

    _beamController = AnimationController(

        vsync: this, duration: const Duration(milliseconds: 1500))..repeat();

  }


  @override

  void dispose() {

    _batteryStateSubscription?.cancel();

    _simulationTimer?.cancel();

    _pulseController.dispose();

    _beamController.dispose();

    super.dispose();

  }


  Future<void> _initBattery() async {

    try {

      final level = await _battery.batteryLevel;

      _batteryStateSubscription =

          _battery.onBatteryStateChanged.listen((BatteryState state) {

        setState(() {

          _batteryState = state;

        });

      });

      if (mounted) {

        setState(() {

          _batteryLevel = level;

        });

      }

    } catch (e) {

      debugPrint("Battery Error: $e");

    }

  }


  Future<void> _initNfc() async {

    bool isAvailable = await NfcManager.instance.isAvailable();

    setState(() {

      _isNfcAvailable = isAvailable;

    });


    if (isAvailable) {

      // Start listening for tags if relevant, or wait for manual trigger 

      // strict "Phone-to-Phone" usually requires Android Beam (deprecated) or proprietary.

      // We will simulate the connection trigger via NFC tag discovery if present.

    }

  }


  void _toggleScan() {

    if (_isConnected) {

      _disconnect();

      return;

    }

    

    setState(() {

      _isScanning = !_isScanning;

      _connectionStatus = _isScanning ? "SEARCHING..." : "STANDBY";

    });


    if (_isScanning) {

      // If NFC is available, try to read. If not, just simulate finding after delay.

      if (_isNfcAvailable) {

        NfcManager.instance.startSession(

          pollingOptions: {NfcPollingOption.iso14443, NfcPollingOption.iso15693},

          onDiscovered: (NfcTag tag) async {

           // Simulate finding a compatible phone

           _handleDeviceFound("NFC_DEVICE_${tag.data.hashCode.toString().substring(0, 4)}");

           NfcManager.instance.stopSession();

        }).catchError((e) {

             // Fallback to simulation if error

        });

      }

      

      // Simulation Fallback for Demo

      Future.delayed(const Duration(seconds: 3), () {

        if (mounted && _isScanning && !_isConnected) {

          _handleDeviceFound("GALAXY_S29_ULTRA");

        }

      });

    } else {

      NfcManager.instance.stopSession().catchError((_) {});

    }

  }


  void _handleDeviceFound(String deviceName) {

    setState(() {

      _isScanning = false;

      _isConnected = true;

      _connectedDeviceName = deviceName;

      _connectionStatus = "LINK ESTABLISHED";

      _isSharing = true;

      _startSharingSimulation();

    });

  }


  void _disconnect() {

    _simulationTimer?.cancel();

    setState(() {

      _isConnected = false;

      _isSharing = false;

      _connectionStatus = "STANDBY";

      _transferEfficiency = 0;

      _transferRate = 0;

    });

  }


  void _startSharingSimulation() {

    _simulationTimer = Timer.periodic(const Duration(milliseconds: 500), (timer) {

      if (!mounted) return;

      setState(() {

        // Fluctuate values for realism

        _transferEfficiency = 85.0 + math.Random().nextDouble() * 14.0;

        _transferRate = (_isReceiver ? 15.0 : -15.0) + math.Random().nextDouble() * 2.0;


        // Simulate battery change slowly

        if (timer.tick % 20 == 0) {

           // every 10 seconds

           if (_isReceiver) {

             _batteryLevel = (_batteryLevel + 1).clamp(0, 100);

           } else {

             _batteryLevel = (_batteryLevel - 1).clamp(0, 100);

           }

        }

      });

    });

  }


  @override

  Widget build(BuildContext context) {

    final size = MediaQuery.of(context).size;

    final isMobile = size.width < 600;

    

    return Scaffold(

      body: Stack(

        children: [

          // 1. Background Grid & Particles

          Positioned.fill(

            child: CustomPaint(

              painter: GridPainter(

                color: Theme.of(context).colorScheme.primary.withOpacity(0.1),

                scroll: _pulseController.value,

              ),

            ),

          ),

          

          // 2. Animated Background Glow

          Positioned(

            top: -100,

            left: -100,

            child: Container(

              width: 300,

              height: 300,

              decoration: BoxDecoration(

                shape: BoxShape.circle,

                color: Theme.of(context).colorScheme.secondary.withOpacity(0.15),

                boxShadow: [BoxShadow(color: Theme.of(context).colorScheme.secondary, blurRadius: 100)],

              ),

            ).animate(onPlay: (c) => c.repeat(reverse: true)).scale(duration: 4.seconds, begin: const Offset(1,1), end: const Offset(1.5,1.5)),

          ),


          // 3. Main Content

          SafeArea(

            child: Column(

              children: [

                _buildHeader(),

                Expanded(

                  child: LayoutBuilder(

                    builder: (context, constraints) {

                      if (!isMobile) {

                        return Row(

                          children: [

                            Expanded(child: _buildPhoneVisual(isMe: true)),

                            Expanded(child: _buildConnectionVisual()),

                            Expanded(child: _buildPhoneVisual(isMe: false)),

                          ],

                        );

                      } else {

                        // Mobile Layout: Vertical

                        return Column(

                          mainAxisAlignment: MainAxisAlignment.center,

                          children: [

                            _buildPhoneVisual(isMe: true),

                            Expanded(child: _buildConnectionVisual()),

                            if (_isConnected) _buildPhoneVisual(isMe: false),

                          ],

                        );

                      }

                    },

                  ),

                ),

                _buildHUD(),

                const SizedBox(height: 20),

                _buildControls(),

                const SizedBox(height: 20),

              ],

            ),

          ),

        ],

      ),

    );

  }


  Widget _buildHeader() {

    return Container(

      padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),

      child: Row(

        mainAxisAlignment: MainAxisAlignment.spaceBetween,

        children: [

          Row(

            children: [

              Icon(Icons.bolt, color: Theme.of(context).primaryColor),

              const SizedBox(width: 8),

              Text(

                "POWER_SHARE // PROTOCOL",

                style: GoogleFonts.orbitron(

                  fontSize: 16,

                  fontWeight: FontWeight.bold,

                  letterSpacing: 2,

                  color: Colors.white,

                ),

              ),

            ],

          ),

          Container(

            padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),

            decoration: BoxDecoration(

              border: Border.all(color: _isNfcAvailable ? Colors.green : Colors.red),

              borderRadius: BorderRadius.circular(4),

              color: (_isNfcAvailable ? Colors.green : Colors.red).withOpacity(0.1),

            ),

            child: Text(

              _isNfcAvailable ? "NFC ACTIVE" : "NFC OFFLINE",

              style: TextStyle(

                fontSize: 10,

                color: _isNfcAvailable ? Colors.green : Colors.red,

                fontWeight: FontWeight.bold,

              ),

            ),

          )

        ],

      ),

    );

  }


  Widget _buildPhoneVisual({required bool isMe}) {

    // If not connected and not me, show nothing or empty slot

    if (!isMe && !_isConnected) return const SizedBox.shrink();


    final color = isMe 

        ? (_isReceiver ? Colors.redAccent : Colors.cyanAccent)

        : (_isReceiver ? Colors.cyanAccent : Colors.redAccent); // Opposite

    

    // Logic: If I am receiver, I am Red (Low/Charging) -> He is Cyan (Source). 

    // Wait, usually Source=Green/Cyan, Receiver=Red/Yellow.

    // If I am Receiver: My Battery is getting charge.

    

    final level = isMe ? _batteryLevel : (100 - _batteryLevel); // Fake other battery

    final label = isMe ? "LOCAL_DEVICE" : "REMOTE_LINK";

    final subLabel = isMe ? "THIS DEVICE" : _connectedDeviceName;


    return Container(

      margin: const EdgeInsets.all(20),

      padding: const EdgeInsets.all(20),

      decoration: BoxDecoration(

        color: const Color(0xFF1A1A20),

        borderRadius: BorderRadius.circular(20),

        border: Border.all(color: color.withOpacity(0.5), width: 1),

        boxShadow: [

          BoxShadow(color: color.withOpacity(0.1), blurRadius: 20, spreadRadius: 5),

        ],

      ),

      child: Column(

        mainAxisSize: MainAxisSize.min,

        children: [

          Icon(isMe ? Icons.smartphone : Icons.phonelink_ring, size: 40, color: color),

          const SizedBox(height: 10),

          Text(label, style: GoogleFonts.rajdhani(color: Colors.white54, fontSize: 12, letterSpacing: 1.5)),

          Text(subLabel, style: GoogleFonts.orbitron(color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold)),

          const SizedBox(height: 20),

          Stack(

            alignment: Alignment.center,

            children: [

               CircularProgressIndicator(

                 value: level / 100,

                 strokeWidth: 8,

                 backgroundColor: Colors.white10,

                 valueColor: AlwaysStoppedAnimation(color),

               ),

               Text("$level%", style: GoogleFonts.orbitron(fontWeight: FontWeight.bold)),

            ],

          ),

          const SizedBox(height: 10),

          Text(isMe 

              ? (_isReceiver ? "RECEIVING" : "TRANSMITTING") 

              : (_isReceiver ? "TRANSMITTING" : "RECEIVING"),

              style: TextStyle(color: color, fontSize: 10, letterSpacing: 2)

          ),

        ],

      ),

    ).animate().fadeIn().slideY(begin: 0.1, end: 0);

  }


  Widget _buildConnectionVisual() {

    if (!_isConnected) {

      if (_isScanning) {

        return Center(

          child: Column(

            mainAxisSize: MainAxisSize.min,

            children: [

              const CircularProgressIndicator(color: Colors.cyanAccent),

              const SizedBox(height: 20),

              Text("SCANNING NEAR FIELD...", style: GoogleFonts.orbitron(letterSpacing: 2, color: Colors.cyanAccent)),

            ],

          ),

        );

      }

      return Center(

        child: Text("LINK REQUIRED", style: GoogleFonts.rajdhani(color: Colors.white24, fontSize: 20)),

      );

    }


    return AnimatedBuilder(

      animation: _beamController,

      builder: (context, child) {

        return CustomPaint(

          size: const Size(double.infinity, 200),

          painter: EnergyBeamPainter(

            animationValue: _beamController.value,

            color: const Color(0xFF00F0FF),

            isVertical: MediaQuery.of(context).size.width < 600,

          ),

        );

      },

    );

  }


  Widget _buildHUD() {

    if (!_isConnected && !_isScanning) return const SizedBox.shrink();


    return GlassContainer(

      child: Row(

        mainAxisAlignment: MainAxisAlignment.spaceEvenly,

        children: [

          _buildHUDItem("STATUS", _connectionStatus, _isConnected ? Colors.greenAccent : Colors.amber),

          if (_isConnected) ...[

            _buildVerticalDivider(),

            _buildHUDItem("EFFICIENCY", "${_transferEfficiency.toStringAsFixed(1)}%", Colors.cyanAccent),

            _buildVerticalDivider(),

            _buildHUDItem("RATE", "${_transferRate.abs().toStringAsFixed(1)}W", Colors.purpleAccent),

          ]

        ],

      ),

    );

  }


  Widget _buildVerticalDivider() => Container(width: 1, height: 30, color: Colors.white24);


  Widget _buildHUDItem(String label, String value, Color color) {

    return Column(

      children: [

        Text(label, style: GoogleFonts.rajdhani(color: Colors.white54, fontSize: 10, fontWeight: FontWeight.bold)),

        const SizedBox(height: 4),

        Text(value, style: GoogleFonts.orbitron(color: color, fontSize: 18, fontWeight: FontWeight.bold)),

      ],

    );

  }


  Widget _buildControls() {

    return Column(

      children: [

        if (_isConnected)

           Padding(

             padding: const EdgeInsets.only(bottom: 20),

             child: Row(

               mainAxisAlignment: MainAxisAlignment.center,

               children: [

                 Text("ROLE: ", style: GoogleFonts.rajdhani(color: Colors.white)),

                 Switch(

                   value: _isReceiver, 

                   activeColor: Colors.redAccent,

                   inactiveThumbColor: Colors.cyanAccent,

                   onChanged: (val) {

                     setState(() {

                       _isReceiver = val;

                     });

                   }

                 ),

                 Text(_isReceiver ? "RECEIVER" : "GIVER", style: TextStyle(

                   color: _isReceiver ? Colors.redAccent : Colors.cyanAccent,

                   fontWeight: FontWeight.bold

                 )),

               ],

             ),

           ),


        GestureDetector(

          onTap: _toggleScan,

          child: AnimatedContainer(

            duration: const Duration(milliseconds: 300),

            padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 15),

            decoration: BoxDecoration(

              gradient: LinearGradient(

                colors: _isScanning 

                  ? [Colors.red.shade900, Colors.red.shade600] 

                  : (_isConnected ? [Colors.red.shade900, Colors.red.shade600] : [Colors.cyan.shade900, Colors.cyan.shade600]),

              ),

              boxShadow: [

                BoxShadow(

                  color: (_isScanning || _isConnected) ? Colors.redAccent : Colors.cyanAccent,

                  blurRadius: 15,

                  offset: const Offset(0, 5),

                )

              ],

              borderRadius: BorderRadius.circular(30),

            ),

            child: Text(

              _isConnected ? "TERMINATE LINK" : (_isScanning ? "CANCEL SCAN" : "INITIATE SCAN"),

              style: GoogleFonts.orbitron(

                color: Colors.white,

                fontWeight: FontWeight.bold,

                fontSize: 16,

                letterSpacing: 2,

              ),

            ),

          ),

        ),

      ],

    );

  }

}


// ---------------------------

// PAINTERS for Sci-Fi Effects

// ---------------------------


class GridPainter extends CustomPainter {

  final Color color;

  final double scroll;


  GridPainter({required this.color, required this.scroll});


  @override

  void paint(Canvas canvas, Size size) {

    final paint = Paint()

      ..color = color

      ..strokeWidth = 1

      ..style = PaintingStyle.stroke;


    const spacing = 40.0;

    

    // Draw Grid with perspective illusion if possible, plain for now

    for (double i = 0; i < size.width; i += spacing) {

      canvas.drawLine(Offset(i, 0), Offset(i, size.height), paint);

    }

    for (double i = 0; i < size.height; i += spacing) {

      double y = (i + (scroll * spacing)) % size.height;

      canvas.drawLine(Offset(0, y), Offset(size.width, y), paint);

    }

  }


  @override

  bool shouldRepaint(covariant GridPainter oldDelegate) => true;

}


class EnergyBeamPainter extends CustomPainter {

  final double animationValue;

  final Color color;

  final bool isVertical;


  EnergyBeamPainter({required this.animationValue, required this.color, required this.isVertical});


  @override

  void paint(Canvas canvas, Size size) {

    final paint = Paint()

      ..color = color

      ..style = PaintingStyle.stroke

      ..strokeWidth = 3

      ..shader = LinearGradient(

        colors: [color.withOpacity(0), color, color.withOpacity(0)],

        stops: const [0.0, 0.5, 1.0],

      ).createShader(Rect.fromLTWH(0, 0, size.width, size.height));


    final path = Path();

    

    if (isVertical) {

       // Wave flowing down

       for (double i = 0; i < size.height; i++) {

         double x = size.width / 2 + 

             math.sin((i / 20) + (animationValue * 2 * math.pi)) * 10 +

             math.cos((i / 30) + (animationValue * 4 * math.pi)) * 5;

         if (i == 0) path.moveTo(x, i);

         else path.lineTo(x, i);

       }

    } else {

       // Wave flowing right

       for (double i = 0; i < size.width; i++) {

         double y = size.height / 2 + 

             math.sin((i / 20) + (animationValue * 2 * math.pi)) * 10 +

             math.cos((i / 30) + (animationValue * 4 * math.pi)) * 5;

         if (i == 0) path.moveTo(i, y);

         else path.lineTo(i, y);

       }

    }

    

    canvas.drawPath(path, paint);

    

    // Core beam

    final corePaint = Paint()..color = Colors.white.withOpacity(0.5)..strokeWidth = 1;

    if (isVertical) {

      canvas.drawLine(Offset(size.width/2, 0), Offset(size.width/2, size.height), corePaint);

    } else {

      canvas.drawLine(Offset(0, size.height/2), Offset(size.width, size.height/2), corePaint);

    }

  }


  @override

  bool shouldRepaint(EnergyBeamPainter oldDelegate) => true;

}


// ---------------------------

// UTILITY WIDGETS

// ---------------------------


class GlassContainer extends StatelessWidget {

  final Widget child;

  const GlassContainer({super.key, required this.child});


  @override

  Widget build(BuildContext context) {

    return ClipRRect(

      borderRadius: BorderRadius.circular(15),

      child: BackdropFilter(

        filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),

        child: Container(

          padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 15),

          decoration: BoxDecoration(

            color: Colors.white.withOpacity(0.05),

            borderRadius: BorderRadius.circular(15),

            border: Border.all(color: Colors.white.withOpacity(0.1)),

          ),

          child: child,

        ),

      ),

    );

  }

}


Comments

Popular posts from this blog

Educational File Encryptor GUI (Python AES Project) | FuzzuTech

Is This News Real or Fake? πŸ€– AI Exposes the Truth | FuzzuTech Python App Demo

🚨 Python Intrusion Detection System (IDS) – Real-Time ML + Tkinter GUI Project | FuzzuTech