1302 lines
		
	
	
		
			50 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			1302 lines
		
	
	
		
			50 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
//import 'dart:io';
 | 
						|
//
 | 
						|
//import 'package:flutter/material.dart';
 | 
						|
//import 'package:rimworld_modman/logger.dart';
 | 
						|
//import 'package:rimworld_modman/mod.dart';
 | 
						|
//import 'package:rimworld_modman/mod_list.dart';
 | 
						|
//
 | 
						|
//// Constants for file paths
 | 
						|
//final String root =
 | 
						|
//    Platform.isWindows
 | 
						|
//        ? r'C:/Users/Administrator/Seafile/Games-RimWorld'
 | 
						|
//        : '~/Library/Application Support/RimWorld';
 | 
						|
//final String modsRoot = Platform.isWindows ? '$root/294100' : '$root/Mods';
 | 
						|
//final String configRoot =
 | 
						|
//    Platform.isWindows
 | 
						|
//        ? '$root/AppData/RimWorld by Ludeon Studios/Config'
 | 
						|
//        : '$root/Config';
 | 
						|
//final String configPath = '$configRoot/ModsConfig.xml';
 | 
						|
//final String logsPath = '$root/ModManager';
 | 
						|
//
 | 
						|
//late ModList modManager;
 | 
						|
//
 | 
						|
//void main() {
 | 
						|
//  WidgetsFlutterBinding.ensureInitialized();
 | 
						|
//
 | 
						|
//  // Get a reference to the logger (now auto-initializes)
 | 
						|
//  final logger = Logger.instance;
 | 
						|
//  logger.info('RimWorld Mod Manager starting...');
 | 
						|
//
 | 
						|
//  // Initialize the mod manager
 | 
						|
//  modManager = ModList(modsPath: modsRoot, configPath: configPath);
 | 
						|
//
 | 
						|
//  // Start the app
 | 
						|
//  runApp(const RimWorldModManager());
 | 
						|
//}
 | 
						|
//
 | 
						|
//class RimWorldModManager extends StatelessWidget {
 | 
						|
//  const RimWorldModManager({super.key});
 | 
						|
//
 | 
						|
//  @override
 | 
						|
//  Widget build(BuildContext context) {
 | 
						|
//    return MaterialApp(
 | 
						|
//      title: 'RimWorld Mod Manager',
 | 
						|
//      theme: ThemeData.dark().copyWith(
 | 
						|
//        primaryColor: const Color(0xFF3D4A59),
 | 
						|
//        colorScheme: ColorScheme.fromSeed(
 | 
						|
//          seedColor: const Color(0xFF3D4A59),
 | 
						|
//          brightness: Brightness.dark,
 | 
						|
//        ),
 | 
						|
//        scaffoldBackgroundColor: const Color(0xFF1E262F),
 | 
						|
//        cardColor: const Color(0xFF2A3440),
 | 
						|
//        appBarTheme: const AppBarTheme(
 | 
						|
//          backgroundColor: Color(0xFF2A3440),
 | 
						|
//          foregroundColor: Colors.white,
 | 
						|
//        ),
 | 
						|
//      ),
 | 
						|
//      home: const ModManagerHomePage(),
 | 
						|
//    );
 | 
						|
//  }
 | 
						|
//}
 | 
						|
//
 | 
						|
//class ModManagerHomePage extends StatefulWidget {
 | 
						|
//  const ModManagerHomePage({super.key});
 | 
						|
//
 | 
						|
//  @override
 | 
						|
//  State<ModManagerHomePage> createState() => _ModManagerHomePageState();
 | 
						|
//}
 | 
						|
//
 | 
						|
//class _ModManagerHomePageState extends State<ModManagerHomePage> {
 | 
						|
//  int _selectedIndex = 0;
 | 
						|
//
 | 
						|
//  final List<Widget> _pages = [
 | 
						|
//    const ModManagerPage(),
 | 
						|
//    const TroubleshootingPage(),
 | 
						|
//  ];
 | 
						|
//
 | 
						|
//  @override
 | 
						|
//  Widget build(BuildContext context) {
 | 
						|
//    return Scaffold(
 | 
						|
//      appBar: AppBar(title: const Text('RimWorld Mod Manager')),
 | 
						|
//      body: _pages[_selectedIndex],
 | 
						|
//      bottomNavigationBar: BottomNavigationBar(
 | 
						|
//        currentIndex: _selectedIndex,
 | 
						|
//        onTap: (index) {
 | 
						|
//          setState(() {
 | 
						|
//            _selectedIndex = index;
 | 
						|
//          });
 | 
						|
//        },
 | 
						|
//        items: const [
 | 
						|
//          BottomNavigationBarItem(icon: Icon(Icons.extension), label: 'Mods'),
 | 
						|
//          BottomNavigationBarItem(
 | 
						|
//            icon: Icon(Icons.build),
 | 
						|
//            label: 'Troubleshoot',
 | 
						|
//          ),
 | 
						|
//        ],
 | 
						|
//      ),
 | 
						|
//    );
 | 
						|
//  }
 | 
						|
//}
 | 
						|
//
 | 
						|
//// Combined page for mod management with two-panel layout
 | 
						|
//class ModManagerPage extends StatefulWidget {
 | 
						|
//  const ModManagerPage({super.key});
 | 
						|
//
 | 
						|
//  @override
 | 
						|
//  State<ModManagerPage> createState() => _ModManagerPageState();
 | 
						|
//}
 | 
						|
//
 | 
						|
//class _ModManagerPageState extends State<ModManagerPage> {
 | 
						|
//  // For all available mods (left panel)
 | 
						|
//  List<Mod> _availableMods = [];
 | 
						|
//
 | 
						|
//  // For active mods (right panel)
 | 
						|
//  List<Mod> _activeMods = [];
 | 
						|
//
 | 
						|
//  bool _isLoading = false;
 | 
						|
//  String _statusMessage = '';
 | 
						|
//  int _totalModsFound = 0;
 | 
						|
//  bool _skipFileCount = false;
 | 
						|
//  bool _hasCycles = false;
 | 
						|
//  List<String>? _cycleInfo;
 | 
						|
//  List<List<String>> _incompatibleMods = [];
 | 
						|
//  List<String>? _loadOrderErrors;
 | 
						|
//
 | 
						|
//  final TextEditingController _searchController = TextEditingController();
 | 
						|
//  String _searchQuery = '';
 | 
						|
//
 | 
						|
//  @override
 | 
						|
//  void initState() {
 | 
						|
//    super.initState();
 | 
						|
//    // Check if mods are already loaded
 | 
						|
//    if (modManager.mods.isNotEmpty) {
 | 
						|
//      _loadModsFromGlobalState();
 | 
						|
//    }
 | 
						|
//
 | 
						|
//    _searchController.addListener(() {
 | 
						|
//      setState(() {
 | 
						|
//        _searchQuery = _searchController.text.toLowerCase();
 | 
						|
//      });
 | 
						|
//    });
 | 
						|
//  }
 | 
						|
//
 | 
						|
//  @override
 | 
						|
//  void dispose() {
 | 
						|
//    _searchController.dispose();
 | 
						|
//    super.dispose();
 | 
						|
//  }
 | 
						|
//
 | 
						|
//  void _loadModsFromGlobalState() {
 | 
						|
//    setState(() {
 | 
						|
//      // Get all mods for the left panel (sorted alphabetically)
 | 
						|
//      _availableMods = modManager.mods.values.toList();
 | 
						|
//      _availableMods.sort((a, b) => a.name.compareTo(b.name));
 | 
						|
//
 | 
						|
//      // Get active mods for the right panel (in load order)
 | 
						|
//      _activeMods = modManager.mods.values.where((m) => m.enabled).toList();
 | 
						|
//      _isLoading = false;
 | 
						|
//      _statusMessage = 'Loaded ${_availableMods.length} mods';
 | 
						|
//      _totalModsFound = _availableMods.length;
 | 
						|
