import 'dart:async'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'client_config.dart'; import 'iop_wire/client_wire_client.dart'; import 'src/integrations/mattermost/mattermost_push_host_integration.dart'; import 'src/integrations/mattermost/mattermost_push_plugin_client.dart'; final _mattermostHost = MattermostPushHostIntegration( pushClient: MattermostPushPluginClient(), ); Future main() => runIopClient(); Future applyFullscreenMode() async { await SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); SystemChrome.setSystemUIOverlayStyle( const SystemUiOverlayStyle( statusBarColor: Colors.transparent, systemNavigationBarColor: Colors.transparent, systemNavigationBarDividerColor: Colors.transparent, ), ); } Future bootstrapIopClient() async { await applyFullscreenMode(); await Firebase.initializeApp(); await _mattermostHost.initialize(); } Future runIopClient() async { WidgetsFlutterBinding.ensureInitialized(); await bootstrapIopClient(); runApp(IopClientApp(mattermostHost: _mattermostHost)); } class IopClientApp extends StatelessWidget { final ClientWireClient? testClient; final MattermostPushHostIntegration? mattermostHost; const IopClientApp({super.key, this.testClient, this.mattermostHost}); @override Widget build(BuildContext context) { return MaterialApp( title: 'IOP Client', debugShowCheckedModeBanner: false, theme: ThemeData.dark(useMaterial3: true).copyWith( colorScheme: ColorScheme.fromSeed( seedColor: const Color(0xFF6366F1), brightness: Brightness.dark, primary: const Color(0xFF6366F1), secondary: const Color(0xFF10B981), ), scaffoldBackgroundColor: const Color(0xFF0F172A), ), home: ClientHomePage( testClient: testClient, mattermostHost: mattermostHost, ), ); } } class ClientHomePage extends StatefulWidget { final ClientWireClient? testClient; final MattermostPushHostIntegration? mattermostHost; const ClientHomePage({super.key, this.testClient, this.mattermostHost}); @override State createState() => _ClientHomePageState(); } class _ClientHomePageState extends State with SingleTickerProviderStateMixin { late AnimationController _pulseController; late Animation _pulseAnimation; String _wireStatus = 'Disconnected'; String _statusMessage = 'Not connected'; ClientWireClient? _client; StreamSubscription? _notificationSubscription; @override void initState() { super.initState(); _pulseController = AnimationController( duration: const Duration(seconds: 2), vsync: this, )..repeat(reverse: true); _pulseAnimation = Tween(begin: 0.6, end: 1.0).animate( CurvedAnimation(parent: _pulseController, curve: Curves.easeInOut), ); // Auto-connect on start WidgetsBinding.instance.addPostFrameCallback((_) { applyFullscreenMode(); _connectWire(); }); final host = widget.mattermostHost; if (host != null) { _notificationSubscription = host.onNotification.listen( _showMattermostNotification, ); } } @override void dispose() { _pulseController.dispose(); _notificationSubscription?.cancel(); _client?.close(); super.dispose(); } void _showMattermostNotification(Map data) { if (data['type'] != 'message' || !mounted) return; final message = data['message'] as String? ?? ''; final channel = data['channel_name'] as String? ?? ''; final sender = data['sender_name'] as String? ?? ''; final content = sender.isNotEmpty ? '[$channel] $sender: $message' : message; ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(content, maxLines: 2, overflow: TextOverflow.ellipsis), duration: const Duration(seconds: 4), behavior: SnackBarBehavior.floating, ), ); } Future _connectWire() async { if (!mounted) return; setState(() { _wireStatus = 'Connecting'; _statusMessage = 'Connecting to ${ClientConfig.controlPlaneWireUrl}...'; }); try { ClientWireClient client; if (widget.testClient != null) { client = widget.testClient!; } else { client = await ClientWireClient.connectToUrl( ClientConfig.controlPlaneWireUrl, ); } _client = client; // Hello handshake final response = await client.hello( clientId: 'client-ui', clientVersion: '1.0.0', ); if (!mounted) return; setState(() { _wireStatus = response.ready ? 'Connected' : 'Error'; _statusMessage = response.ready ? 'Handshake Success: ${response.message} (Protocol: ${response.protocol})' : 'Handshake Rejected: ${response.message}'; }); client.addDisconnectListener((_) { if (!mounted) return; setState(() { _wireStatus = 'Disconnected'; _statusMessage = 'Connection closed by peer.'; _client = null; }); }); } catch (e) { if (!mounted) return; setState(() { _wireStatus = 'Error'; _statusMessage = 'Connection failed: $e'; _client = null; }); } } @override Widget build(BuildContext context) { return Scaffold( body: Container( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [Color(0xFF0F172A), Color(0xFF1E1B4B)], ), ), child: SafeArea( child: Padding( padding: const EdgeInsets.symmetric( horizontal: 24.0, vertical: 32.0, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Top Header Section Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'IOP Client', style: TextStyle( fontSize: 32.0, fontWeight: FontWeight.w800, letterSpacing: -0.5, color: Colors.white, ), ), const SizedBox(height: 4), Text( 'Inference Operations Platform', style: TextStyle( fontSize: 14.0, color: Colors.grey[400], letterSpacing: 0.5, ), ), ], ), // Health Status Indicator AnimatedBuilder( animation: _pulseAnimation, builder: (context, child) { return Container( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 8, ), decoration: BoxDecoration( color: const Color( 0xFF10B981, ).withOpacity(0.15 * _pulseAnimation.value), borderRadius: BorderRadius.circular(20), border: Border.all( color: const Color( 0xFF10B981, ).withOpacity(0.5 * _pulseAnimation.value), width: 1.5, ), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Container( width: 8, height: 8, decoration: const BoxDecoration( color: Color(0xFF10B981), shape: BoxShape.circle, ), ), const SizedBox(width: 8), const Text( 'HEALTH: OK', style: TextStyle( color: Color(0xFF10B981), fontWeight: FontWeight.bold, fontSize: 12, ), ), ], ), ); }, ), ], ), const SizedBox(height: 48), // Dashboard Cards Section Expanded( child: ListView( physics: const BouncingScrollPhysics(), children: [ _buildEndpointCard( title: 'Control Plane Connection', icon: Icons.cloud_queue_rounded, accentColor: const Color(0xFF6366F1), children: [ _buildConfigRow( 'Control Plane HTTP Endpoint', ClientConfig.controlPlaneHttpUrl, ), const SizedBox(height: 12), _buildConfigRow( 'Control Plane Wire WebSocket Endpoint', ClientConfig.controlPlaneWireUrl, ), const SizedBox(height: 16), const Divider(color: Colors.white10), const SizedBox(height: 12), _buildWireStatusSection(), ], ), const SizedBox(height: 24), _buildEndpointCard( title: 'System Information', icon: Icons.info_outline_rounded, accentColor: const Color(0xFF3B82F6), children: [ _buildConfigRow('Framework', 'Flutter Web & Native'), const SizedBox(height: 12), _buildConfigRow('UI Status', 'Scaffold Active'), ], ), ], ), ), // Footer Center( child: Text( '© 2026 Antigravity & Toki Labs. All rights reserved.', style: TextStyle(fontSize: 12, color: Colors.grey[600]), ), ), ], ), ), ), ), ); } Widget _buildWireStatusSection() { Color statusColor; IconData statusIcon; switch (_wireStatus) { case 'Connected': statusColor = const Color(0xFF10B981); statusIcon = Icons.check_circle_outline_rounded; break; case 'Connecting': statusColor = const Color(0xFFF59E0B); statusIcon = Icons.sync_rounded; break; case 'Error': statusColor = const Color(0xFFEF4444); statusIcon = Icons.error_outline_rounded; break; default: statusColor = Colors.grey; statusIcon = Icons.help_outline_rounded; } return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( 'Wire Connection Status', style: TextStyle( fontSize: 12, color: Colors.grey, fontWeight: FontWeight.w500, ), ), Row( children: [ if (_wireStatus == 'Connecting') const SizedBox( width: 12, height: 12, child: CircularProgressIndicator( strokeWidth: 1.5, valueColor: AlwaysStoppedAnimation( Color(0xFFF59E0B), ), ), ) else Icon(statusIcon, color: statusColor, size: 16), const SizedBox(width: 6), Text( _wireStatus, style: TextStyle( fontSize: 14, color: statusColor, fontWeight: FontWeight.bold, ), ), ], ), ], ), const SizedBox(height: 8), Container( width: double.infinity, padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.black12, borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.white.withOpacity(0.05)), ), child: Text( _statusMessage, style: const TextStyle( fontSize: 13, fontFamily: 'monospace', color: Colors.white70, ), ), ), const SizedBox(height: 12), ElevatedButton.icon( onPressed: _wireStatus == 'Connecting' ? null : _connectWire, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF6366F1), foregroundColor: Colors.white, disabledBackgroundColor: const Color(0xFF6366F1).withOpacity(0.5), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), ), icon: const Icon(Icons.bolt_rounded, size: 16), label: const Text('Connect & Handshake'), ), ], ); } Widget _buildEndpointCard({ required String title, required IconData icon, required Color accentColor, required List children, }) { return Container( decoration: BoxDecoration( color: const Color(0xFF1E293B).withOpacity(0.6), borderRadius: BorderRadius.circular(24), border: Border.all(color: Colors.white.withOpacity(0.08), width: 1), ), child: ClipRRect( borderRadius: BorderRadius.circular(24), child: Padding( padding: const EdgeInsets.all(24.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: accentColor.withOpacity(0.15), borderRadius: BorderRadius.circular(12), ), child: Icon(icon, color: accentColor, size: 24), ), const SizedBox(width: 16), Text( title, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white, ), ), ], ), const SizedBox(height: 20), const Divider(color: Colors.white10), const SizedBox(height: 12), ...children, ], ), ), ), ); } Widget _buildConfigRow(String label, String value) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: TextStyle( fontSize: 12, color: Colors.grey[500], fontWeight: FontWeight.w500, ), ), const SizedBox(height: 4), SelectableText( value, style: const TextStyle( fontSize: 14, fontFamily: 'monospace', color: Colors.white70, fontWeight: FontWeight.w600, ), ), ], ); } }