import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:sqlite3/sqlite3.dart'; import 'package:xp_nix/src/monitors/productivity_monitor.dart'; import 'package:xp_nix/src/config/config_manager.dart'; import 'package:xp_nix/src/logging/logger.dart'; import 'package:xp_nix/src/web/dashboard_server.dart'; import 'package:xp_nix/src/database/database_manager.dart'; import 'package:xp_nix/src/detectors/idle_monitor.dart'; import 'package:xp_nix/src/providers/system_time_provider.dart'; import 'package:xp_nix/src/enhancers/hyprland_enhancer.dart'; import 'package:xp_nix/src/build/dashboard_builder.dart'; late final Database _db; late final IdleMonitor _idleMonitor; late final SystemTimeProvider _timeProvider; late final HyprlandEnhancer _desktopEnhancer; late final ProductivityMonitor _monitor; late final DashboardServer _dashboardServer; // Enhanced main function with interactive commands and one-shot mode void main(List args) async { // Parse command line arguments String dbPath = 'productivity_tracker.db'; int port = 8080; for (int i = 0; i < args.length; i++) { switch (args[i]) { case '--db': if (i + 1 < args.length) { dbPath = args[i + 1]; i++; // Skip next argument as it's the db path } else { print('Error: --db flag requires a database path'); exit(1); } break; case '--port': if (i + 1 < args.length) { port = int.tryParse(args[i + 1]) ?? 8080; i++; // Skip next argument as it's the port number } else { print('Error: --port flag requires a port number'); exit(1); } break; case '--help': case '-h': print(''' XP Nix Server Usage: dart xp_nix.dart [options] Options: --db PATH Database file path (default: productivity_tracker.db) --port PORT Server port (default: 8080) --help, -h Show this help message Examples: dart xp_nix.dart dart xp_nix.dart --db test_data.db --port 8081 '''); exit(0); } } print('🗄️ Using database: $dbPath'); print('🌐 Starting server on port: $port'); // Initialize logging system await Logger.instance.initialize(level: LogLevel.info, logDirectory: 'logs', maxFileSizeMB: 10, maxFiles: 5); // Initialize configuration manager await ConfigManager.instance.initialize(); _db = sqlite3.open(dbPath); // Create production dependencies _idleMonitor = IdleMonitor(); _timeProvider = SystemTimeProvider(); _desktopEnhancer = HyprlandEnhancer(); // Create monitor with dependency injection _monitor = ProductivityMonitor( db: _db, idleMonitor: _idleMonitor, timeProvider: _timeProvider, desktopEnhancer: _desktopEnhancer, // No activity detector provided - will use legacy polling mode ); _dashboardServer = DashboardServer.withDatabase(DatabaseManager(_db)); ProcessSignal.sigint.watch().listen((_) async { Logger.info('Shutting down XP Nix...'); print('\nShutting down...'); _quit(); }); // Start the dashboard server try { await _dashboardServer.start(port); Logger.info('Dashboard available at: ${_dashboardServer.dashboardUrl}'); print('🌐 Dashboard available at: ${_dashboardServer.dashboardUrl}'); } catch (e) { Logger.error('Failed to start dashboard server: $e'); print('⚠️ Dashboard server failed to start: $e'); _quit(); } _monitor.start(); _monitor.printDetailedStats(); // Add command listener for manual controls stdin.transform(utf8.decoder).transform(LineSplitter()).listen((line) { final parts = line.trim().split(' '); final command = parts[0].toLowerCase(); switch (command) { case 'stats': _monitor.printDetailedStats(); break; case 'test': if (parts.length > 1) { final level = int.tryParse(parts[1]) ?? 1; _monitor.testTheme(level); } break; case 'restore': _monitor.restoreDesktop(); break; case 'refresh': _monitor.refreshConfig(); break; case 'build': _handleBuildCommand(); break; case 'help': print(''' Available commands: - stats: Show current productivity stats - test [level]: Test theme for specific level - restore: Restore desktop backup - refresh: Refresh base config from current system config - build: Build Flutter dashboard and copy to static files - help: Show this help '''); break; } }); print('💡 Type "help" for available commands'); // Keep running and show stats periodically while (true) { await Future.delayed(Duration(seconds: 1)); if (DateTime.now().second == 0 && DateTime.now().minute % 10 == 0) { _monitor.printDetailedStats(); } } } /// Handles the build command to rebuild the Flutter dashboard void _handleBuildCommand() async { print('🚀 Starting dashboard build process...'); // Check if Flutter is available if (!await DashboardBuilder.checkFlutterAvailable()) { print('❌ Flutter is not available in the system PATH'); print(' Please ensure Flutter is installed and available in your PATH'); return; } // Build the dashboard final success = await DashboardBuilder.buildDashboard(); if (success) { print('🎉 Dashboard build completed successfully!'); print(' The server is now serving the updated Flutter dashboard'); } else { print('❌ Dashboard build failed. Check the logs for more details.'); } } Future _quit() async { _monitor.stop(); await _dashboardServer.stop(); await Logger.instance.dispose(); _db.dispose(); exit(0); }