//    });
 | 
						|
//  }
 | 
						|
//
 | 
						|
//  @override
 | 
						|
//  Widget build(BuildContext context) {
 | 
						|
//    return Scaffold(
 | 
						|
//      body:
 | 
						|
//          _isLoading && _availableMods.isEmpty
 | 
						|
//              ? _buildLoadingView()
 | 
						|
//              : _availableMods.isEmpty
 | 
						|
//              ? _buildEmptyState()
 | 
						|
//              : _buildSplitView(),
 | 
						|
//    );
 | 
						|
//  }
 | 
						|
//
 | 
						|
//  Widget _buildLoadingView() {
 | 
						|
//    return Center(
 | 
						|
//      child: Column(
 | 
						|
//        mainAxisAlignment: MainAxisAlignment.center,
 | 
						|
//        children: [
 | 
						|
//          const CircularProgressIndicator(),
 | 
						|
//          const SizedBox(height: 16),
 | 
						|
//          Text(
 | 
						|
//            _statusMessage,
 | 
						|
//            style: Theme.of(context).textTheme.bodyMedium,
 | 
						|
//            textAlign: TextAlign.center,
 | 
						|
//          ),
 | 
						|
//        ],
 | 
						|
//      ),
 | 
						|
//    );
 | 
						|
//  }
 | 
						|
//
 | 
						|
//  Widget _buildEmptyState() {
 | 
						|
//    return Center(
 | 
						|
//      child: Column(
 | 
						|
//        mainAxisAlignment: MainAxisAlignment.center,
 | 
						|
//        children: [
 | 
						|
//          const Icon(Icons.extension, size: 64),
 | 
						|
//          const SizedBox(height: 16),
 | 
						|
//          Text(
 | 
						|
//            'Mod Manager',
 | 
						|
//            style: Theme.of(context).textTheme.headlineMedium,
 | 
						|
//          ),
 | 
						|
//          const SizedBox(height: 16),
 | 
						|
//          Text(
 | 
						|
//            'Ready to scan for RimWorld mods.',
 | 
						|
//            style: Theme.of(context).textTheme.bodyLarge,
 | 
						|
//          ),
 | 
						|
//          const SizedBox(height: 12),
 | 
						|
//          Row(
 | 
						|
//            mainAxisSize: MainAxisSize.min,
 | 
						|
//            children: [
 | 
						|
//              Checkbox(
 | 
						|
//                value: _skipFileCount,
 | 
						|
//                onChanged: (value) {
 | 
						|
//                  setState(() {
 | 
						|
//                    _skipFileCount = value ?? true;
 | 
						|
//                  });
 | 
						|
//                },
 | 
						|
//              ),
 | 
						|
//              const Text('Skip file counting (faster loading)'),
 | 
						|
//            ],
 | 
						|
//          ),
 | 
						|
//          const SizedBox(height: 24),
 | 
						|
//          ElevatedButton(
 | 
						|
//            onPressed: _startLoadingMods,
 | 
						|
//            child: const Text('Scan for Mods'),
 | 
						|
//          ),
 | 
						|
//        ],
 | 
						|
//      ),
 | 
						|
//    );
 | 
						|
//  }
 | 
						|
//
 | 
						|
//  Widget _buildSplitView() {
 | 
						|
//    // Filter both available and active mods based on search query
 | 
						|
//    final filteredAvailableMods =
 | 
						|
//        _searchQuery.isEmpty
 | 
						|
//            ? _availableMods
 | 
						|
//            : _availableMods
 | 
						|
//                .where(
 | 
						|
//                  (mod) =>
 | 
						|
//                      mod.name.toLowerCase().contains(_searchQuery) ||
 | 
						|
//                      mod.id.toLowerCase().contains(_searchQuery),
 | 
						|
//                )
 | 
						|
//                .toList();
 | 
						|
//
 | 
						|
//    final filteredActiveMods =
 | 
						|
//        _searchQuery.isEmpty
 | 
						|
//            ? _activeMods
 | 
						|
//            : _activeMods
 | 
						|
//                .where(
 | 
						|
//                  (mod) =>
 | 
						|
//                      mod.name.toLowerCase().contains(_searchQuery) ||
 | 
						|
//                      mod.id.toLowerCase().contains(_searchQuery),
 | 
						|
//                )
 | 
						|
//                .toList();
 | 
						|
//
 | 
						|
//    return Column(
 | 
						|
//      children: [
 | 
						|
//        Padding(
 | 
						|
//          padding: const EdgeInsets.all(8.0),
 | 
						|
//          child: Row(
 | 
						|
//            children: [
 | 
						|
//              // Search field
 | 
						|
//              Expanded(
 | 
						|
//                child: TextField(
 | 
						|
//                  controller: _searchController,
 | 
						|
//                  decoration: InputDecoration(
 | 
						|
//                    hintText: 'Search mods by name or ID...',
 | 
						|
//                    prefixIcon: const Icon(Icons.search),
 | 
						|
//                    border: OutlineInputBorder(
 | 
						|
//                      borderRadius: BorderRadius.circular(8.0),
 | 
						|
//                    ),
 | 
						|
//                    suffixIcon:
 | 
						|
//                        _searchQuery.isNotEmpty
 | 
						|
//                            ? IconButton(
 | 
						|
//                              icon: const Icon(Icons.clear),
 | 
						|
//                              onPressed: () {
 | 
						|
//                                _searchController.clear();
 | 
						|
//                              },
 | 
						|
//                            )
 | 
						|
//                            : null,
 | 
						|
//                  ),
 | 
						|
//                ),
 | 
						|
//              ),
 | 
						|
//              const SizedBox(width: 8),
 | 
						|
//              // Reload button
 | 
						|
//              IconButton(
 | 
						|
//                icon: const Icon(Icons.refresh),
 | 
						|
//                tooltip: 'Reload mods',
 | 
						|
//                onPressed: _startLoadingMods,
 | 
						|
//              ),
 | 
						|
//              const SizedBox(width: 8),
 | 
						|
//              // Load Dependencies button
 | 
						|
//              Tooltip(
 | 
						|
//                message:
 | 
						|
//                    'Automatically load missing dependencies for active mods',
 | 
						|
//                child: ElevatedButton.icon(
 | 
						|
//                  icon: const Icon(Icons.download),
 | 
						|
//                  label: const Text('Load Deps'),
 | 
						|
//                  onPressed: _loadRequiredDependencies,
 | 
						|
//                ),
 | 
						|
//              ),
 | 
						|
//              const SizedBox(width: 8),
 | 
						|
//              // Auto-sort button
 | 
						|
//              ElevatedButton.icon(
 | 
						|
//                icon: const Icon(Icons.sort),
 | 
						|
//                label: const Text('Auto-Sort'),
 | 
						|
//                onPressed: _sortActiveMods,
 | 
						|
//              ),
 | 
						|
//              const SizedBox(width: 8),
 | 
						|
//              // Save button
 | 
						|
//              ElevatedButton.icon(
 | 
						|
//                icon: const Icon(Icons.save),
 | 
						|
//                label: const Text('Save'),
 | 
						|
//                onPressed: _saveModOrder,
 | 
						|
//              ),
 | 
						|
//            ],
 | 
						|
//          ),
 | 
						|
//        ),
 | 
						|
//
 | 
						|
//        // Status message
 | 
						|
//        if (!_isLoading && _statusMessage.isNotEmpty)
 | 
						|
//          Padding(
 | 
						|
//            padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
 | 
						|
//            child: Text(
 | 
						|
//              _statusMessage,
 | 
						|
//              style: TextStyle(
 | 
						|
//                color:
 | 
						|
//                    _hasCycles || _incompatibleMods.isNotEmpty
 | 
						|
//                        ? Colors.orange
 | 
						|
//                        : Colors.green,
 | 
						|
//              ),
 | 
						|
//            ),
 | 
						|
//          ),
 | 
						|
