diff --git a/lib/main.dart b/lib/main.dart index b8cdfb4..653a208 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1325,47 +1325,7 @@ class _ModManagerPageState extends State { '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(''); - buffer.writeln(''); - buffer.writeln(' 1'); - - // Write active mods - buffer.writeln(' '); - for (final mod in _activeMods) { - buffer.writeln('
  • ${mod.id}
  • '); - logger.info(' - Adding mod to config: ${mod.name} (${mod.id})'); - } - buffer.writeln('
    '); - - // 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(' '); - for (final mod in expansions) { - buffer.writeln('
  • ${mod.id}
  • '); - logger.info(' - Adding expansion to config: ${mod.name} (${mod.id})'); - } - buffer.writeln('
    '); - - buffer.writeln('
    '); - - // 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'); + modManager.saveToConfig(LoadOrder(_activeMods)); setState(() { _isLoading = false; diff --git a/lib/mod_list.dart b/lib/mod_list.dart index 3db8812..5427aca 100644 --- a/lib/mod_list.dart +++ b/lib/mod_list.dart @@ -13,7 +13,9 @@ class LoadOrder { return order.map((mod) => mod.id).toList(); } - LoadOrder(); + LoadOrder([List? order]) { + this.order = order ?? []; + } bool get hasErrors => errors.isNotEmpty; } @@ -204,6 +206,66 @@ class ModList { } } + void saveToConfig(LoadOrder loadOrder) { + final file = File(configPath); + final logger = Logger.instance; + + try { + // Create XML builder + final builder = XmlBuilder(); + + // Add XML declaration + builder.declaration(encoding: 'utf-8'); + + // Add root element + builder.element( + 'ModsConfigData', + nest: () { + // Add version element + builder.element('version', nest: '1.5.4297 rev994'); + + // Add active mods element + builder.element( + 'activeMods', + nest: () { + // Add each mod as a list item + for (final mod in loadOrder.order) { + builder.element('li', nest: mod.id); + logger.info('Adding mod to config: ${mod.name} (${mod.id})'); + } + }, + ); + + // Add known expansions element + final expansions = mods.values.where((m) => m.isExpansion).toList(); + if (expansions.isNotEmpty) { + builder.element( + 'knownExpansions', + nest: () { + for (final mod in expansions) { + builder.element('li', nest: mod.id); + logger.info( + 'Adding expansion to config: ${mod.name} (${mod.id})', + ); + } + }, + ); + } + }, + ); + + // Build the XML document + final xmlDocument = builder.buildDocument(); + + // Write the XML document to file + file.writeAsStringSync(xmlDocument.toString()); + logger.info('Successfully saved mod configuration to: $configPath'); + } catch (e) { + logger.error('Error saving configuration file: $e'); + throw Exception('Failed to save config file: $e'); + } + } + void setEnabled(String modId, bool enabled) { if (mods.containsKey(modId)) { final mod = mods[modId]!; diff --git a/lib/mod_troubleshooter_widget.dart b/lib/mod_troubleshooter_widget.dart index 8e6b262..8fba710 100644 --- a/lib/mod_troubleshooter_widget.dart +++ b/lib/mod_troubleshooter_widget.dart @@ -34,7 +34,7 @@ class _ModTroubleshooterWidgetState extends State { final Set _problemMods = {}; // The currently selected mod IDs (for highlighting) - List _selectedMods = []; + LoadOrder _loadOrder = LoadOrder(); // The next potential set of mods (from move calculation) Move? _nextForwardMove; @@ -64,7 +64,7 @@ class _ModTroubleshooterWidgetState extends State { // Set initial active mods for highlighting if (modManager.activeMods.isNotEmpty) { // Initially select all active mods - _selectedMods = List.from(modManager.activeMods.keys); + _loadOrder = LoadOrder(modManager.activeMods.values.toList()); } // Calculate initial moves @@ -100,7 +100,7 @@ class _ModTroubleshooterWidgetState extends State { // Use the mods from the load order result setState(() { - _selectedMods = loadOrder.loadOrder; + _loadOrder = loadOrder; _updateNextMoves(); }); } @@ -118,7 +118,7 @@ class _ModTroubleshooterWidgetState extends State { // Use the mods from the load order result setState(() { - _selectedMods = loadOrder.loadOrder; + _loadOrder = loadOrder; _updateNextMoves(); }); } @@ -155,7 +155,7 @@ class _ModTroubleshooterWidgetState extends State { void _saveTroubleshootingConfig() { // Only save if we have a valid selection - if (_selectedMods.isEmpty) { + if (_loadOrder.order.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('No mods selected to save'), @@ -165,17 +165,13 @@ class _ModTroubleshooterWidgetState extends State { return; } - // First disable all mods - modManager.disableAll(); - - // Then enable only the selected mods - modManager.enableMods(_selectedMods); + modManager.saveToConfig(_loadOrder); // Save the configuration (we don't have direct access to save method, so show a message) ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( - '${_selectedMods.length} mods prepared for testing. Please use Save button in the Mods tab to save config.', + '${_loadOrder.order.length} mods prepared for testing. Please use Save button in the Mods tab to save config.', ), backgroundColor: Colors.orange, duration: const Duration(seconds: 4), @@ -184,7 +180,7 @@ class _ModTroubleshooterWidgetState extends State { } void _markSelectedAsGood() { - if (_selectedMods.isEmpty) { + if (_loadOrder.order.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('No mods selected to mark'), @@ -195,15 +191,15 @@ class _ModTroubleshooterWidgetState extends State { } setState(() { - for (final modId in _selectedMods) { - _checkedMods.add(modId); - _problemMods.remove(modId); + for (final mod in _loadOrder.order) { + _checkedMods.add(mod.id); + _problemMods.remove(mod.id); } }); ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text('Marked ${_selectedMods.length} mods as good'), + content: Text('Marked ${_loadOrder.order.length} mods as good'), backgroundColor: Colors.green, duration: const Duration(seconds: 2), ), @@ -211,7 +207,7 @@ class _ModTroubleshooterWidgetState extends State { } void _markSelectedAsProblem() { - if (_selectedMods.isEmpty) { + if (_loadOrder.order.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('No mods selected to mark'), @@ -222,15 +218,15 @@ class _ModTroubleshooterWidgetState extends State { } setState(() { - for (final modId in _selectedMods) { - _problemMods.add(modId); - _checkedMods.remove(modId); + for (final mod in _loadOrder.order) { + _problemMods.add(mod.id); + _checkedMods.remove(mod.id); } }); ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text('Marked ${_selectedMods.length} mods as problematic'), + content: Text('Marked ${_loadOrder.order.length} mods as problematic'), backgroundColor: Colors.orange, duration: const Duration(seconds: 2), ), @@ -307,8 +303,8 @@ class _ModTroubleshooterWidgetState extends State { // Compact instruction Expanded( child: Text( - _selectedMods.isNotEmpty - ? 'Testing ${_selectedMods.length} mods. Tap highlighted mods to navigate. Mark results below:' + _loadOrder.order.isNotEmpty + ? 'Testing ${_loadOrder.order.length} mods. Tap highlighted mods to navigate. Mark results below:' : 'Click highlighted mods to begin testing. Blue→forward, purple←backward.', style: TextStyle( fontSize: AppThemeExtension.of(context).textSizeRegular, @@ -379,7 +375,7 @@ class _ModTroubleshooterWidgetState extends State { const Spacer(), // Buttons to mark selected mods - if (_selectedMods.isNotEmpty) ...[ + if (_loadOrder.order.isNotEmpty) ...[ OutlinedButton.icon( icon: Icon( Icons.error, @@ -427,7 +423,7 @@ class _ModTroubleshooterWidgetState extends State { onPressed: _resetTroubleshooter, ), - if (_selectedMods.isNotEmpty) ...[ + if (_loadOrder.order.isNotEmpty) ...[ const SizedBox(width: 4), // Save config button OutlinedButton.icon( @@ -492,7 +488,9 @@ class _ModTroubleshooterWidgetState extends State { if (mod == null) return const SizedBox.shrink(); // Determine if this mod is in the selection range for highlighted navigation - final bool isSelected = _selectedMods.contains(modId); + final bool isSelected = _loadOrder.order.any( + (m) => m.id == modId, + ); // Check if this mod would be included in the next Forward/Backward move bool isInNextForward = false;