import 'package:flutter/material.dart'; import 'package:flutter_background_service/flutter_background_service.dart'; import 'proxy_service.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); await ProxyService.initialize(); runApp(const KPhoneApp()); } class KPhoneApp extends StatelessWidget { const KPhoneApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'k_phone', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo), useMaterial3: true, ), home: const ProxyStatusScreen(), ); } } class ProxyStatusScreen extends StatefulWidget { const ProxyStatusScreen({super.key}); @override State createState() => _ProxyStatusScreenState(); } class _ProxyStatusScreenState extends State { bool _serviceRunning = false; bool _cardAttached = false; String _statusMessage = 'Stopped'; final List _log = []; @override void initState() { super.initState(); _subscribeToService(); } void _subscribeToService() { final service = FlutterBackgroundService(); // Sync initial running state service.isRunning().then((running) { if (mounted) setState(() => _serviceRunning = running); }); service.on('status').listen((event) { if (event == null) return; if (mounted) { setState(() { _serviceRunning = event['running'] as bool? ?? false; _cardAttached = event['cardAttached'] as bool? ?? false; _statusMessage = event['message'] as String? ?? ''; final log = event['log'] as String?; if (log != null) { _log.insert(0, log); if (_log.length > 200) _log.removeLast(); } }); } }); } Future _toggleService() async { final service = FlutterBackgroundService(); final running = await service.isRunning(); if (running) { service.invoke('stop'); setState(() { _serviceRunning = false; _cardAttached = false; _statusMessage = 'Stopped'; }); } else { await service.startService(); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('k_phone — ChromeCard proxy'), backgroundColor: Theme.of(context).colorScheme.inversePrimary, ), body: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _StatusTile( label: 'Proxy service', ok: _serviceRunning, value: _serviceRunning ? 'Running on :8771' : 'Stopped', ), const SizedBox(height: 8), _StatusTile( label: 'ChromeCard (USB)', ok: _cardAttached, value: _cardAttached ? 'Attached' : 'Not detected', ), const SizedBox(height: 8), Text( _statusMessage, style: Theme.of(context).textTheme.bodySmall, ), const SizedBox(height: 16), FilledButton( onPressed: _toggleService, child: Text(_serviceRunning ? 'Stop proxy' : 'Start proxy'), ), const Divider(height: 32), const Text('Log', style: TextStyle(fontWeight: FontWeight.bold)), Expanded( child: ListView.builder( itemCount: _log.length, itemBuilder: (_, i) => Text( _log[i], style: const TextStyle(fontSize: 11, fontFamily: 'monospace'), ), ), ), ], ), ), ); } } class _StatusTile extends StatelessWidget { final String label; final bool ok; final String value; const _StatusTile({ required this.label, required this.ok, required this.value, }); @override Widget build(BuildContext context) { return Row( children: [ Icon( ok ? Icons.check_circle : Icons.radio_button_unchecked, color: ok ? Colors.green : Colors.grey, size: 18, ), const SizedBox(width: 8), Text('$label: ', style: const TextStyle(fontWeight: FontWeight.w600)), Text(value), ], ); } }