//
 | 
						|
//        // Error display section
 | 
						|
//        if (_hasCycles ||
 | 
						|
//            _incompatibleMods.isNotEmpty ||
 | 
						|
//            (_loadOrderErrors?.isNotEmpty ?? false))
 | 
						|
//          Container(
 | 
						|
//            margin: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
 | 
						|
//            padding: const EdgeInsets.all(8.0),
 | 
						|
//            decoration: BoxDecoration(
 | 
						|
//              color: Colors.red.shade900.withOpacity(0.3),
 | 
						|
//              borderRadius: BorderRadius.circular(4.0),
 | 
						|
//              border: Border.all(color: Colors.red.shade800),
 | 
						|
//            ),
 | 
						|
//            child: Column(
 | 
						|
//              crossAxisAlignment: CrossAxisAlignment.start,
 | 
						|
//              children: [
 | 
						|
//                // Cycle warnings
 | 
						|
//                if (_hasCycles && _cycleInfo != null)
 | 
						|
//                  Padding(
 | 
						|
//                    padding: const EdgeInsets.only(bottom: 4.0),
 | 
						|
//                    child: Row(
 | 
						|
//                      children: [
 | 
						|
//                        const Icon(Icons.loop, color: Colors.orange, size: 16),
 | 
						|
//                        const SizedBox(width: 4),
 | 
						|
//                        Expanded(
 | 
						|
//                          child: Text(
 | 
						|
//                            'Dependency cycle detected: ${_cycleInfo!.join(" -> ")}',
 | 
						|
//                            style: const TextStyle(color: Colors.orange),
 | 
						|
//                          ),
 | 
						|
//                        ),
 | 
						|
//                      ],
 | 
						|
//                    ),
 | 
						|
//                  ),
 | 
						|
//
 | 
						|
//                // Incompatible mod warnings
 | 
						|
//                if (_incompatibleMods.isNotEmpty)
 | 
						|
//                  Padding(
 | 
						|
//                    padding: const EdgeInsets.only(bottom: 4.0),
 | 
						|
//                    child: Row(
 | 
						|
//                      crossAxisAlignment: CrossAxisAlignment.start,
 | 
						|
//                      children: [
 | 
						|
//                        const Icon(
 | 
						|
//                          Icons.warning,
 | 
						|
//                          color: Colors.orange,
 | 
						|
//                          size: 16,
 | 
						|
//                        ),
 | 
						|
//                        const SizedBox(width: 4),
 | 
						|
//                        Expanded(
 | 
						|
//                          child: Column(
 | 
						|
//                            crossAxisAlignment: CrossAxisAlignment.start,
 | 
						|
//                            children: [
 | 
						|
//                              Text(
 | 
						|
//                                '${_incompatibleMods.length} incompatible mod pairs:',
 | 
						|
//                                style: const TextStyle(color: Colors.orange),
 | 
						|
//                              ),
 | 
						|
//                              if (_incompatibleMods.length <= 3)
 | 
						|
//                                ...List.generate(_incompatibleMods.length, (
 | 
						|
//                                  index,
 | 
						|
//                                ) {
 | 
						|
//                                  final pair = _incompatibleMods[index];
 | 
						|
//                                  final mod1 =
 | 
						|
//                                      modManager.mods[pair[0]]?.name ?? pair[0];
 | 
						|
//                                  final mod2 =
 | 
						|
//                                      modManager.mods[pair[1]]?.name ?? pair[1];
 | 
						|
//                                  return Padding(
 | 
						|
//                                    padding: const EdgeInsets.only(
 | 
						|
//                                      left: 12.0,
 | 
						|
//                                      top: 2.0,
 | 
						|
//                                    ),
 | 
						|
//                                    child: Text(
 | 
						|
//                                      '• $mod1 ↔ $mod2',
 | 
						|
//                                      style: TextStyle(
 | 
						|
//                                        color: Colors.orange.shade300,
 | 
						|
//                                        fontSize: 12,
 | 
						|
//                                      ),
 | 
						|
//                                    ),
 | 
						|
//                                  );
 | 
						|
//                                }),
 | 
						|
//                            ],
 | 
						|
//                          ),
 | 
						|
//                        ),
 | 
						|
//                      ],
 | 
						|
//                    ),
 | 
						|
//                  ),
 | 
						|
//
 | 
						|
//                // Other errors (missing dependencies, etc.)
 | 
						|
//                if (_loadOrderErrors?.isNotEmpty ?? false)
 | 
						|
//                  Row(
 | 
						|
//                    crossAxisAlignment: CrossAxisAlignment.start,
 | 
						|
//                    children: [
 | 
						|
//                      const Icon(
 | 
						|
//                        Icons.error_outline,
 | 
						|
//                        color: Colors.red,
 | 
						|
//                        size: 16,
 | 
						|
//                      ),
 | 
						|
//                      const SizedBox(width: 4),
 | 
						|
//                      Expanded(
 | 
						|
//                        child: Column(
 | 
						|
//                          crossAxisAlignment: CrossAxisAlignment.start,
 | 
						|
//                          children: [
 | 
						|
//                            const Text(
 | 
						|
//                              'Dependency errors:',
 | 
						|
//                              style: TextStyle(color: Colors.red),
 | 
						|
//                            ),
 | 
						|
//                            ...List.generate(
 | 
						|
//                              _loadOrderErrors!.length > 5
 | 
						|
//                                  ? 5
 | 
						|
//                                  : _loadOrderErrors!.length,
 | 
						|
//                              (index) => Padding(
 | 
						|
//                                padding: const EdgeInsets.only(
 | 
						|
//                                  left: 12.0,
 | 
						|
//                                  top: 2.0,
 | 
						|
//                                ),
 | 
						|
//                                child: Text(
 | 
						|
//                                  '• ${_loadOrderErrors![index]}',
 | 
						|
//                                  style: TextStyle(
 | 
						|
//                                    color: Colors.red.shade300,
 | 
						|
//                                    fontSize: 12,
 | 
						|
//                                  ),
 | 
						|
//                                ),
 | 
						|
//                              ),
 | 
						|
//                            ),
 | 
						|
//                            if (_loadOrderErrors!.length > 5)
 | 
						|
//                              Padding(
 | 
						|
//                                padding: const EdgeInsets.only(
 | 
						|
//                                  left: 12.0,
 | 
						|
//                                  top: 4.0,
 | 
						|
//                                ),
 | 
						|
//                                child: Text(
 | 
						|
//                                  '(${_loadOrderErrors!.length - 5} more errors...)',
 | 
						|
//                                  style: TextStyle(
 | 
						|
//                                    color: Colors.red.shade300,
 | 
						|
//                                    fontSize: 12,
 | 
						|
//                                    fontStyle: FontStyle.italic,
 | 
						|
//                                  ),
 | 
						|
//                                ),
 | 
						|
//                              ),
 | 
						|
//                          ],
 | 
						|
//                        ),
 | 
						|
//                      ),
 | 
						|
//                    ],
 | 
						|
//                  ),
 | 
						|
//              ],
 | 
						|
//            ),
 | 
						|
//          ),
 | 
						|
//
 | 
						|
//        // Main split view
 | 
						|
//        Expanded(
 | 
						|
//          child: Row(
 | 
						|
//            children: [
 | 
						|
//              // LEFT PANEL - All available mods (alphabetical)
 | 
						|
//              Expanded(
 | 
						|
//                child: Card(
 | 
						|
//                  margin: const EdgeInsets.all(8.0),
 | 
						|
//                  child: Column(
 | 
						|
//                    crossAxisAlignment: CrossAxisAlignment.stretch,
 | 
						|
//                    children: [
 | 
						|
//                      Container(
 | 
						|
//                        color: Theme.of(context).primaryColor,
 | 
						|
//                        padding: const EdgeInsets.all(8.0),
 | 
						|
//                        child: Text(
 | 
						|
//                          'Available Mods (${filteredAvailableMods.length}${_searchQuery.isNotEmpty ? '/${_availableMods.length}' : ''})',
 | 
						|
//                          style: const TextStyle(fontWeight: FontWeight.bold),
 | 
						|
//                          textAlign: TextAlign.center,
 | 
						|
//                        ),
 | 
						|
//                      ),
 | 
						|
//                      if (_searchQuery.isNotEmpty)
 | 
						|
//                        Padding(
 | 
						|
//                          padding: const EdgeInsets.all(4.0),
 | 
						|
//                          child: Text(
 | 
						|
//                            'Searching: "$_searchQuery"',
 | 
						|
//                            style: TextStyle(
 | 
						|
//                              fontSize: 12,
 | 
						|
//                              fontStyle: FontStyle.italic,
 | 
						|
//                              color: Colors.grey.shade400,
 | 
						|
//                            ),
 | 
						|
//                            textAlign: TextAlign.center,
 | 
						|
//                          ),
 | 
						|
//                        ),
 | 
						|
//                      Expanded(
 | 
						|
//                        child: ListView.builder(
 | 
						|
//                          itemCount: filteredAvailableMods.length,
 | 
						|
//                          itemBuilder: (context, index) {
 | 
						|
//                            final mod = filteredAvailableMods[index];
 | 
						|
//                            final isActive = mod.enabled;
 | 
						|
//
 | 
						|
//                            return GestureDetector(
 | 
						|
//                              onDoubleTap: () => _toggleModActive(mod),
 | 
						|
//                              child: ListTile(
 | 
						|
//                                title: Text(
 | 
						|
//                                  mod.name,
 | 
						|
//                                  style: TextStyle(
 | 
						|
//                                    color:
 | 
						|
//                                        isActive ? Colors.green : Colors.white,
 | 
						|
//                                  ),
 | 
						|
//                                ),
 | 
						|
//                                subtitle: Text(
 | 
						|
//                                  'ID: ${mod.id}\nSize: ${mod.size} files',
 | 
						|
//                                  style: Theme.of(context).textTheme.bodySmall,
 | 
						|
//                                ),
 | 
						|
//                                trailing: Row(
 | 
						|
//                                  mainAxisSize: MainAxisSize.min,
 | 
						|
//                                  children: [
 | 
						|
//                                    if (mod.isBaseGame)
 | 
						|
//                                      const Tooltip(
 | 
						|
//                                        message: 'Base Game',
 | 
						|
//                                        child: Icon(
 | 
						|
//                                          Icons.home,
 | 
						|
//                                          color: Colors.blue,
 | 
						|
//                                          size: 24,
 | 
						|
//                                        ),
 | 
						|
//                                      ),
 | 
						|
//                                    if (mod.isExpansion)
 | 
						|
//                                      const Tooltip(
 | 
						|
//                                        message: 'Expansion',
 | 
						|
//                                        child: Icon(
 | 
						|
//                                          Icons.star,
 | 
						|
//                                          color: Colors.yellow,
 | 
						|
//                                          size: 24,
 | 
						|
//                                        ),
 | 
						|
//                                      ),
 | 
						|
//                                    const SizedBox(width: 4),
 | 
						|
//                                    if (mod.dependencies.isNotEmpty)
 | 
						|
//                                      Tooltip(
 | 
						|
//                                        message:
 | 
						|
//                                            'Dependencies:\n${mod.dependencies.join('\n')}',
 | 
						|
//                                        child: const Icon(
 | 
						|
//                                          Icons.link,
 | 
						|
//                                          color: Colors.orange,
 | 
						|
//                                          size: 24,
 | 
						|
//                                        ),
 | 
						|
//                                      ),
 | 
						|
//                                    if (mod.loadAfter.isNotEmpty)
 | 
						|
//                                      Tooltip(
 | 
						|
//                                        message:
 | 
						|
//                                            'Loads after:\n${mod.loadAfter.join('\n')}',
 | 
						|
//                                        child: const Icon(
 | 
						|
//                                          Icons.arrow_downward,
 | 
						|
//                                          color: Colors.blue,
 | 
						|
//                                          size: 24,
 | 
						|
//                                        ),
 | 
						|
//                                      ),
 | 
						|
//                                    if (mod.loadBefore.isNotEmpty)
 | 
						|
//                                      Tooltip(
 | 
						|
//                                        message:
 | 
						|
//                                            'Loads before:\n${mod.loadBefore.join('\n')}',
 | 
						|
//                                        child: const Icon(
 | 
						|
//                                          Icons.arrow_upward,
 | 
						|
//                                          color: Colors.green,
 | 
						|
//                                          size: 24,
 | 
						|
//                                        ),
 | 
						|
//                                      ),
 | 
						|
//                                  ],
 | 
						|
//                                ),
 | 
						|
//                                onTap: () {
 | 
						|
//                                  // Show mod details in future
 | 
						|
//                                },
 | 
						|
//                              ),
 | 
						|
//                            );
 | 
						|
//                          },
 | 
						|
//                        ),
 | 
						|
//                      ),
 | 
						|
//                    ],
 | 
						|
//                  ),
 | 
						|
//                ),
 | 
						|
//              ),
 | 
						|
//
 | 
						|
//              // RIGHT PANEL - Active mods (load order)
 | 
						|
//              Expanded(
 | 
						|
//                child: Card(
 | 
						|
//                  margin: const EdgeInsets.all(8.0),
 | 
						|
//                  child: Column(
 | 
						|
//                    crossAxisAlignment: CrossAxisAlignment.stretch,
 | 
						|
//                    children: [
 | 
						|
//                      Container(
 | 
						|
//                        color: Theme.of(context).primaryColor,
 | 
						|
//                        padding: const EdgeInsets.all(8.0),
 | 
						|
//                        child: Text(
 | 
						|
//                          'Active Mods (${filteredActiveMods.length}${_searchQuery.isNotEmpty ? '/${_activeMods.length}' : ''})',
 | 
						|
//                          style: const TextStyle(fontWeight: FontWeight.bold),
 | 
						|
//                          textAlign: TextAlign.center,
 | 
						|
//                        ),
 | 
						|
//                      ),
 | 
						|
//                      Padding(
 | 
						|
//                        padding: const EdgeInsets.all(8.0),
 | 
						|
//                        child: Text(
 | 
						|
//                          _searchQuery.isNotEmpty
 | 
						|
//                              ? 'Searching: "$_searchQuery"'
 | 
						|
//                              : 'Larger mods are prioritized during auto-sorting.',
 | 
						|
//                          style: TextStyle(
 | 
						|
//                            fontSize: 12,
 | 
						|
//                            color: Colors.grey.shade400,
 | 
						|
//                            fontStyle: FontStyle.italic,
 | 
						|
//                          ),
 | 
						|
//                          textAlign: TextAlign.center,
 | 
						|
//                        ),
 | 
						|
//                      ),
 | 
						|
//                      Expanded(
 | 
						|
//                        child: ListView.builder(
 | 
						|
//                          itemCount: filteredActiveMods.length,
 | 
						|
//                          itemBuilder: (context, index) {
 | 
						|
//                            final mod = filteredActiveMods[index];
 | 
						|
//                            // Find the actual position in the complete active mods list (for correct load order)
 | 
						|
//                            final actualLoadOrderPosition =
 | 
						|
//                                _activeMods.indexWhere((m) => m.id == mod.id) +
 | 
						|
//                                1;
 | 
						|
//
 | 
						|
//                            return GestureDetector(
 | 
						|
//                              onDoubleTap: () {
 | 
						|
//                                // Don't allow deactivating base game or expansions
 | 
						|
//                                if (!mod.isBaseGame && !mod.isExpansion) {
 | 
						|
//                                  _toggleModActive(mod);
 | 
						|
//                                } else {
 | 
						|
//                                  ScaffoldMessenger.of(context).showSnackBar(
 | 
						|
//                                    const SnackBar(
 | 
						|
//                                      content: Text(
 | 
						|
//                                        'Core game and expansions cannot be deactivated',
 | 
						|
//                                      ),
 | 
						|
//                                      backgroundColor: Colors.orange,
 | 
						|
//                                    ),
 | 
						|
//                                  );
 | 
						|
//                                }
 | 
						|
//                              },
 | 
						|
//                              child: Card(
 | 
						|
//                                margin: const EdgeInsets.symmetric(
 | 
						|
//                                  horizontal: 8.0,
 | 
						|
//                                  vertical: 4.0,
 | 
						|
//                                ),
 | 
						|
//                                child: ListTile(
 | 
						|
//                                  leading: SizedBox(
 | 
						|
//                                    width: 50,
 | 
						|
//                                    child: Column(
 | 
						|
//                                      mainAxisSize: MainAxisSize.min,
 | 
						|
//                                      mainAxisAlignment:
 | 
						|
//                                          MainAxisAlignment.center,
 | 
						|
//                                      children: [
 | 
						|
//                                        SizedBox(
 | 
						|
//                                          height: 24,
 | 
						|
//                                          child: Container(
 | 
						|
//                                            padding: const EdgeInsets.symmetric(
 | 
						|
//                                              horizontal: 4,
 | 
						|
//                                            ),
 | 
						|
//                                            decoration: BoxDecoration(
 | 
						|
//                                              color:
 | 
						|
//                                                  _searchQuery.isNotEmpty
 | 
						|
//                                                      ? Colors.blue.withOpacity(
 | 
						|
//                                                        0.2,
 | 
						|
//                                                      )
 | 
						|
//                                                      : null,
 | 
						|
//                                              borderRadius:
 | 
						|
//                                                  BorderRadius.circular(4),
 | 
						|
//                                            ),
 | 
						|
//                                            child: Tooltip(
 | 
						|
//                                              message:
 | 
						|
//                                                  'Load position: $actualLoadOrderPosition of ${_activeMods.length}${_searchQuery.isNotEmpty ? " (preserved when filtering)" : ""}',
 | 
						|
//                                              child: Text(
 | 
						|
//                                                '$actualLoadOrderPosition',
 | 
						|
//                                                style: TextStyle(
 | 
						|
//                                                  fontWeight: FontWeight.bold,
 | 
						|
//                                                  fontSize: 12,
 | 
						|
//                                                  color:
 | 
						|
//                                                      _searchQuery.isNotEmpty
 | 
						|
//                                                          ? Colors.blue.shade300
 | 
						|
//                                                          : null,
 | 
						|
//                                                ),
 | 
						|
//                                              ),
 | 
						|
//                                            ),
 | 
						|
//                                          ),
 | 
						|
//                                        ),
 | 
						|
//                                        SizedBox(
 | 
						|
//                                          height: 24,
 | 
						|
//                                          child: Center(
 | 
						|
//                                            child:
 | 
						|
//                                                mod.size > 0
 | 
						|
//                                                    ? Tooltip(
 | 
						|
//                                                      message:
 | 
						|
//                                                          'This mod contains ${mod.size} files.',
 | 
						|
//                                                      child: Text(
 | 
						|
//                                                        '${mod.size}',
 | 
						|
//                                                        style: const TextStyle(
 | 
						|
//                                                          fontSize: 10,
 | 
						|
//                                                          color: Colors.grey,
 | 
						|
//                                                        ),
 | 
						|
//                                                      ),
 | 
						|
//                                                    )
 | 
						|
//                                                    : const SizedBox(),
 | 
						|
//                                          ),
 | 
						|
//                                        ),
 | 
						|
//                                      ],
 | 
						|
//                                    ),
 | 
						|
//                                  ),
 | 
						|
//                                  title: Text(mod.name),
 | 
						|
//                                  subtitle: Text(
 | 
						|
//                                    mod.id,
 | 
						|
//                                    style: const TextStyle(fontSize: 12),
 | 
						|
//                                  ),
 | 
						|
//                                  trailing: Row(
 | 
						|
//                                    mainAxisSize: MainAxisSize.min,
 | 
						|
//                                    children: [
 | 
						|
//                                      if (mod.isBaseGame)
 | 
						|
//                                        const Tooltip(
 | 
						|
//                                          message: 'Base Game',
 | 
						|
//                                          child: Icon(
 | 
						|
//                                            Icons.home,
 | 
						|
//                                            color: Colors.blue,
 | 
						|
//                                            size: 24,
 | 
						|
//                                          ),
 | 
						|
//                                        ),
 | 
						|
//                                      if (mod.isExpansion)
 | 
						|
//                                        const Tooltip(
 | 
						|
//                                          message: 'Expansion',
 | 
						|
//                                          child: Icon(
 | 
						|
//                                            Icons.star,
 | 
						|
//                                            color: Colors.yellow,
 | 
						|
//                                            size: 24,
 | 
						|
//                                          ),
 | 
						|
//                                        ),
 | 
						|
//                                      if (mod.dependencies.isNotEmpty)
 | 
						|
//                                        Tooltip(
 | 
						|
//                                          message:
 | 
						|
//                                              'Dependencies:\n${mod.dependencies.join('\n')}',
 | 
						|
//                                          child: const Icon(
 | 
						|
//                                            Icons.link,
 | 
						|
//                                            color: Colors.orange,
 | 
						|
//                                            size: 24,
 | 
						|
//                                          ),
 | 
						|
//                                        ),
 | 
						|
//                                      const SizedBox(width: 4),
 | 
						|
//                                      if (mod.loadAfter.isNotEmpty)
 | 
						|
//                                        Tooltip(
 | 
						|
//                                          message:
 | 
						|
//                                              'Loads after other mods:\n${mod.loadAfter.join('\n')}',
 | 
						|
//                                          child: const Icon(
 | 
						|
//                                            Icons.arrow_downward,
 | 
						|
//                                            color: Colors.blue,
 | 
						|
//                                            size: 24,
 | 
						|
//                                          ),
 | 
						|
//                                        ),
 | 
						|
//                                      const SizedBox(width: 4),
 | 
						|
//                                      if (mod.loadBefore.isNotEmpty)
 | 
						|
//                                        Tooltip(
 | 
						|
//                                          message:
 | 
						|
//                                              'Loads before other mods:\n${mod.loadBefore.join('\n')}',
 | 
						|
//                                          child: const Icon(
 | 
						|
//                                            Icons.arrow_upward,
 | 
						|
//                                            color: Colors.green,
 | 
						|
//                                            size: 24,
 | 
						|
//                                          ),
 | 
						|
//                                        ),
 | 
						|
//                                    ],
 | 
						|
//                                  ),
 | 
						|
//                                  onTap: () {
 | 
						|
//                                    // Show mod details in future
 | 
						|
//                                  },
 | 
						|
//                                ),
 | 
						|
//                              ),
 | 
						|
//                            );
 | 
						|
//                          },
 | 
						|
//                        ),
 | 
						|
//                      ),
 | 
						|
//                    ],
 | 
						|
//                  ),
 | 
						|
//                ),
 | 
						|
//              ),
 | 
						|
//            ],
 | 
						|
//          ),
 | 
						|
//        ),
 | 
						|
//      ],
 | 
						|
//    );
 | 
						|
//  }
 | 
						|
//
 | 
						|
//  void _startLoadingMods() {
 | 
						|
//    setState(() {
 | 
						|
//      _availableMods.clear();
 | 
						|
//      _activeMods.clear();
 | 
						|
//      _isLoading = true;
 | 
						|
//      _statusMessage = 'Scanning for mods...';
 | 
						|
//      _hasCycles = false;
 | 
						|
//      _cycleInfo = null;
 | 
						|
//      _incompatibleMods = [];
 | 
						|
//    });
 | 
						|
//
 | 
						|
//    // Create an async function to load mods
 | 
						|
//    Future<void> loadMods() async {
 | 
						|
//      try {
 | 
						|
//        // First load available mods
 | 
						|
//        await for (final mod in modManager.loadAvailable()) {
 | 
						|
//          // Update UI for each mod loaded
 | 
						|
//          if (mounted) {
 | 
						|
//            setState(() {
 | 
						|
//              _statusMessage = 'Loaded mod: ${mod.name}';
 | 
						|
//              _totalModsFound = modManager.mods.length;
 | 
						|
//            });
 | 
						|
//          }
 | 
						|
//        }
 | 
						|
//
 | 
						|
//        // Then load active mods from config
 | 
						|
//        await for (final mod in modManager.loadActive()) {
 | 
						|
//          // Update UI as active mods are loaded
 | 
						|
//          if (mounted) {
 | 
						|
//            setState(() {
 | 
						|
//              _statusMessage = 'Loading active mod: ${mod.name}';
 | 
						|
//            });
 | 
						|
//          }
 | 
						|
//        }
 | 
						|
//
 | 
						|
//        // Update the UI with all loaded mods
 | 
						|
//        if (mounted) {
 | 
						|
//          _loadModsFromGlobalState();
 | 
						|
//          setState(() {
 | 
						|
//            _statusMessage =
 | 
						|
//                'Loaded ${_availableMods.length} mods, ${_activeMods.length} active';
 | 
						|
//          });
 | 
						|
//        }
 | 
						|
//      } catch (error) {
 | 
						|
//        if (mounted) {
 | 
						|
//          setState(() {
 | 
						|
//            _isLoading = false;
 | 
						|
//            _statusMessage = 'Error loading mods: $error';
 | 
						|
//          });
 | 
						|
//        }
 | 
						|
//      }
 | 
						|
//    }
 | 
						|
//
 | 
						|
//    // Start the loading process
 | 
						|
//    loadMods();
 | 
						|
//  }
 | 
						|
//
 | 
						|
//  void _toggleModActive(Mod mod) {
 | 
						|
//    // Cannot deactivate base game or expansions
 | 
						|
//    if ((mod.isBaseGame || mod.isExpansion) && mod.enabled) {
 | 
						|
//      ScaffoldMessenger.of(context).showSnackBar(
 | 
						|
//        const SnackBar(
 | 
						|
//          content: Text('Core game and expansions cannot be deactivated'),
 | 
						|
//          backgroundColor: Colors.orange,
 | 
						|
//        ),
 | 
						|
//      );
 | 
						|
//      return;
 | 
						|
//    }
 | 
						|
//
 | 
						|
//    // Get the current state before toggling
 | 
						|
//    final bool wasEnabled = mod.enabled;
 | 
						|
//
 | 
						|
//    // Toggle the mod in the global mod manager
 | 
						|
//    modManager.setEnabled(mod.id, !wasEnabled);
 | 
						|
//    Logger.instance.info(
 | 
						|
//      'Toggled mod ${mod.name} (${mod.id}) from ${wasEnabled ? 'enabled' : 'disabled'} to ${!wasEnabled ? 'enabled' : 'disabled'}',
 | 
						|
//    );
 | 
						|
//
 | 
						|
//    // Update the UI
 | 
						|
//    setState(() {
 | 
						|
//      // Update in the available mods list
 | 
						|
//      final index = _availableMods.indexWhere((m) => m.id == mod.id);
 | 
						|
//      if (index >= 0) {
 | 
						|
//        _availableMods[index] = modManager.mods[mod.id]!;
 | 
						|
//      }
 | 
						|
//
 | 
						|
//      // Update the active mods list
 | 
						|
//      _activeMods = modManager.mods.values.where((m) => m.enabled).toList();
 | 
						|
//
 | 
						|
//      _statusMessage =
 | 
						|
//          'Mod "${mod.name}" ${!wasEnabled ? 'activated' : 'deactivated'}';
 | 
						|
//    });
 | 
						|
//  }
 | 
						|
//
 | 
						|
//  void _sortActiveMods() async {
 | 
						|
//    if (_activeMods.isEmpty) {
 | 
						|
//      setState(() {
 | 
						|
//        _statusMessage = 'No active mods to sort';
 | 
						|
//      });
 | 
						|
//      return;
 | 
						|
//    }
 | 
						|
//
 | 
						|
//    setState(() {
 | 
						|
//      _isLoading = true;
 | 
						|
//      _statusMessage = 'Sorting mods based on dependencies...';
 | 
						|
//      _hasCycles = false;
 | 
						|
//      _cycleInfo = null;
 | 
						|
//      _incompatibleMods = [];
 | 
						|
//      _loadOrderErrors = null;
 | 
						|
//    });
 | 
						|
//
 | 
						|
//    // Use a Future.delayed to allow the UI to update
 | 
						|
//    await Future.delayed(Duration.zero);
 | 
						|
//
 | 
						|
//    try {
 | 
						|
//      final logger = Logger.instance;
 | 
						|
//      logger.info('Starting auto-sort of ${_activeMods.length} active mods');
 | 
						|
//
 | 
						|
//      // Generate a load order for active mods
 | 
						|
//      final loadOrder = modManager.generateLoadOrder();
 | 
						|
//
 | 
						|
//      // Store all errors
 | 
						|
//      if (loadOrder.hasErrors) {
 | 
						|
//        setState(() {
 | 
						|
//          _loadOrderErrors = List<String>.from(loadOrder.errors);
 | 
						|
//        });
 | 
						|
//
 | 
						|
//        logger.warning(
 | 
						|
//          'Found ${loadOrder.errors.length} errors during sorting',
 | 
						|
//        );
 | 
						|
//        for (final error in loadOrder.errors) {
 | 
						|
//          logger.warning('  - $error');
 | 
						|
//        }
 | 
						|
//
 | 
						|
//        setState(() {
 | 
						|
//          _hasCycles = loadOrder.errors.any(
 | 
						|
//            (e) => e.contains('Cyclic dependency'),
 | 
						|
//          );
 | 
						|
//          if (_hasCycles) {
 | 
						|
//            // Extract cycle info from error message
 | 
						|
//            final cycleError = loadOrder.errors.firstWhere(
 | 
						|
//              (e) => e.contains('Cyclic dependency'),
 | 
						|
//              orElse: () => '',
 | 
						|
//            );
 | 
						|
//            logger.warning('Detected dependency cycle: $cycleError');
 | 
						|
//
 | 
						|
//            if (cycleError.isNotEmpty) {
 | 
						|
//              // Extract cycle path from error message
 | 
						|
//              final startIndex = cycleError.indexOf(':');
 | 
						|
//              if (startIndex != -1) {
 | 
						|
//                final pathStr = cycleError.substring(startIndex + 1).trim();
 | 
						|
//                _cycleInfo = pathStr.split(' -> ');
 | 
						|
//                logger.info(
 | 
						|
//                  'Extracted cycle path: ${_cycleInfo!.join(" -> ")}',
 | 
						|
//                );
 | 
						|
//              }
 | 
						|
//            }
 | 
						|
//          }
 | 
						|
//        });
 | 
						|
//      } else {
 | 
						|
//        _loadOrderErrors = null;
 | 
						|
//      }
 | 
						|
//
 | 
						|
//      // Check for incompatibilities
 | 
						|
//      _incompatibleMods = modManager.checkIncompatibilities(
 | 
						|
//        modManager.activeMods.keys.toList(),
 | 
						|
//      );
 | 
						|
//
 | 
						|
//      if (_incompatibleMods.isNotEmpty) {
 | 
						|
//        logger.warning(
 | 
						|
//          'Found ${_incompatibleMods.length} incompatible mod pairs:',
 | 
						|
//        );
 | 
						|
//        for (final pair in _incompatibleMods) {
 | 
						|
//          final mod1 = modManager.mods[pair[0]]?.name ?? pair[0];
 | 
						|
//          final mod2 = modManager.mods[pair[1]]?.name ?? pair[1];
 | 
						|
//          logger.warning('  - $mod1 is incompatible with $mod2');
 | 
						|
//        }
 | 
						|
//      }
 | 
						|
//
 | 
						|
//      // Get sorted mods from the load order
 | 
						|
//      final List<Mod> sortedMods = [];
 | 
						|
//      for (final modId in loadOrder.loadOrder) {
 | 
						|
//        if (modManager.mods.containsKey(modId)) {
 | 
						|
//          sortedMods.add(modManager.mods[modId]!);
 | 
						|
//        }
 | 
						|
//      }
 | 
						|
//
 | 
						|
//      logger.info(
 | 
						|
//        'Sorting complete. Arranged ${sortedMods.length} mods in load order',
 | 
						|
//      );
 | 
						|
//      if (sortedMods.isNotEmpty) {
 | 
						|
//        logger.info(
 | 
						|
//          'First 5 mods in order: ${sortedMods.take(5).map((m) => m.name).join(', ')}',
 | 
						|
//        );
 | 
						|
//        if (sortedMods.length > 5) {
 | 
						|
//          logger.info('... (${sortedMods.length - 5} more) ...');
 | 
						|
//          logger.info(
 | 
						|
//            'Last 3 mods in order: ${sortedMods.reversed.take(3).map((m) => m.name).toList().reversed.join(', ')}',
 | 
						|
//          );
 | 
						|
//        }
 | 
						|
//      }
 | 
						|
//
 | 
						|
//      setState(() {
 | 
						|
//        _activeMods = sortedMods;
 | 
						|
//        _isLoading = false;
 | 
						|
//        _statusMessage = 'Sorting complete! ${sortedMods.length} mods sorted.';
 | 
						|
//        if (_hasCycles) {
 | 
						|
//          _statusMessage += ' Warning: Dependency cycles were found and fixed.';
 | 
						|
//        }
 | 
						|
//        if (_incompatibleMods.isNotEmpty) {
 | 
						|
//          _statusMessage +=
 | 
						|
//              ' Warning: ${_incompatibleMods.length} incompatible mod pairs found.';
 | 
						|
//        }
 | 
						|
//      });
 | 
						|
//    } catch (e) {
 | 
						|
//      Logger.instance.error('Error during auto-sort: $e');
 | 
						|
//      setState(() {
 | 
						|
//        _isLoading = false;
 | 
						|
//        _statusMessage = 'Error sorting mods: $e';
 | 
						|
//      });
 | 
						|
//    }
 | 
						|
//  }
 | 
						|
//
 | 
						|
//  void _saveModOrder() async {
 | 
						|
//    if (_activeMods.isEmpty) {
 | 
						|
//      setState(() {
 | 
						|
//        _statusMessage = 'No active mods to save';
 | 
						|
//      });
 | 
						|
//      return;
 | 
						|
//    }
 | 
						|
//
 | 
						|
//    setState(() {
 | 
						|
//      _isLoading = true;
 | 
						|
//      _statusMessage = 'Saving mod load order...';
 | 
						|
//    });
 | 
						|
//
 | 
						|
//    try {
 | 
						|
//      final logger = Logger.instance;
 | 
						|
//      logger.info(
 | 
						|
//        'Saving mod load order for ${_activeMods.length} active mods to $configPath',
 | 
						|
//      );
 | 
						|
//
 | 
						|
//      // Save the mod list to the XML config file
 | 
						|
//      final file = File(configPath);
 | 
						|
//      final buffer = StringBuffer();
 | 
						|
//
 | 
						|
//      buffer.writeln('<?xml version="1.0" encoding="utf-8"?>');
 | 
						|
//      buffer.writeln('<ModsConfigData>');
 | 
						|
//      buffer.writeln('  <version>1</version>');
 | 
						|
//
 | 
						|
//      // Write active mods
 | 
						|
//      buffer.writeln('  <activeMods>');
 | 
						|
//      for (final mod in _activeMods) {
 | 
						|
//        buffer.writeln('    <li>${mod.id}</li>');
 | 
						|
//        logger.info('  - Adding mod to config: ${mod.name} (${mod.id})');
 | 
						|
//      }
 | 
						|
//      buffer.writeln('  </activeMods>');
 | 
						|
//
 | 
						|
//      // Count expansions
 | 
						|
//      final expansions = _availableMods.where((m) => m.isExpansion).toList();
 | 
						|
//      logger.info('Found ${expansions.length} expansions to include in config');
 | 
						|
//
 | 
						|
//      // Add known expansions
 | 
						|
//      buffer.writeln('  <knownExpansions>');
 | 
						|
//      for (final mod in expansions) {
 | 
						|
//        buffer.writeln('    <li>${mod.id}</li>');
 | 
						|
//        logger.info('  - Adding expansion to config: ${mod.name} (${mod.id})');
 | 
						|
//      }
 | 
						|
//      buffer.writeln('  </knownExpansions>');
 | 
						|
//
 | 
						|
//      buffer.writeln('</ModsConfigData>');
 | 
						|
//
 | 
						|
//      // Ensure directory exists
 | 
						|
//      final directory = Directory(configRoot);
 | 
						|
//      if (!directory.existsSync()) {
 | 
						|
//        logger.info('Creating config directory: $configRoot');
 | 
						|
//        directory.createSync(recursive: true);
 | 
						|
//      }
 | 
						|
//
 | 
						|
//      // Write to file
 | 
						|
//      logger.info('Writing config file to $configPath');
 | 
						|
//      await file.writeAsString(buffer.toString());
 | 
						|
//      logger.info('Successfully saved mod configuration');
 | 
						|
//
 | 
						|
//      setState(() {
 | 
						|
//        _isLoading = false;
 | 
						|
//        _statusMessage = 'Mod load order saved successfully!';
 | 
						|
//      });
 | 
						|
//
 | 
						|
//      // Show success message
 | 
						|
//      ScaffoldMessenger.of(context).showSnackBar(
 | 
						|
//        SnackBar(
 | 
						|
//          content: Text(
 | 
						|
//            'Mod order saved to config. ${_activeMods.length} mods enabled.',
 | 
						|
//          ),
 | 
						|
//          backgroundColor: Colors.green,
 | 
						|
//        ),
 | 
						|
//      );
 | 
						|
//    } catch (e) {
 | 
						|
//      final logger = Logger.instance;
 | 
						|
//      logger.error('Error saving mod load order: $e');
 | 
						|
//
 | 
						|
//      setState(() {
 | 
						|
//        _isLoading = false;
 | 
						|
//        _statusMessage = 'Error saving mod load order: $e';
 | 
						|
//      });
 | 
						|
//
 | 
						|
//      // Show error message
 | 
						|
//      ScaffoldMessenger.of(context).showSnackBar(
 | 
						|
//        SnackBar(
 | 
						|
//          content: Text('Error saving mod order: $e'),
 | 
						|
//          backgroundColor: Colors.red,
 | 
						|
//        ),
 | 
						|
//      );
 | 
						|
//    }
 | 
						|
//  }
 | 
						|
//
 | 
						|
//  // Load all required dependencies for active mods
 | 
						|
//  void _loadRequiredDependencies() async {
 | 
						|
//    if (_activeMods.isEmpty) {
 | 
						|
//      setState(() {
 | 
						|
//        _statusMessage = 'No active mods to load dependencies for';
 | 
						|
//      });
 | 
						|
//      return;
 | 
						|
//    }
 | 
						|
//
 | 
						|
//    setState(() {
 | 
						|
//      _isLoading = true;
 | 
						|
//      _statusMessage = 'Loading required dependencies...';
 | 
						|
//      _hasCycles = false;
 | 
						|
//      _cycleInfo = null;
 | 
						|
//      _incompatibleMods = [];
 | 
						|
//      _loadOrderErrors = null;
 | 
						|
//    });
 | 
						|
//
 | 
						|
//    // Use a Future.delayed to allow the UI to update
 | 
						|
//    await Future.delayed(Duration.zero);
 | 
						|
//
 | 
						|
//    try {
 | 
						|
//      final logger = Logger.instance;
 | 
						|
//      logger.info(
 | 
						|
//        'Starting dependency resolution for ${_activeMods.length} active mods',
 | 
						|
//      );
 | 
						|
//
 | 
						|
//      // Get current active mod count for comparison
 | 
						|
//      final initialActiveCount = modManager.activeMods.length;
 | 
						|
//
 | 
						|
//      // Load required dependencies and get the load order
 | 
						|
//      final loadOrder = modManager.loadRequired();
 | 
						|
//
 | 
						|
//      // Store any errors
 | 
						|
//      if (loadOrder.hasErrors) {
 | 
						|
//        setState(() {
 | 
						|
//          _loadOrderErrors = List<String>.from(loadOrder.errors);
 | 
						|
//        });
 | 
						|
//
 | 
						|
//        logger.warning(
 | 
						|
//          'Found ${loadOrder.errors.length} errors during dependency loading',
 | 
						|
//        );
 | 
						|
//        for (final error in loadOrder.errors) {
 | 
						|
//          logger.warning('  - $error');
 | 
						|
//        }
 | 
						|
//
 | 
						|
//        // Check for cycles
 | 
						|
//        setState(() {
 | 
						|
//          _hasCycles = loadOrder.errors.any(
 | 
						|
//            (e) => e.contains('Cyclic dependency'),
 | 
						|
//          );
 | 
						|
//          if (_hasCycles) {
 | 
						|
//            // Extract cycle info from error message
 | 
						|
//            final cycleError = loadOrder.errors.firstWhere(
 | 
						|
//              (e) => e.contains('Cyclic dependency'),
 | 
						|
//              orElse: () => '',
 | 
						|
//            );
 | 
						|
//            logger.warning('Detected dependency cycle: $cycleError');
 | 
						|
//
 | 
						|
//            if (cycleError.isNotEmpty) {
 | 
						|
//              // Extract cycle path from error message
 | 
						|
//              final startIndex = cycleError.indexOf(':');
 | 
						|
//              if (startIndex != -1) {
 | 
						|
//                final pathStr = cycleError.substring(startIndex + 1).trim();
 | 
						|
//                _cycleInfo = pathStr.split(' -> ');
 | 
						|
//                logger.info(
 | 
						|
//                  'Extracted cycle path: ${_cycleInfo!.join(" -> ")}',
 | 
						|
//                );
 | 
						|
//              }
 | 
						|
//            }
 | 
						|
//          }
 | 
						|
//        });
 | 
						|
//      } else {
 | 
						|
//        _loadOrderErrors = null;
 | 
						|
//      }
 | 
						|
//
 | 
						|
//      // Check for incompatibilities
 | 
						|
//      _incompatibleMods = modManager.checkIncompatibilities(
 | 
						|
//        modManager.activeMods.keys.toList(),
 | 
						|
//      );
 | 
						|
//
 | 
						|
//      if (_incompatibleMods.isNotEmpty) {
 | 
						|
//        logger.warning(
 | 
						|
//          'Found ${_incompatibleMods.length} incompatible mod pairs:',
 | 
						|
//        );
 | 
						|
//        for (final pair in _incompatibleMods) {
 | 
						|
//          final mod1 = modManager.mods[pair[0]]?.name ?? pair[0];
 | 
						|
//          final mod2 = modManager.mods[pair[1]]?.name ?? pair[1];
 | 
						|
//          logger.warning('  - $mod1 is incompatible with $mod2');
 | 
						|
//        }
 | 
						|
//      }
 | 
						|
//
 | 
						|
//      // Get sorted mods from the load order
 | 
						|
//      final List<Mod> sortedMods = [];
 | 
						|
//      for (final modId in loadOrder.loadOrder) {
 | 
						|
//        if (modManager.mods.containsKey(modId)) {
 | 
						|
//          sortedMods.add(modManager.mods[modId]!);
 | 
						|
//        }
 | 
						|
//      }
 | 
						|
//
 | 
						|
//      // Calculate how many dependencies were added
 | 
						|
//      final newModsCount = modManager.activeMods.length - initialActiveCount;
 | 
						|
//
 | 
						|
//      logger.info(
 | 
						|
//        'Dependency loading complete. Enabled $newModsCount new dependencies.',
 | 
						|
//      );
 | 
						|
//      if (newModsCount > 0) {
 | 
						|
//        logger.info('Newly enabled dependencies:');
 | 
						|
//        final activeModIds = modManager.activeMods.keys.toList();
 | 
						|
//        for (int i = 0; i < newModsCount; i++) {
 | 
						|
//          final modId = activeModIds[initialActiveCount + i];
 | 
						|
//          logger.info('  - ${modManager.mods[modId]?.name ?? modId} ($modId)');
 | 
						|
//        }
 | 
						|
//      }
 | 
						|
//
 | 
						|
//      setState(() {
 | 
						|
//        _activeMods = sortedMods;
 | 
						|
//        _isLoading = false;
 | 
						|
//        if (newModsCount > 0) {
 | 
						|
//          _statusMessage = 'Added $newModsCount required dependencies!';
 | 
						|
//        } else {
 | 
						|
//          _statusMessage = 'All dependencies are already loaded.';
 | 
						|
//        }
 | 
						|
//
 | 
						|
//        if (_hasCycles) {
 | 
						|
//          _statusMessage += ' Warning: Dependency cycles were found and fixed.';
 | 
						|
//        }
 | 
						|
//        if (_incompatibleMods.isNotEmpty) {
 | 
						|
//          _statusMessage +=
 | 
						|
//              ' Warning: ${_incompatibleMods.length} incompatible mod pairs found.';
 | 
						|
//        }
 | 
						|
//      });
 | 
						|
//    } catch (e) {
 | 
						|
//      Logger.instance.error('Error during dependency loading: $e');
 | 
						|
//      setState(() {
 | 
						|
//        _isLoading = false;
 | 
						|
//        _statusMessage = 'Error loading dependencies: $e';
 | 
						|
//      });
 | 
						|
//    }
 | 
						|
//  }
 | 
						|
//}
 | 
						|
//
 | 
						|
//// Page for troubleshooting problematic mods
 | 
						|
//class TroubleshootingPage extends StatelessWidget {
 | 
						|
//  const TroubleshootingPage({super.key});
 | 
						|
//
 | 
						|
//  @override
 | 
						|
//  Widget build(BuildContext context) {
 | 
						|
//    return Center(
 | 
						|
//      child: Column(
 | 
						|
//        mainAxisAlignment: MainAxisAlignment.center,
 | 
						|
//        children: [
 | 
						|
//          const Icon(Icons.build, size: 64),
 | 
						|
//          const SizedBox(height: 16),
 | 
						|
//          Text(
 | 
						|
//            'Troubleshooting',
 | 
						|
//            style: Theme.of(context).textTheme.headlineMedium,
 | 
						|
//          ),
 | 
						|
//          const SizedBox(height: 16),
 | 
						|
//          Padding(
 | 
						|
//            padding: const EdgeInsets.symmetric(horizontal: 32.0),
 | 
						|
//            child: Text(
 | 
						|
//              'Find problematic mods with smart batch testing.',
 | 
						|
//              style: Theme.of(context).textTheme.bodyLarge,
 | 
						|
//              textAlign: TextAlign.center,
 | 
						|
//            ),
 | 
						|
//          ),
 | 
						|
//          const SizedBox(height: 24),
 | 
						|
//          ElevatedButton(
 | 
						|
//            onPressed: () {
 | 
						|
//              // TODO: Implement troubleshooting wizard
 | 
						|
//            },
 | 
						|
//            child: const Text('Start Troubleshooting'),
 | 
						|
//          ),
 | 
						|
//        ],
 | 
						|
//      ),
 | 
						|
//    );
 | 
						|
//  }
 | 
						|
//}
 | 
						|
// |